News Forums RAIN General Discussion and Troubleshooting Using Unity's Built In Pathfinding System With RAIN

This topic contains 25 replies, has 5 voices, and was last updated by  Sigil 3 months, 4 weeks ago.

Viewing 11 posts - 16 through 26 (of 26 total)
  • Author
    Posts
  • #38946

    Sigil
    Keymaster

    Hmmm I put this together and it worked with the code above, it could be something particular with your behavior tree though, or perhaps you are using the version I posted briefly before editing it. This should behave similarly to what happens when a constraint interrupts a move:

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

    This is making him walk for 4 seconds, then pause for 2, and then repeats. If that doesn’t work for you, double check the code. If it does work, but your tree still doesn’t, post the problem area and I’ll test it out.

    #38957

    ck
    Participant

    Something weird is going on on my end… I’ve created a brand new project, re-copied the motor code and created a behavior tree like the one above, but it still didn’t do the trick. Here’s the link to the repro project:
    https://www.dropbox.com/s/cpzijf7hoqzq3to/RainRepro.zip?dl=0

    The white capsule is using the BasicMotor, the red one - the NavMeshMotor and both of them are running the same behavior tree, but the red capsule never stops moving.

    #38963

    Sigil
    Keymaster

    You are correct, sorry, I wasn’t paying attention to my tree well enough and screwed that one up. I’ll post a fix shortly if I can come up with one easily.

    #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.

    #38974

    ck
    Participant

    The new motor seems to be working great, haven’t tested much but it’s working with my original behavior trees so everything’s good so far. Thanks again, Sigil!

    #38984

    Sigil
    Keymaster

    No problem, come back here with any issues/requests and I’ll see what I can do.

    #39215

    Lanthian
    Participant

    This was a huge help for our project, thanks for posting this. I have already run it through several tests and it works great.

    #39221

    Lanthian
    Participant

    I see that there are places for look at target code but it’s not finished.
    Would it be possible to get some tips on finishing the look at target functionality of the above custom motor. I’ve been trying to code the unfinished parts but I’m not very familiar with the unity navigator system nor how rain deals with it.

    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;
        }

    thanks

    #39231

    Sigil
    Keymaster

    I’ll take a look at this later tonight (maybe tomorrow though, no promises). There is a value on the NavMeshAgent (updateRotation I think) that can be used to turn off rotation updating by the agent. If that works the way I hope, it might be trivial to add those remaining functions in.

    #39293

    Lanthian
    Participant

    I’ve been playing around with the navmeshagent and updaterotation value. I can turn on and off rotation for the agent but I haven’t been able to figure out how to get it to stay looking at the target after arriving. The ai units will look in the general direction of the target but not right at it(or within a set angle limit) and if they get bumped by another unit they will not update their facing direction. The only way I can see to accomplish that at the moment is to turn off rotation once they arrive and then script rotation for them but that causes some weird problems with other behaviors that I have in my tree. I’m sure that there is probably some much simpler way of doing this that I’m just not thinking of. Have you had any luck with this?

    • This reply was modified 3 months, 4 weeks ago by  Lanthian.
    #39298

    Sigil
    Keymaster

    So I got this working, but unfortunately I’ve been using the next version of RAIN and it doesn’t quite line up anymore. If you like you can contact me (sigil@rivaltheory.com) and I can get you it plus RAIN (beta). Or you can wait a bit longer and I’ll transfer it over.

    This turned out pretty good so we’re also gonna throw it in the starter kit as an example of a custom motor (part of the reason I screwed it up with the RAIN beta).

Viewing 11 posts - 16 through 26 (of 26 total)

You must be logged in to reply to this topic.