Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Third person character controller velocity and Root animation confusion

Discussion in 'Scripting' started by Fish-e, Feb 8, 2022.

  1. Fish-e

    Fish-e

    Joined:
    Feb 6, 2022
    Posts:
    1
    I am using a mixture of in place and "not in place" animations, so I want to use root motion for those. When working on movement with a character controller I noticed a strange behaviour after activating apply root motion on the animator. The character moves extremely slow and I have to increase the speed drastically to get the wanted results, but the movement becomes janky. This also happens for the Starter Asset - Third Person Character Controller from the asset store.

    This code to smooth the speed transition of the character seems to be the problem:

    float currentSpeed = new Vector3(controller.velocity.x, 0.0f, controller.velocity.z).magnitude;
    if (currentSpeed < targetSpeed - speedOffset || currentSpeed > targetSpeed + speedOffset)
    {
    movementSpeed = Mathf.Lerp(currentSpeed, targetSpeed, Time.deltaTime * SpeedChangeRate);
    movementSpeed = Mathf.Round(movementSpeed * 1000f) / 1000f;
    }
    else
    {
    movementSpeed = targetSpeed;
    }

    This works until you activate root motion. After some debugging I noticed that the currentSpeed is always 0 because of it. Controller velocity only changes when it is moved by an animation otherwise even if moving by script the velocity magnitude stays 0;

    Is this intended to work like this ? The documentation states: The velocity returned is simply the difference in distance for the current timestep before and after a call to CharacterController.Move or CharacterController.SimpleMove. This code uses Move() but the velocity is still 0... so what gives.

    My workaround was to implement my own velocity calculation like so:

    Vector3 previousPosition = transform.position;
    controller.Move(moveDirection.normalized * movementSpeed * Time.deltaTime);
    float distance = Vector3.Distance(previousPosition, transform.position);
    currentSpeed = distance / Time.deltaTime;

    Now the movement seems to work correctly with root motion.

    Can anyone give me some insight into this? Is using a mix of root motion and script based movement bad practice?
     
    Pruthin and sagarhinsu like this.
  2. sagarhinsu

    sagarhinsu

    Joined:
    Nov 13, 2021
    Posts:
    2
    I am also facing the same issue, after applying Root Motion the movement is kinda janky...