2

I have a sphere as player and I want it to move relative to camera and not world.

When I rotate camera along Y-axis by 90 or 270 degree and give input, it gives opposite output than expected.

Here is my script attached to sphere:

using System.Collections;
using UnityEngine;

public class mover : MonoBehaviour {

    public Rigidbody sphere;

    public GameObject cameraa;


    void Start () 
    {
        sphere = GetComponent<Rigidbody> ();
    }


    void Update () 
    {
        // getting input in controlVector
        Vector3 controlVector = new Vector3 (Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

        // transforming direction from world space to local space[to camera]
        Vector3 localVectToCam = cameraa.transform.InverseTransformDirection (controlVector);

        //applying inputs   
        sphere.AddForce (localVectToCam * 10);
    }
}

when camera's direction is same as world and when camera is rotated along Y-axis by 180 degree, it works fine.

But on rotating camera along Y-axis by 90 and 270 degree is gives opposite output.

example:

camera rotation along Y-axis = 90 degree [ i.e (0,90,0) ]

input given = (0,0,1)

output got = (-1,0,0)

expected output = (1,0,0)

Can you help me to understand and correct it?

code11
  • 1,986
  • 5
  • 29
  • 37
Makarand
  • 983
  • 9
  • 27
  • Why are you expecting `(1,0,0)`? Rotating `(0,0,1)` 90 degrees clockwise does indeed give you `(-1,0,0)`. – Ian H. Feb 06 '17 at 18:04
  • because when I rotate camera 90 clockwise along Y-axis, its positive Z-axis is toward worlds positive X-axis. Now if I press key 'W' , input given is (0,0,1) [relative to world], I want to move sphere in cameras +ve Z-axis which is now aligned with worlds +ve X-axis, for that I want (1,0,0). In short I want to add force on sphere relative to camera's space rather than world space if the camera rotates. – Makarand Feb 06 '17 at 19:24
  • Try removing Vector3 localVectToCam and use sphere.AddRelativeForce (controlVector * 10) instead – Absinthe Feb 06 '17 at 22:28
  • @Makarand Did you find a solution to this problem? – Ruzihm Mar 23 '22 at 21:13

1 Answers1

1

I think you want to go the other way round actually!

Transform.InverseTransformDirection converts a vector from world space into local space.

What you get as input however is a local vector on the XZ plane and Rigidbody.AddForce expects a world space vector.

You want to apply this direction according to your player objects orientation, if e.g. pressing right (your input is 1,0,0) the object shall move towards its transform.right vector.

So you rather want to convert in the opposite direction into world space to move the object in the Unity world space.

You should rather be using Transform.TransformDirection!

var worldMove = transform.TransformDirection(controlVector);
sphere.AddForce(worldMove * 10);

Or alternatively you can also just multiply by the rotation like

var worldMove = transform.rotation * controlVector;
sphere.AddForce(worldMove * 10);

However, since you are using a Rigidbody there is also Rigidbody.AddForceRelative which basically works the same way and expects a local space vector which is then internally converted into a world space force.

sphere.AddRelativeForce (controlVector * 10);
derHugo
  • 83,094
  • 9
  • 75
  • 115