News Forums RAIN General Discussion and Troubleshooting ai.Senses.GetSensor(s) causes Unity Editor crash

This topic contains 10 replies, has 2 voices, and was last updated by  Saurian 10 months, 2 weeks ago.

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
  • #35515


    Hey, I updated to v. 2.8.0 and just wrote a bunch of new code to go with the Perception overhauls. I previously had no problem caching a visual sensor with GetSensor(“visual”), but when I try now from calling ai.Senses I’m encountering a problem.
    My first attempt was with:

    this.sensor = ai.Senses.GetSensor("visual") as VisualSensor;

    which created a null reference exception, but didn’t crash the editor. I realized that you now call GetSensor with the sensor name (“Visual Sensor”) as argument, rather than type (“visual”). So I changed it to:

    this.sensor = ai.Senses.GetSensor("Visual Sensor") as VisualSensor;

    and this caused the editor crash. I tried referencing the sensor a different way, through:

    this.sensor = ai.Senses.GetSensors(null, true)[0] as VisualSensor;

    but it causes the same crash.
    Since the editor crashes, I can’t really get much debug info. Is there a possibility that this is somehow causing an infinite loop? If it’s a problem with v 2.8.0, do you have any suggestions for a hotfix?



    The GetSensors code didn’t change (nor did any of the existing calls in BasicSenses), so I don’t think that’s the problem. What is “this” in your code, and what is the “sensor” field you are assigning to? Is it a simple variable, or is it a Property?



    Sigil mentioned that you are using custom sensors. We did start using a new base class for visual and audio sensors. That still shouldn’t impact the GetSensors method of BasicSenses, but feel free to share or send over your custom sensor code and I can take a look.

    • This reply was modified 10 months, 2 weeks ago by  prime.


    this.sensor is a variable (VisualSensor sensor, with ‘this’ being the class inheriting RAINAction) — could that be the source of the problem? I’m not using a custom sensor, but I wrote a custom action to replace a Detect node since the “Match All” wasn’t working properly (only “Best Match”).

    • This reply was modified 10 months, 2 weeks ago by  Saurian.


    Real quick:

    Match All returns a list of matches. It isn’t all that useful in the behavior tree directly, but can be useful from custom code.

    Best Match returns the single best match based on the sensor. For Visual and Audio nodes, this represents “nearest” by default. You can create sensors that use different criteria for “best”.

    Any Match returns the first matching aspect based on their ordering in the sensor manager. This is essentially arbitrary.

    Consistent means that the Detect node will attempt to keep returning the same value that it matched previously (or whatever value is already stored in the variable that you pass in.) Essentially, the Detect node retains an item in memory until it is no longer detected. This is useful when doing Best Match so that your detect doesn’t constantly switch objects as things move around.



    Still not sure what would be causing the Unity crash. Can you pass along the code for your custom action?



    Sure thing, thanks for taking a look:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Action;
    using RAIN.Core;
    using RAIN.Perception.Sensors;
    using RAIN.Entities.Aspects;
    public class SenseAnimals : RAINAction
    	protected IList<RAINAspect> animalsSensed;
    	protected string myType;
    	protected string[] animalPriorities;
    	protected RLearner learner;
    	protected SocialStatManager socialManager;
    	protected AI ai;
    	protected float visual_range;
    	protected VisualSensor sensor;
        public override void Start(RAIN.Core.AI ai)
            base.Start(ai); = ai;
    		this.sensor = ai.Senses.GetSensors(null, true)[0] as VisualSensor;
    		this.visual_range = sensor.Range;
    		this.socialManager = ai.Body.GetComponent<SocialStatManager>();
    		this.learner = ai.Body.GetComponent<RLearner>();
    		this.myType = learner.type;
    		this.animalPriorities = socialManager.animalReactionPriorities;
        public override ActionResult Execute(RAIN.Core.AI ai)
    		sensor.Sense("Animal", RAINSensor.MatchType.ALL);
    		animalsSensed = sensor.Matches;
    		ai.WorkingMemory.SetItem<GameObject>("ClosestAnimal", processAnimals(animalsSensed));
            return ActionResult.RUNNING;
        public override void Stop(RAIN.Core.AI ai)
    	protected GameObject processAnimals(IList<RAINAspect> matches){
    		int maxScore = 0;
    		RAINAspect maxAspect = null;
    		List<RAINAspect> pack = new List<RAINAspect>();
    		for(int i = 0; i < matches.Count; i++){
    			string type = matches[i].Entity.Form.GetComponent<RLearner>().type;
    			int dist = getDistanceEnum(matches[i]);
    			if(type == this.myType && dist == 2) pack.Add (matches[i]); // add to pack if same type and close
    			for(int j = 1; j < this.animalPriorities.Length; i++){
    				if(type == this.animalPriorities[j]){
    					if(j + dist >= maxScore){
    						maxScore = j+dist;
    						maxAspect = matches[i];
    					}//if priority + dist greater than current max, keep
    				}//if type is matched with animal priority index, calc total priority
    			}//for each entry in animal priorities
    		}//for each match
    		//send pack info to social manager
    		socialManager.pack = pack;
    		//return game object for placement in memory
    		return maxAspect.Entity.Form;
    	}//select animal by priority
    	public int getDistanceEnum(RAINAspect a){
    		float distance = Vector3.Distance (ai.Kinematic.Position, a.Position);
    		//if object is 2/3 to farthest from agent, return
    		//Debug.Log ( + "distance, visual range from" + type + distance.ToString() + ", " + visual_range.ToString());
    		if( distance>= visual_range/2) return 1;
    		//if within 1/3rd of sensing distance
    		if(distance <= visual_range/2) return 2;
    		else{return 0;}
    	}//get distance enum
    • This reply was modified 10 months, 2 weeks ago by  Saurian.


    Is this line your problem? (incrementing i instead of j)

    for(int j = 1; j < this.animalPriorities.Length; i++){


    D’oh! Yeah that was the problem, thanks!
    On a side note, in my previous attempt at a custom sensor I wanted to override MatchAspectName so that I would filter out aspects by additional desired qualities as aspects were being filtered by their name / line of sight (so that I didn’t have to iterate through them again later, as I’m doing in the above action) — is something like this still possible with Sense(aspectName)?



    The best way to do it is to inherit from PhysicalSensor and then just override the TestVisibility method. That’s what we do for Audio sensors. In fact, to create a custom sensor the only two methods you need to override are TestVisibility and SensedAspectType. If you are inheriting from a Visual Sensor, then only override TestVisibility:

    protected override bool TestVisibility(RAINAspect aAspect, float aSqrRange)
                if (base.TestVisibility(aAspect, aSqrRange))
                    //Do your additional checks here - fail whenever something doesn't match
                    return true;
                return false;


    Awesome, thank you so much!

Viewing 11 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic.