News Forums Search Search Results for 'tree set variable'

Viewing 15 results - 1 through 15 (of 112 total)
  • Author
    Search Results
  • #34831

    prime
    Keymaster

    That depends a lot on your behavior tree. Are you integrating that with other behaviors, or is that the main behavior of the tree?

    Regardless of exactly how you do it, the general approach would be to recognize the click, then set an AI.WorkingMemory variable that triggers the behavior in the behavior tree.

    #34809

    prime
    Keymaster

    Any changes you make to the behavior tree at runtime, including toggling the debug break option, does cause the behavior tree to reset. When it resets, it starts back at the top of the tree.

    The reason the detect isn’t nulling out the variable is that once it detects the target, it never runs again. In the sequencer, the Detect will run until it succeeds, then move on to the Move node. The Move node repeats forever, so the detect will never run again and will never get a chance to unset the variable (which is why using a parallel is necessary.)

    We’re already looking at numerous changes to the behavior editor, including limiting when the BT gets reset. Thanks for the suggestion on swapping the name of the node in the default case.

    #34766

    rainingrick
    Participant

    Continued to get odd movement!

    I watched this video (https://www.youtube.com/watch?v=YuaBBCL5PSs#t=11) and there doesn’t seem to be any character controller or rigid body used here?

    Could it be a problem with the nav mesh?

    I’ve also noticed that the minute I add a rigid body and character controller my character starts to get stuck a LOT!

    As a bit of background, I’m generating my NavMesh based on the code in this example: http://rivaltheory.com/wiki/rainelements/navmeshrig

    The general setup is:

    NavMesh
    I have several obstacles.

    My character has a behaviour tree which has a waypoint patrol variable which is set via

    aiRig.AI.WorkingMemory.SetItem<string>(“patrolRoute”, patrolName);

    The character set up is:

    Character

    Is there anyway to get source code so that I can debug!

    • This reply was modified 1 week, 6 days ago by  rainingrick.
    • This reply was modified 1 week, 6 days ago by  rainingrick.
    #34754

    In reply to: Constraints


    prime
    Keymaster

    First, you should probably use float instead of double. Especially for time.

    If you are trying to make the value of the timer variable available in AI Memory and accessible by the Behavior Tree Expressions, then you will need to do this in your custom action:

    ai.WorkingMemory.SetItem<float>("timer", timer);

    The AI mind doesn’t have a time variable. The right approach is to use WorkingMemory to store information.

    #34733

    Velathora
    Participant

    Hello all,

    I’ve been following along @CodersExpo ‘s tutorials and had no issues until the last and final tutorial.

    I seem to be having issues with the custom action and the wander.

    Basically, I am able to get the character to run at the hero, wave (instead of punch) when within the “near” detector range, and whilst within his normal patrol route, idle randomly within the timer intervals set in BT.

    Afterwards, we had been advised to get the custom action created to allow the character to wander after the Hero takes cover and removes himself from line of sight. At that point, I have the parallel node showing a failure and the waypoint path node showing a failure as well. It seems odd because it states that the execution of the previous “WanderLocation” custom action is succeeding as needed.

    For reference,

    BT:

    ->PAR-RPT:Never, Fail:Any, Succeed:Any, TieBreaker:Fail
    ->->Detect-Sensor:"eyes", Aspect:"aHero", FormVariable:varHero
    ->->Detect-Sensor:"close", Aspect:"aHero", FormVariable:varNear
    ->->Selector
    ->->->Constraint(TreeHereWorksPerfectly)
    ->->->Constraint(TreeHereWorksPerfectly)
    ->->->Constraint-Constraint:varHero == null && isSearching (shows fail)
    ->->->->Custom Action - Name:WanderLocation, Assembly:(global), Class:WanderLocation (Succeeds)
    ->->->->PAR - RPT:Never, Fail:Any, Succeed:Any, TieBreaker:Succeed (Fails)
    ->->->->->WaypointPath - WaypointNetwork:"Wander", PathTarget:varNext, MoveTargetVariable:varMoveTo (Fails)
    ->->->->->->Move-MoveTarget:varMoveTo, MoveSpeed:3 (NeverCalled)
    ->->->->->Animate - AnimationState:Walk (fails)

    Custom Action Script “WanderLocation”:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Action;
    using RAIN.Core;
    using RAIN.Navigation;
    using RAIN.Navigation.Graph;
    [RAINAction]
    public class WanderLocation : RAINAction
    {
    		private static float _time = 0f;
    		public override void Start (RAIN.Core.AI ai)
    		{
    				base.Start (ai);
    				_time += Time.time;
    		}
    		public WanderLocation ()
    		{
    				actionName = "WanderLocation";
    		}
    		public override ActionResult Execute (RAIN.Core.AI ai)
    		{
    				Vector3 loc = Vector3.zero;
    				List<RAINNavigationGraph> found = new List<RAINNavigationGraph> ();
    				do {
    						loc = new Vector3 (ai.Kinematic.Position.x + Random.Range (-8f, 8f),
    			                  ai.Kinematic.Position.y,
    			                  ai.Kinematic.Position.z + Random.Range (-8f, 8f));
    						found = NavigationManager.Instance.GraphsForPoints (ai.Kinematic.Position, 
    			                                                    loc, 
    			                                                    ai.Motor.StepUpHeight, 
    			                                                    NavigationManager.GraphType.Navmesh,
    			                                                    ((BasicNavigator)ai.Navigator).GraphTags);
    				} while((Vector3.Distance(ai.Kinematic.Position, loc)<2f)||(found.Count == 0));
    				ai.WorkingMemory.SetItem<Vector3> ("varMoveTo", loc);
    				if (_time > 5000f) {
    						ai.WorkingMemory.SetItem ("isSearching", false);
    				}
    				return ActionResult.SUCCESS;
    		}
    		public override void Stop (RAIN.Core.AI ai)
    		{
    				base.Stop (ai);
    		}
    }

    So essentially, the character will run on the spot after losing detection and is set to “isSearching”, and after 5 seconds or so, he will then return to the normal patrol route. This is unexpected behaviour, simply because he should instead be wandering around searching on the waypoint network for signs of the hero.

    Would really appreciate the assistance to wrap my head around RAIN AI.

    Cheers.

    • This topic was modified 2 weeks, 2 days ago by  Velathora. Reason: Cleaned
    • This topic was modified 2 weeks, 2 days ago by  Velathora. Reason: Clarify end
    #34628

    prime
    Keymaster

    Are you switching between two different branches of the behavior tree when you do this? In other words, do you have one WaypointPatrol node for red, and one for green?

    If so, then you get the result you want simply by using one single waypoint patrol node for both. Set the name of the patrol route into a variable, and just change the variable whenever you switch.

    The trick is to force the waypoint patrol node to completely restart. If a waypoint node exits for any reason, but then resumes later, it will attempt to start where it left off - except when the waypoint route changes. In that case it will try to determine which segment of the route it is on and resume from there. So if you force the waypoint route to change (by using one node and then switching the value of the variable) it should cause a restart and should work.

    LMK if that does it.

    #34533

    prime
    Keymaster

    I don’t think I understand your question. Maybe this will help:

    All variables that are used in a RAIN Behavior Tree come from the AI.Memory of the AI that is running the tree. So if 3 different AI are running the same behavior tree, they will each have their own variables with their own values.

    If you want to send information to an AI to use in its behavior tree, you must do so by creating or modifying a variable in that AI’s memory. You can do so on any AI by calling AI.WorkingMemory.SetItem() from code. Usually in code you will have access to the AIRig component rather than the AI itself, so you would call rig.AI.WorkingMemory.SetItem()

    So, to “warn the others” you would grab each other AI’s rig and do the SetItem call on each.

    #34488

    prime
    Keymaster

    If I understand your behavior tree correctly, it contains 3 basic states: run when you aren’t shooting, walk when you are shooting, and a hit animation when you are hit.

    With the way your logic is set up, whenever you leave the shooting or hit states, the top level selector under the Waypoint node will stop running. This happens because either (a) you stop shooting or stop being hit, which makes the Constraint node fail and the selector parent fail, or (b) you actually reach your destination while moving, which makes the whole subtree succeed.

    If your selector fails from (a), then the entire Waypoint node will fail and reset. In some cases, that can result in skipping a node.

    What you probably want to do instead is separate your Movement from your Animation entirely. Under your Waypoint node, create a parallel. Let that parallel succeed on Any. Inside the parallel, add a selector which manages two things: (1) the animation you are playing based on running/shooting/being hit, and (2) sets a variable indicating how fast the move node should be moving. Make that selector repeat forever. Add another node to the parallel. This will be your Move node. Make sure the Move node uses the speed variable set in the selector.

    With this setup, the only way your Parallel can finish is if the Move node succeeds or fails (it should always succeed). That will only happen when you have reached your waypoint target.

    Hope that helps

    #34454

    Jaroslav
    Participant

    You should create a variable in the AIRig memory and set it using:
    AIRig rig = GetComponentInChildren<AIRig>();
    rig.AI.WorkingMemory.SetItem<T>(string name, <T> value);
    In this case an isDead bool would be appropriate.

    Then in the enemy behaviour tree, have a component that checks if the condition is false – behave normaly as an enemy does, but if the bool is true – animate death. Set the animation through the behaviour tree, it is preferable.

    I am really new to RAIN, so pardon me if I say anaything wrong, but I am using this in my BT and it is working.
    Hope this helps and ask away. We beginner are in this together. :)

    Yep, It’s working :) Thanks for the point about setting the animation through BT, I absolutely forgot about that!

    #34453

    Moloch
    Participant

    You should create a variable in the AIRig memory and set it using:
    AIRig rig = GetComponentInChildren<AIRig>();
    rig.AI.WorkingMemory.SetItem<T>(string name, <T> value);
    In this case an isDead bool would be appropriate.

    Then in the enemy behaviour tree, have a component that checks if the condition is false - behave normaly as an enemy does, but if the bool is true - animate death. Set the animation through the behaviour tree, it is preferable.

    I am really new to RAIN, so pardon me if I say anaything wrong, but I am using this in my BT and it is working.
    Hope this helps and ask away. We beginner are in this together. :)

    #34426

    Stormy102
    Participant

    I am trying to get the AI to shoot the player. I have set up the sensors so that the player can be detected. Then, the AI moves towards the player. When the player is in range of the AI, the AI should raycast the player and print that it has hit the player. However, I get a NULL REFERENCE EXCEPTION at line 47, where the code raycasts. Could someone please help me with this? Here is the code:

    import RAIN.Core;
    import RAIN.Action;
    @RAINAction
    class aiShootPlayer extends RAIN.Action.RAINAction
    {
    	private var woodenImpactParticle : GameObject;
    	private var concreteImpactParticle : GameObject;
    	private var dirtImpactParticle : GameObject;
    	private var metalImpactParticle : GameObject;
    	private var bodyImpactParticle : GameObject;
    	private var shootPos : GameObject;
    	private var dist : float = 50;
    	private var showBlood : int = 0;
    	function newclass()
    	{
    		actionName = "aiShootPlayer";
    	}
    	function Start(ai:AI):void
    	{
            super.Start(ai);
    	}
    	function Execute(ai:AI):ActionResult
    	{
    		showBlood = PlayerPrefs.GetInt("GraphicsShowBlood", 0);
            shootPos = ai.WorkingMemory.GetItem("ShootPos") as GameObject;
            woodenImpactParticle = ai.WorkingMemory.GetItem("WoodenImpactParticle") as GameObject;
            concreteImpactParticle = ai.WorkingMemory.GetItem("ConcreteImpactParticle") as GameObject;
            dirtImpactParticle = ai.WorkingMemory.GetItem("DirtImpactParticle") as GameObject;
            metalImpactParticle = ai.WorkingMemory.GetItem("MetalImpactParticle") as GameObject;
            bodyImpactParticle = ai.WorkingMemory.GetItem("BodyImpactParticle") as GameObject;
    		Shoot();
            return ActionResult.SUCCESS;
    	}
       	function Stop(ai:AI):void
    	{
            super.Stop(ai);
    	}
    	function Shoot()
    	{
    		var hit : RaycastHit;
    		if (Physics.Raycast(this.transform.position, Vector3.forward, hit, 50))//shootPos.transform.position, Vector3.forward, hit, 50))
    		{
    			if (hit.gameObject.tag.ToLower() == "player")
    			{
    				print("Hit player");
    				Object.Instantiate(bodyImpactParticle, hit.point, bodyImpactParticle.transform.rotation);
    			}
    		}
    	}
    }

    and here is the XML Behaviour Tree:

    <behaviortree version="1.1" repeatuntil="" name="soldierAITree"><parallel tiebreaker="fail" succeed="all" repeatuntil="" name="root" fail="any"><detect sensor=""eyes"" repeatuntil="running" name="detectEyes" entityobjectvariable="entityPlayerPos" aspectvariable="" aspectobjectvariable="" aspect=""entityPlayerVisual"" /><detect sensor=""shootRange"" repeatuntil="running" name="detectShootRange" entityobjectvariable="entityPlayerTarget" aspectvariable="" aspectobjectvariable="" aspect=""entityPlayerVisual"" /><selector usepriorities="False" repeatuntil="" name="ExecuteAll"><constraint repeatuntil="" priority="" name="IfTargetNull" constraint="entityPlayerPos == null && entityPlayerTarget == null"><parallel tiebreaker="fail" succeed="all" repeatuntil="" name="ExecuteAll" fail="any"><waypointpatrol waypointsetvariable="PatrolRoute" waypointactiontype="patrol" traversetype="pingpong" traverseorder="forward" repeatuntil="" pathtargetvariable="" name="patrol" movetargetvariable="nextPos"><move turnspeed="" repeatuntil="" name="move" movetarget="nextPos" movespeed="2" facetarget="" closeenoughdistance="" closeenoughangle="" /></waypointpatrol></parallel></constraint><constraint repeatuntil="" priority="" name="If PlayerFound" constraint="entityPlayerPos != null"><parallel tiebreaker="fail" succeed="all" repeatuntil="" name="parallel" fail="any"><constraint repeatuntil="" name="IfInRange" constraint="entityPlayerTarget != null "><parallel tiebreaker="fail" succeed="all" repeatuntil="" name="ExecuteAll" fail="any"><action repeatuntil="" parametervalues="" parameters="" namespace="(global)" name="ShootPlayer" classname="aiShootPlayer" /></parallel></constraint><constraint repeatuntil="" name="IfNotInRange" constraint="entityPlayerTaget == null"><parallel tiebreaker="fail" succeed="all" repeatuntil="" name="ExecuteAll" fail="any"><move turnspeed="" repeatuntil="" name="move" movetarget="entityPlayerPos" movespeed="2" facetarget="" closeenoughdistance="" closeenoughangle="" /></parallel></constraint></parallel></constraint></selector></parallel></behaviortree>

    Cheers,

    Stormy102

    #34363

    prime
    Keymaster

    There are a couple of ways to do this:

    1) Set the name of the waypoints you want to use into a variable. Then make sure the Waypoint node references the variable rather than the name of the Waypoints directly.

    2) You could take just the part of the tree that follows the waypoints and swap it for a Behavior Tree Binding. Then create a number of sub trees based on the waypoints part. In each AI, you would attach the appropriate sub behavior tree into the binding (this appears in the Mind element of the AI.)

    I suspect (1) is what you want. It’s easy enough to set up variables for your AI that hold the value of the Waypoint route you want to use. This can be done via code or by pre-setting it into AI memory.

    (2) can be useful if you actually use slightly different behavior in each case and you want to customize different behavior trees.

    #34361

    prime
    Keymaster

    Here’s an example of a custom action that checks to see if an object is within a certain distance range:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Action;
    using RAIN.Core;
    using RAIN.Representation;
    using RAIN.Motion;
    [RAINAction("Distance Check")]
    public class DistanceCheck : RAINAction
    {
        public Expression Target = new Expression();
        public Expression GreaterThan = new Expression();
        public Expression LessThan = new Expression();
        public override ActionResult Execute(AI ai)
        {
            if (Target.IsValid && Target.IsVariable)
            {
                MoveLookTarget tTarget = MoveLookTarget.GetTargetFromVariable(ai.WorkingMemory, Target.VariableName);
                float tDistance = (tTarget.Position - ai.Kinematic.Position).magnitude;
                if (GreaterThan.IsValid && (tDistance <= GreaterThan.Evaluate<float>(ai.DeltaTime, ai.WorkingMemory)))
                    return ActionResult.FAILURE;
                if (LessThan.IsValid && (tDistance >= GreaterThan.Evaluate<float>(ai.DeltaTime, ai.WorkingMemory)))
                    return ActionResult.FAILURE;
            }
            return ActionResult.SUCCESS;
        }
    }

    You can use it in the behavior tree and set values for min distance, max distance, and the name of the variable that holds the player position/game object.

    #34153

    prime
    Keymaster

    The answer is pretty simple and easy to implement.

    Once you have your move-to position from your raycast, simply set a variable in AI memory with that position. e.g.,

    Vector3 moveToPosition; //Set this to the position you want to move to
    ai.WorkingMemory.SetItem<Vector3>("moveTarget", moveToPosition); //moveTarget is the AI memory variable I'm using

    Then in your behavior tree just set the Move Target of your move node to the variable you used (in my case, moveTarget).

    #34006

    prime
    Keymaster

    This should be pretty straightforward.

    - Add an Entity to the player.
    - Add a Visual Aspect with aspect name player

    - Create an AI.
    - Add a Visual Sensor. Make sure the range is large enough to detect the player

    - Create a behavior tree
    Parallel
    — Detect node - use “Visual Sensor” and set the aspect to “player” and the aspect variable to player. repeat forever
    — Move node - set Move Target to player. set close enough distance to 2. repeat forever

    Set the AI mind to use the new behavior tree

    That should be a reasonable base to get started and get the behavior you want.

Viewing 15 results - 1 through 15 (of 112 total)