0
\$\begingroup\$

I move my character based on the rootmotion of their animation using a blend tree that uses 2D Freeform Cartesian input (Vertical, Horizontal)

if Vertical = 1, the character moves forward based on the direction he is facing

if Horizontal = 1, the character turns right based on the direction he is facing

and the rest of the system follows, here is the current Blend Tree: enter image description here

Currently, if i press forward, the character move forward no matter where the camera is facing: enter image description here

But in this example, what i want is for the character to slightly make a turn left to face the camera direction and then start walking forward: enter image description here

When working on a game that moves the character by code (without rootmotion), something like this would solve the issue:

_inputAxis = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
_inputCam = Quaternion.Euler(0, _cam.transform.eulerAngles.y, 0) * _inputAxis;

And then use _inputCam to move the character, but for some reason this isn't working, and these two variables are always equal to each other, what am i doing wrong ? also if there is a "standard" solution for this problem (am sure it is) please link it (doesn't matter if its Unity or not as long as the code is readable)

Thanks!

\$\endgroup\$
1
\$\begingroup\$

You have two steps here.

  1. Convert your controller-relative input into a desired direction in the world, based on the camera perspective.

  2. Convert your desired direction in the world to a steering direction, based on the object orientation.

The code you've shown is one way to do step 1.

Myself, I like to use a different version that can also handle slopes:

Vector3 CameraRelativeFlatten(Vector3 input, Vector3 localUp)
{
    Transform cam = Camera.main.transform; // You can cache this to save a search.

    Quaternion flatten = Quaternion.LookRotation(
                                        -localUp, 
                                        cam.forward
                                   )
                                    * Quaternion.Euler(-90f, 0, 0);

    return flatten * input;
}

We can use that to do step 1 like so:

// If you want to handle slopes, use the character's up vector,
// or a terrain normal you get from a raycast here instead.
Vector3 groundNormal = Vector3.up;

Vector3 controllerSpaceInput = new Vector3(Input.GetAxis("Horizontal"), 
                                           0f,
                                           Input.GetAxis("Vertical"));

Vector3 worldSpaceInput = CameraRelativeFlatten(input, groundNormal);

Now that we have an arrow in the world pointing where we want to go, we want to look at that from the character's point of view - to know whether it's pointing left or right based on which way they're facing. That's step 2:

Vector3 localSpaceInput = characterTransform.InverseTransformDirection(worldSpaceInput);

Now localSpaceInput.x contains the amount of input pointing to your character's right, and localSpaceInput.z contains the amount pointing directly ahead in their forward direction.

\$\endgroup\$
5
  • \$\begingroup\$ thank you! this is extremely helpful and it seems that it's working, few questions please: (1) what's exactly going on in the 2nd line of the CameraRelativeFlatten method ? (2) if i wanted to do a 180 degree turn when the forward is exactly at -1, do you think this should be done as an "event trigger" or is there a proper way to do it in blend tree ? \$\endgroup\$ – alaslipknot Jan 16 at 16:46
  • 1
    \$\begingroup\$ (1) Click the link to see my previous answer, where I explain the steps in more detail. (2) No idea - try it and see how it works for your needs! \$\endgroup\$ – DMGregory Jan 16 at 16:50
  • \$\begingroup\$ (1) oh i totally missed that, thought its for slope only, (2) sure thing no worries! (3), am gonna mark this question as solved since the correct vector is acquired (THANKS again), but do you mind if i DM you on twitter cause i have a different question that i really can't even explain properly to find a title for it or google it :p \$\endgroup\$ – alaslipknot Jan 16 at 16:55
  • \$\begingroup\$ You can try that, or you can post in Game Development Chat and possibly get feedback faster. \$\endgroup\$ – DMGregory Jan 16 at 16:56
  • \$\begingroup\$ oh i didn't knew about the chat, will try first, thanks! \$\endgroup\$ – alaslipknot Jan 16 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.