News Forums Search Search Results for 'timer not stopping'

Viewing 2 results - 1 through 2 (of 2 total)
  • Author
    Search Results
  • #38964

    Sigil
    Keymaster

    New and improved. I added a DefaultSpeed to the motor (removed the acceleration), and I now override the speed value on Nav Mesh Agent, so if you want to affect speed you will have to use the one on the UnityNavMeshMotor instead. In addition, I changed my behavior tree a bit to give a more obvious result (not that it really matters).

    using RAIN.Motion;
    using RAIN.Serialization;
    using UnityEngine;
    [RAINSerializableClass]
    public class UnityNavMeshMotor : RAINMotor
    {
        [RAINSerializableField]
        private float _closeEnoughDistance = 0.1f;
        [RAINSerializableField]
        private float _speed = 3.5f;
        private NavMeshAgent _agent = null;
        private Vector3 _lastPosition = Vector3.zero;
        public override float DefaultCloseEnoughDistance
        {
            get { return _closeEnoughDistance; }
            set { _closeEnoughDistance = value; }
        }
        public override float DefaultSpeed
        {
            get { return _speed; }
            set { _speed = value; }
        }
        // It seems like the NavMeshAgent forces positions on
        // the NavMesh, so 3D Movement doesn't make sense
        public override bool Allow3DMovement
        {
            get { return false; }
            set { }
        }
        // Don't support this at the moment, not sure if the NavMeshAgent
        // can go off of the mesh
        public override bool AllowOffGraphMovement
        {
            get { return false; }
            set { }
        }
        // 3D Rotation is technically doable, but not like
        // we support it with the BasicMotor
        public override bool Allow3DRotation
        {
            get { return false; }
            set { }
        }
        public override void BodyInit()
        {
            base.BodyInit();
            if (AI.Body == null)
                _agent = null;
            else
            {
                _agent = AI.Body.GetComponent<NavMeshAgent>();
                if (_agent == null)
                    _agent = AI.Body.AddComponent<NavMeshAgent>();
            }
        }
        public override void UpdateMotionTransforms()
        {
            // I don't believe the Unity Navigation Mesh can handle transforms, so this stays as identity
            AI.Kinematic.ParentTransform = Matrix4x4.identity;
            AI.Kinematic.Position = AI.Body.transform.position;
            AI.Kinematic.Orientation = AI.Body.transform.rotation.eulerAngles;
            // Velocities likely won't matter as we never actually use them in this motor
            AI.Kinematic.ResetVelocities();
            // Set our speed to zero, we'll set it when we are using it
            _agent.speed = 0;
        }
        public override void ApplyMotionTransforms()
        {
        }
        public override bool Move()
        {
            if (!MoveTarget.IsValid)
                return false;
            // Set our acceleration
            _agent.speed = _speed;
            // We'll just update these constantly as our value can change when the MoveTarget changes
            _agent.stoppingDistance = Mathf.Max(DefaultCloseEnoughDistance, MoveTarget.CloseEnoughDistance);
            // Have to make sure the target is still in the same place
            Vector3 tEndMoved = _lastPosition - MoveTarget.Position;
            tEndMoved.y = 0;
            // If we don't have a path or our target moved
            if (!_agent.hasPath || !Mathf.Approximately(tEndMoved.sqrMagnitude, 0))
            {
                _agent.destination = MoveTarget.Position;
                _lastPosition = MoveTarget.Position;
                // We can return at least if we are at our destination at this point
                return IsAt(_agent.destination);
            }
            // Still making a path or our path is invalid
            if (_agent.pathPending || _agent.pathStatus == NavMeshPathStatus.PathInvalid)
                return false;
            return _agent.remainingDistance <= _agent.stoppingDistance;
        }
        public override bool IsAt(Vector3 aPosition)
        {
            Vector3 tPosition = AI.Body.transform.position - aPosition;
            tPosition.y = 0;
            return tPosition.magnitude <= _agent.stoppingDistance;
        }
        public override bool IsAt(MoveLookTarget aTarget)
        {
            return IsAt(aTarget.Position);
        }
        public override bool Face()
        {
            // Too tired to do this
            return true;
        }
        public override bool IsFacing(Vector3 aPosition)
        {
            // Too tired to do this
            return true;
        }
        public override bool IsFacing(MoveLookTarget aTarget)
        {
            // Too tired to do this
            return true;
        }
        public override void Stop()
        {
            _agent.Stop();
        }
    }

    And the behavior tree:

    root
       sequencer
          parallel (fail: any, succeed: any, tie breaker: fail)
             waypoint patrol (waypoint route: "route", move target variable: moveTarget)
                 move (move target: moveTarget)
             timer (seconds: 2)
          timer (seconds: 2)

    Let me know how it works.

    #27279

    lordofduct
    Participant

    So the reason I ask is because I’m tooling with TreeBindings and I run into this problem.

    This is my root tree:

    <behaviortree version="1.1" repeatuntil="" name="GatorBehaviour">
    	<parallel tiebreaker="fail" succeed="all" repeatuntil="" name="root" fail="any">
    		<action repeatuntil="" parametervalues="ACJEZXRlY3RTdXJyb3VuZGluZ3Mi" parameters="QnJhaW4AQ29tbWFuZA==" namespace="(global)" name="Detect Surroundings" classname="BrainAction" />
    		<selector usepriorities="False" repeatuntil="" name="Has Target?">
    			<constraint repeatuntil="" priority="" name="Has Target" constraint="varTarget != null">
    				<action repeatuntil="" parametervalues="ACJ2YXJJc0hlYWx0aHkiACJFdmFsdWF0ZUlzSGVhbHRoeSIAImJvb2wi" parameters="QnJhaW4AVmFyaWFibGUARnVuY3Rpb24AUmVzdWx0VHlwZQ==" namespace="(global)" name="Evaluate Health" classname="BrainEvaluate" />
    				<selector usepriorities="False" repeatuntil="" name="Is Healthy?">
    					<constraint repeatuntil="" priority="" name="Healthy" constraint="varIsHealthy">
    						<treebinding repeatuntil="" name="Offense" binding="Offense" />
    					</constraint>
    					<constraint repeatuntil="" priority="" name="Unhealthy" constraint="!varIsHealthy">
    						<treebinding repeatuntil="" name="Defense" binding="Defense" />
    					</constraint>
    				</selector>
    			</constraint>
    			<constraint repeatuntil="" priority="" name="No Target" constraint="varTarget == null">
    				<treebinding repeatuntil="" name="treebinding" binding="Idle" />
    			</constraint>
    		</selector>
    	</parallel>
    </behaviortree>

    It’s pretty basic, basically I am observing my surroundings. If there are any targets in the area, we will evaluate our current health and go on the offense or defense depending. If nothing is around we go into an idle state.

    All 3 of these states will be tree bindings. One main reason is this is a fairly basic AI structure… most mobs will probably end up with this very structure. Though their offense/defense/idle trees may vary… the root of it is identical.

    So because the lack of debugging the whole tree at the same time, I went and first just attached the ‘idle’ tree to my mob and developed it up to make it act exactly how I want. This is it for reference…

    <behaviortree version="1.1" repeatuntil="" name="GatorIdle">
    	<sequencer usepriorities="False" repeatuntil="" name="root">
    		<action repeatuntil="" priority="" parametervalues="ACJ2YXJJc0hlYWx0aHkiACJFdmFsdWF0ZUlzSGVhbHRoeSIAImJvb2wi" parameters="QnJhaW4AVmFyaWFibGUARnVuY3Rpb24AUmVzdWx0VHlwZQ==" namespace="(global)" name="Evaluate Health" classname="BrainEvaluate" />
    		<selector usepriorities="False" repeatuntil="" priority="" name="Is Healthy?">
    			<constraint repeatuntil="" priority="" name="Healthy" constraint="varIsHealthy">
    				<sequencer usepriorities="False" repeatuntil="" name="idle sequence">
    					<parallel tiebreaker="succeed" succeed="any" repeatuntil="" priority="" name="patrol" fail="any">
    						<parallel tiebreaker="fail" succeed="all" repeatuntil="" name="parallel" fail="any">
    							<action repeatuntil="" parametervalues="ACJQYXRyb2wi" parameters="QnJhaW4AQ29tbWFuZA==" namespace="(global)" name="Patrol" classname="BrainAction" />
    							<animate repeatuntil="" name="animate walk" animationstate="walk" />
    						</parallel>
    						<timer waitforsec="random(5,10)" returnvalue="success" name="timer" />
    					</parallel>
    					<parallel tiebreaker="succeed" succeed="any" repeatuntil="" priority="" name="idle" fail="any">
    						<timer waitforsec="random(1,5)" returnvalue="success" name="timer" />
    						<animate repeatuntil="" name="animate idle" animationstate="idle" />
    					</parallel>
    					<random repeatuntil="" priority="" name="look around AND/OR pick direction">
    						<sequencer weight="" usepriorities="False" repeatuntil="" name="look around">
    							<animate repeatuntil="" priority="" name="animate lookback" animationstate="idle_lookback" />
    							<timer waitforsec="random(0.5, 1.5)" returnvalue="success" priority="" name="timer" />
    							<action repeatuntil="" priority="" parametervalues="ACJQaWNrRGlyZWN0aW9uIg==" parameters="QnJhaW4AQ29tbWFuZA==" namespace="(global)" name="pick direction" classname="BrainAction" />
    						</sequencer>
    						<action weight="" repeatuntil="" parametervalues="ACJQaWNrRGlyZWN0aW9uIg==" parameters="QnJhaW4AQ29tbWFuZA==" namespace="(global)" name="pick direction" classname="BrainAction" />
    					</random>
    				</sequencer>
    			</constraint>
    			<constraint repeatuntil="" priority="" name="Unhealthy" constraint="!varIsHealthy">
    				<sequencer usepriorities="False" repeatuntil="" name="forage sequence">
    					<parallel tiebreaker="succeed" succeed="any" repeatuntil="" priority="" name="patrol" fail="any">
    						<parallel tiebreaker="fail" succeed="all" repeatuntil="" name="parallel" fail="any">
    							<action repeatuntil="" parametervalues="ACJQYXRyb2wi" parameters="QnJhaW4AQ29tbWFuZA==" namespace="(global)" name="Patrol" classname="BrainAction" />
    							<animate repeatuntil="" name="animate" animationstate="walk" />
    						</parallel>
    						<timer waitforsec="random(5,10)" returnvalue="success" name="timer" />
    					</parallel>
    					<random repeatuntil="" priority="" name="forage OR idle">
    						<sequencer weight="" usepriorities="False" repeatuntil="" name="forage">
    							<animate repeatuntil="" priority="" name="animate forage dig" animationstate="melee_bite" />
    							<random repeatuntil="" priority="" name="eat OR return">
    								<sequencer weight="" usepriorities="False" repeatuntil="" name="eat">
    									<animate repeatuntil="" priority="" name="animate eat" animationstate="melee_bite" />
    									<action repeatuntil="" priority="" parametervalues="ACJGb3JhZ2VIZWFsIg==" parameters="QnJhaW4AQ29tbWFuZA==" namespace="(global)" name="Heal" classname="BrainAction" />
    								</sequencer>
    								<sequencer weight="" usepriorities="False" repeatuntil="" name="return">
    									<parallel tiebreaker="succeed" succeed="any" repeatuntil="" priority="" name="idle" fail="any">
    										<animate repeatuntil="" name="animate idle" animationstate="" />
    										<timer waitforsec="random(0.5, 1.5)" returnvalue="success" name="timer" />
    									</parallel>
    								</sequencer>
    							</random>
    						</sequencer>
    						<sequencer weight="" usepriorities="False" repeatuntil="" name="idle">
    							<animate repeatuntil="" priority="" name="animate forage idle" animationstate="idle" />
    						</sequencer>
    					</random>
    				</sequencer>
    			</constraint>
    		</selector>
    	</sequencer>
    </behaviortree>

    So this BT works, it does what I expect. It goes through the entire sequence… primarily: patrol -> stand still -> sometimes lookaround -> turn around -> repeat

    Problem is, when I go and bind it to the primary tree and run it that way. It just patrols… walking in the same direction forever. Wat?

    So I go and copy the entire tree and just put it right into the spot where the tree binding is for idle, replacing the binding for just a complete tree in one.

    It again only patrols, not stopping. Worse, it doesn’t animate now either. Just walks in a straight line in T-pose.

    Now… I had an issue with sometimes animations not occurring before. This is the second time I’m coming across it. And there is nothing here pointing as to why. I honestly have no clue… Wat?

Viewing 2 results - 1 through 2 (of 2 total)