#Problem with code? Trying to fix animations (Root Motion)

1 messages ยท Page 1 of 1 (latest)

manic rune
#

Making a thread to help clear up the chat for other people

#

I've actually been stuck on trying to get this root motion movement to work for about 2 weeks now and I still can't figure out where it's going wrong. Even though I now have just used a pre-built animator setup ๐Ÿ˜‚

There's something really wrong with a setting or code or something
I'll show what the readme for the animator says which is

The graph is controlled by 3 variables:

  1. InputMagnitude
    This is a float that should be controlled by Input Axis Vector Magnitude (so for example, how far is the joystick bent). It controls the transitions between Idling and running.

  2. InputDirection
    This is a float that should be controlled by the angle between character's Forward Axis and the Input Axis Vector. So for example, if the joystick is bent right, the angle will be 90 degrees, if back, the angle will be 180 degrees and so on.

  3. IsRightLegUp
    This is a bool that should be controlled by which foot is currently higher in a run cycle, so the controller knows which animation it should play while stopping. Easiest way to get this info is checking which foot bone has a bigger Global Transform Y at the moment. So, if right foot is higher - we change IsRightLegUp to true.

So, if anyone can see where I'm going wrong, I would greatly love some help ๐Ÿ˜ญ

manic rune
#

Problem with code? Trying to fix animations (Root Motion)

analog bear
#

based on the video, it look like it might be related to the camera. I see this line in the code: // Camera relative movement var move = mainCamera.right * moveInput.x+ mainCamera.forward * moveInput.y; but I don't see where you adjust the camera facing direction (assume in a different script).. it look almost like a feedback thing going on .. when you turn left hard, the camera turns fast, then you turn "harder". I'd test this by making that line use transform.right and transform.forward, rather than the mainCamera.right/forward.

manic rune
# analog bear based on the video, it look like it might be related to the camera. I see this ...

I feel like you might be onto something with the camera affecting things somehow.

I've just done as you suggested so it looks this now

// Camera relative movement
        var move = transform.right * moveInput.x+ transform.forward * moveInput.y;
        move.y = 0;

The movement still seems to be the same as the above video so I don't think it appears to have really changed anything. But yeah, I do feel like it could possibly be a camera thing somehow

#

What I've noticed just now, is maybe something is wrong with Input Direction? Looking at the animator parameters, it doesn't seem to receive a constant input?

For example, I am holding right, the inputdirection initially increases, but then starts to 0 out so my character just starts running straight even though I am trying to go right

analog bear
#

I dont see where it actually changes the character's facing dir...

manic rune
#

From looking through, my only other thing I can find, is the empty object I attached to the character as a target, so that when the object rotates (with mouse) etc, the camera rotates also

using UnityEngine;
using UnityEngine.InputSystem;

public class CameraController : MonoBehaviour
{
    public InputActionReference lookAction;
    public InputActionReference aimAction;
    public Transform cameraTransform;
    public Transform aimCamTransform;
    public Animator animator;
    public float xSens = 2.5f;
    public float ySens = 2.5f;
    public float yMinLimit = -20;
    public float yMaxLimit = 80;
    public float centerWaitTime = 2f;
    public float centerSpeed = 5f;
    private float centerTimer;
    private float xRotation;
    private float yRotation;
    private float aimLayerWeight;

    private void Start()
    {
        var rot = transform.rotation.eulerAngles;
        xRotation = rot.x;
        yRotation = rot.y;
    }

    private void Update()
    {
        var input = aimAction.action.IsPressed();
        cameraTransform.gameObject.SetActive(!input);
        aimCamTransform.gameObject.SetActive(input);
        aimLayerWeight = Mathf.Lerp(aimLayerWeight, input ? 1 : 0, Time.deltaTime * 5);
        animator.SetLayerWeight(1, aimLayerWeight);
    }

    private void LateUpdate()
    {
        var input = lookAction.action.ReadValue<Vector2>();
        if (input.magnitude < 0.01f)
        {
            centerTimer += Time.deltaTime;
            if (centerTimer > centerWaitTime)
            {
                xRotation = Mathf.LerpAngle(xRotation, 0, Time.deltaTime * centerSpeed);
                yRotation = Mathf.LerpAngle(yRotation, 0, Time.deltaTime * centerSpeed);
            }
            
        }
        else
        {
            centerTimer = 0;
        }

        xRotation += input.x * xSens;
        yRotation -= input.y * ySens;
        yRotation = ClampAngle(yRotation, yMinLimit, yMaxLimit);

        var rotation = Quaternion.AngleAxis(xRotation, Vector3.up) * Quaternion.AngleAxis(yRotation, Vector3.right);
        transform.localRotation = rotation;
    }

    private float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360) angle += 360;
        if (angle > 360) angle -= 360;
        return Mathf.Clamp(angle, min, max);
    }
}
analog bear
#

Vector3 inputAxisVector = new Vector3(moveInput.x, 0, moveInput.y); angle = Vector3.SignedAngle(transform.forward, inputAxisVector, Vector3.up); your turn angle is NOT relative to the transform.forward.. it's moveInput is relative to Vector2(0,1) no?

#

(left on the joystick means turn left 90. regardless of direction char is facing...)

manic rune
#

Yeah it's moveinput is Vector2

#

It's as you say yeah I think

analog bear
#

you used Atan2 else where ... I think that's the way to go here too

manic rune
#
private void UpdateDirection()
    {
        // Camera relative movement
        var move = transform.right * moveInput.x+ transform.forward * moveInput.y;
        // var move = mainCamera.right * moveInput.x+ mainCamera.forward * moveInput.y;
        move.y = 0;

        // Transforming to local space of character
        // move = transform.InverseTransformDirection(move);

        forward = move.z;
        lateral = move.x;
        turn = Mathf.Atan2(move.x, move.z);
#

At the bottom there

analog bear
#

unless I misunderstand what inputDirection is.. is that a world-space angle or "how much to turn"?

manic rune
#

So basically, after troubleshooting a bunch. I tried to go with a different animation pack to sorta elimate the pack as an issue.

This pack comes with a basic controller already set up and this is what the readme says

#

The graph is controlled by 4 variables:

  1. InputMagnitude
    This is a float that should be controlled by Input Axis Vector Magnitude (so for example, how far is the joystick bent). It controls the transitions between Idling and running.

  2. InputDirection
    This is a float that should be controlled by the angle between character's Forward Axis and the Input Axis Vector. So for example, if the joystick is bent right, the angle will be 90 degrees, if back, the angle will be 180 degrees and so on.

  3. IsRightLegUp
    This is a bool that should be controlled by which foot is currently higher in a run cycle, so the controller knows which animation it should play while stopping. Easiest way to get this info is checking which foot bone has a bigger Global Transform Y at the moment. So, if right foot is higher - we change IsRightLegUp to true.

#

So really, direction and magnitude are what I was trying to go for so that I could make the controller work as intended

#

(Says controlled by 4 variables in the readme but it only is 3)

analog bear
#

" if the joystick is bent right, the angle will be 90 degrees, if back, the angle will be 180 degrees and so on." ya sounds like atan2 using the joystick inut is the way to go here

manic rune
#

It ofc talks about joystick etc, but just to sort of make sure as I'm not sure if this is a conflicting thing, but I'm not using a joystick or anything and want it work kb/m

analog bear
#

same diff, but keyboard will just be 1,0,-1 for each axis. mouse... hmmm not sure there

manic rune
#

First time trying to work with root motion as well as being a bit fresh to Unity as well, so trying to come to grips with everything ๐Ÿ˜“

manic rune
#

Mouse isn't a big worry right now, I can ignore camera related movement or such for the moment

#

I just want to be able to have the smooth animator with wasd for now before I progress

analog bear
#

I'm SUPER rusty on animator stuff to be honest, but I know transforms and vectors well enough. inputDirection =Mathf.Atan2(moveInput.x, moveInput.y);

#

give that a go.. not sure how it'll do, but worth a shot

manic rune
#

Sure

#
// Calculate input magnitude and direction
        inputMagnitude = moveInput.magnitude;
        Vector3 inputAxisVector = new Vector3(moveInput.x, 0, moveInput.y);
        angle = Vector3.SignedAngle(transform.forward, inputAxisVector, Vector3.up);
        inputDirection = Mathf.Atan2(moveInput.x, moveInput.y);

Like this then yeah?

analog bear
#

will help us figure out what might be wroing if it doesn't

#

I dont think you need "angle"

#

just use inputDirection

#

but yes

manic rune
#

0.7 was the number when I held W & D to go FL

analog bear
#

it's ghiving you radians

#

Mathf.RadToDeg

manic rune
#

Ohhhh

#

Okay

#

So yeah, it looks like that did it for the most part

#

The character is still "snapping" in movement

#

Which is a problem

#

But general trajectory seems to be on point

#

Not sure the snapping is something I can fix with code or if it is an animator only thing currently

The controller is prebuilt so I imagine, it should be working fine without snaps

analog bear
#

I fear that snapping may be outa my skill range- animator stuff. but I'd GUESS it's cuz your using a keybaord. which is gonna be 0 or 1 for any given direction... so even combining keys tere is only like 8 diff dirctions you can go

#

one option: we can check when a direction key is first pressed, then, over some specified amount of time, drive it from 0 to 1 (while it's held down).

manic rune
#

Yeah that sounds like it could be something possibly

analog bear
#

^ it : the input(s) to the Atan2 function

#

we can also try with the mouse.. just need to make sure the value we get from it is somewhere between -1,-1 and 1,1 .. not quite sure how to do that... hmm

#

is that what the black dot is for?

#

dragging it to turn and stuff?

manic rune
#

I've just been ignoring it while trying to do the animations

analog bear
#

lol, I do that stuff all the time tooo

manic rune
#

Yeah I tried getting rid of it, but it's from cinemachine 3rd person aim script, and I cant quite understand how cinemachine is wanting it to work

#

Even disabling the original image of that block dot doesnt do anything

manic rune
analog bear
#

this was for driving the input from 0 to 1 over a peroid of time, rather than going from 0 to 1 instantly, like the keyboard currently does. so, right now we are calling Atan2(a,b) with only 1,-1 and 0 as possible values for a and b. If we drive it slowly, we'd pass the slowly driven values into the Atan2 function.

#

bah.. was that understandable at all?

manic rune
#

Yeah that makes perfect sense in the theory. No problem at all, it's just a problem on my end knowing how to implement it ๐Ÿ˜‚

analog bear
#

ah! well, step 1- we need to remember what moveInput was LAST frame. then we can see if it's changed.

#

step 2- when we see a change, we make note of the current Time.time. We'll also need a new member to store how long the change should take.

manic rune
#

Every time "Last frame" is mentioned, I feel like I've never quite grasped how people check that

On a side note, just wanted to give you some praise on your knowledge also. Seems like you are really well versed

analog bear
#

step 3 - interpolate between the previous moveInput and the current moveInput, over that time period.

analog bear
manic rune
#

๐Ÿ˜‚
Ah fair enough, I'm still fresh to it myself, only been at it for a couple of years in University. But never get to sit down and spend a long period of time on one language or something in particular

analog bear
#

there is just SO MUCH programming stuff to learn out there! I'd be usesless at most of it.

manic rune
analog bear
#

even in JUST unity... animations for example- I'm useless

#

might be a way to do this over time thing right in there for all I know.

manic rune
#

Just realised though, I do have a controller sitting around

analog bear
#

whats your major, btw, CS?

manic rune
#

So I might quickly try to use the joystick, just to give it a go and see if the outcome differs

#

Yeah CS

#

In my final year now, working to make something in Unity is what I wanted to do as a project idea

#

Anyone else that also picked Unity chose to do a 2D one for theirs though, so I picked a much tougher choice ๐Ÿ˜‚

analog bear
#

cool! FYI some joysticks are ALSO digital meaning only 1 or 0, so figers crossed

manic rune
#

I'll have to set it up on the input manager also, as I only have my kb map currently

analog bear
#

alright bud, I'm out for now- but ping me if ya need!

manic rune
#

Sure no problem, thanks so much for everything

#

Honestly can't say how much I appreciate it