Having trouble with Vectors
Hi there.
I'm having a bit of difficulty with getting the Vector I need and thought I'd turn to the forums for help.
In my game, a camera is attached to an empty gameObject. The gameObject is located in the center of the world, and this object slowly rotates, causing the camera to pivot around the origin. The camera itself is elevated, further away from the center and is angled downward at about -40 degree rotation. Situated at the origin of the world is a flat piece of terrain which acts as an arena for players to move around on top of, and do battle on.
What I want to do is create a script that will move my player characters around in that arena relative to the camera's current orientation. When the player moves the joystick "up" or presses 'W' on the keyboard, the player's character should always move away from the camera on this 2d terrain.
In order to accomplish this, as far as I know, I first need to take the XZ vector of Camera.main.foward (relative to the camera's position) and do some kind of operation alongside the normalized 2d input vector from the players movement.
To put it another way, I need to find an operation that allows me to return a Vector2 with a bearing equal to the sum of 2 other Vector's bearings. For example, if I have two vector2s A) 0,1 (a 90 degree bearing) and B) -1, 1 ( a 135 degree bearing), I need to find an operation that will give me vector C) -1, -1 (which has a bearing of 90+135). In the above examples the first vector can be thought of as the 'cameras XZ forward facing vector' and the second vector can be thought of as the 'user axis input'.
Does anyone know what operation I therefore need to use? I thought it was Quaternion.FromToRotation that I needed, but I can't get it to work and am less sure about that now.
Here is the code I have so far:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float Speed = 3.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
//Rotate the player to always face away from the camera (on a 2d plane)
Vector3 NorthOfPlayer = new Vector3 (gameObject.transform.position.x + GetCameraNorth ().x, 1.0f, gameObject.transform.position.z + GetCameraNorth ().y);
transform.LookAt (NorthOfPlayer);
//Move the character in relation to the camera's XZ orientation
if (Input.GetAxis ("Horizontal") != 0 || Input.GetAxis ("Vertical") != 0)
{
transform.Translate (new Vector3(GetMoveDirection().x * Time.deltaTime * Speed, 0, GetMoveDirection().z * Time.deltaTime * Speed));
}
}
Vector2 GetCameraNorth ()
{
//Find the forward facing vector of the camera (relative to the camera position) if it were on a 2d plane
Vector2 CameraNorth = new Vector2 (Camera.main.transform.forward.x, Camera.main.transform.forward.z);
Vector2 Offset = CameraNorth - new Vector2(Camera.main.transform.position.x, Camera.main.transform.position.z);
return Offset.normalized;
}
Vector3 GetMoveDirection ()
{
//Get the player input as a 2d vector
Vector3 MovementInput = new Vector3 (Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical"));
Vector3 NormalizedMovementInput = MovementInput.normalized;
//Combine both the input vector and the camera vector to create the desired direction for the player character to eventually move
Quaternion q = Quaternion.FromToRotation (Vector3.up, NormalizedMovementInput);
Vector3 CameraNorthVec3 = new Vector3 (GetCameraNorth().x, 0, GetCameraNorth().y);
Vector3 v = q * CameraNorthVec3;
return v;
}
}
Thought Id add a picture to help clear up what I mean. If I already know vectors A and B, then I'd like an operation that gives me Vector C. A = Camera's XZ forward vector B = Player Input C = Desired move direction
You wrote you were posting to the Forums. Just checking - there is a Unity Forum site, but this isn't it (see the top bar.) I moved this into the UnityAnswer HelpRoom, just in case.
It sounds like you're missing rotation addition: q1*q2. FromToRotation(A,B) is sort of like subtraction: it solves A+__=B. A common way to solve, what I think is your problem, is to do whatever math, then add cameraOrPlayerSpin*calculatedDirection at the end.
@Owen-Reynolds I use the term forum loosely; I didn't think semantics would matter. Essentially I was just hoping someone could help answer my query, which is why I turned to Unity Answers. Could you please return my question to the answers section where people might be able to help me? Best wishes and Thankyou.
Regarding your answer, I'm willing to go down the route, of doing the mathematics to find out what the calculated direction is (that is essentially what i am asking how to do in this post), but I need help with that (i.e. how to turn a vector 2 into an angle/bearing, and then how to turn it back again). Alternatively if it is 'rotation addition' I need, could you point me to the function I need to perform this? I see you wrote down q1 and q2, but I have no idea what these (presumably quaternions) are referring to. I apologize if this comes across newbyish, but I find it very hard to understand quaternions, and so typically just do what I'm told with how to use them and pray.
Answer by ElijahShadbolt · Oct 13, 2016 at 02:15 AM
You could project the Camera's forward and right vectors onto the xz plane, then just use those 3D vectors like so
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float Speed = 3.0f;
void Update()
{
float inputVert = Input.GetAxis("Vertical");
float inputHorz = Input.GetAxis("Horizontal");
Vector3 normal = Vector3.up;
Vector3 right = Vector3.ProjectOnPlane(Camera.main.transform.right, normal).normalized; // camera's right vector projected onto xz plane
Vector3 forward = Vector3.ProjectOnPlane(Camera.main.transform.forward, normal).normalized; // camera's forward vector projected onto xz plane
if (forward != Vector3.zero) // if vector is zero, Quaternion.LookRotation would throw an error
transform.rotation = Quaternion.LookRotation(forward); // look along the xz plane according to the camera's forward
if (inputHorz != 0f) // if moving right/left
{
transform.position += right * inputHorz * Speed * Time.deltaTime; // move along camera's right
}
if (inputVert != 0f) // if moving forward/backward
{
transform.position += forward * inputVert * Speed * Time.deltaTime; // move along camera's forward
}
}
}