5.0 - using replacing MovementUpdate when using FollowerEntity

I’m using the UltimateCharacterController integration with IAStarAI and I’d like to see if the FollowerEntity gives better results for the path finding (eg movement but also offmesh links). However, the MovementUpdate() method which is used by the character controller is not supported on the ECS component.

Can you give some directions on how I could integrate this with the new FollowerEntity (I’m unfortunately not very familiar with ECS).

thanks

Hi

Are you using this with your player character? Or is this for enemies?
I’d need a bit more info about what the character controller does here.

This is with NPCs. I give the character controller a path which it then follows. The character controller takes care of vaulting over obstacles it encounters and triggering the right animations.

It disabled the movement on the IAStarAI using canMove = false and used the next position/rotation to translate that to input on the character controller instead.

Is this your code? If so, do you have a copy of it?

These are the methods that apply the movement with the agent (not pasting full classes as those are I think only downloadable for paid members of the library).

/// <summary>
        /// Updates the ability.
        /// </summary>
        public override void Update() {
            m_IAstarAIAgent.MovementUpdate( Time.fixedDeltaTime, out m_NextPosition, out m_NextRotation );
            var localVelocity = m_Transform.InverseTransformDirection( (m_NextPosition - m_CharacterLocomotion.Position) / Time.fixedDeltaTime );
            localVelocity.y = 0;
            // Only move if a path exists.
            m_InputVector = Vector2.zero;
            if ( m_IAstarAIAgent.hasPath && localVelocity.sqrMagnitude > 0.01f && m_IAstarAIAgent.remainingDistance > 0.01f ) {
                // Only normalize if the magnitude is greater than 1. This will allow the character to walk.
                if ( localVelocity.sqrMagnitude > 1 ) {
                    localVelocity.Normalize();
                }

                m_InputVector.x = localVelocity.x;
                m_InputVector.y = localVelocity.z;
            }

            var rotation = m_NextRotation * Quaternion.Inverse( m_Transform.rotation );
            m_DeltaRotation.y = Utility.MathUtility.ClampInnerAngle( rotation.eulerAngles.y );

            base.Update();
        }

        /// <summary>
        /// Ensure the move direction is valid.
        /// </summary>
        public override void ApplyPosition() {
            if ( HasArrived ) {
                // Prevent the character from jittering back and forth to land precisely on the target.
                var direction = m_Transform.InverseTransformPoint( m_IAstarAIAgent.destination );
                var moveDirection = m_Transform.InverseTransformDirection( m_CharacterLocomotion.DesiredMovement );
                if ( Mathf.Abs( moveDirection.x ) > Mathf.Abs( direction.x ) ) {
                    moveDirection.x = direction.x;
                }

                if ( Mathf.Abs( moveDirection.z ) > Mathf.Abs( direction.z ) ) {
                    moveDirection.z = direction.z;
                }

                m_CharacterLocomotion.DesiredMovement = m_Transform.TransformDirection( moveDirection );
            }
        }

        /// <summary>
        /// Notify IAStarAI of the final position and rotation after the movement is complete.
        /// </summary>
        public override void LateUpdate() {
            m_IAstarAIAgent.FinalizeMovement( m_CharacterLocomotion.Position, m_CharacterLocomotion.Rotation );
        }

Hello,
i’ve the same problem here. Is this something for the opsive support? I’m also not into ECS - is there something we can tell them so they can update their integration accordingly?
thanks

Hi

In the next version I’ll introduce a new API that can be used to override the movement.
It’s not quite fleshed out, so there may be some changes in future versions. But it would be great if you could try it out and see if it works for your purpose.

Hi,
I downloaded 5.0.5 and am trying the new movementOverrides.
Not there yet but making some progress. But I have a couple of questions because I actually don’t feel that I grasp how it all works.

I set updatePosition/updateRotation and add callbacks and get no errors. However, a frame later they are reset and the callbacks don’t get executed. So I assume I register them too early somehow? I work around this by applying the configuration the first time I try to do a move, this appears to work.

Looking at the docs I think it’s the BeforeMovement callback that I need if I want RVO.
I disable movement on the AI and use the position/rotation of the ResolvedMovement. Which I then feed to as desired input to the character controller.

However, it’s a bit unclear to me how I can feed back the actual position (like the FinalizeMovement() method). I understand I could update the ResolvedMovement but I don’t fully understand how to do so at the right time. I guess this is related to the ECS/non-ECS setup, because the character controller and AI movement run at separate points in time.

What I think the scenario is:

  • when the callback comes, I take the resolved movement as desired location
  • the character controller will take this as desired movement “on its next update cycle” but will apply additional movement parameters, making the actual position different
  • when the character controller finishes, I should feed the final position (and rotation) back to the AI

If the entity always takes the transform position and rotation as its current values, but does not automatically update them, I suppose that would not be a problem, but I assume it keeps its own simulated position?

Does this makes sense or am I missing something and do you see a best way to approach this?
Side question: how do I correctly feed back the actual rotation from the transform Quaternion to the ResolvedMovement?

Thanks for all input in helping me understand!