- Home /
Why is my movement inverted to the changed camera angle?
Hi all,
I'm making a simple 3th person movement script. I have a camera following the character and whilst pressing right mouse button the camera orbits around the character nicely. The character then snaps into the direction of the camera when a movement command is given.
Now the problem I have is that after if move the camera to face one of the sides and move the character that the actual movement angles move to the opposite sides.
I tried to make my question clearer with a drawing. This is a top-down view of my character. As you can see in the drawing when I move my camera 90° to one side and want to move forward the forward movement is actually moving the character backwards. And when I move my camera 45° to one side the movement changes 45° degrees to the opposite side. When I move my camera 180° all the controls are normal.
It is like the movement vectors are moving in an equal angle to the opposite side of the camera movement I have this problem at any change of camera angle.
I'm very new to scripting and Unity3D so I'm not sure if this problem might lie in a wrong Unity3D setting or in an actual scripting flaw.
Hope someone could point me to where my error might be.
Thank you.
using UnityEngine;
using System.Collections;
public class TP_Controller: MonoBehaviour
{
public static CharacterController CharacterController;
public static TP_Controller Instance;
void Awake()
{
CharacterController = GetComponent("CharacterController") as CharacterController;
Instance = this;
TP_Camera.UseExistingOrCreateNewMainCamera();
}
void Update()
{
if (Camera.mainCamera == null)
{
return;
}
GetLocomotionInput();
TP_Motor.Instance.UpdateMotor();
}
void GetLocomotionInput()
{
// Deze var aanpassen voor deadzone.
var deadZone = 0.1f;
TP_Motor.Instance.MoveVector = Vector3.zero;
if (Input.GetAxis("Vertical") > deadZone || Input.GetAxis("Vertical") < -deadZone)
TP_Motor.Instance.MoveVector += new Vector3(0 , 0, Input.GetAxis ("Vertical"));
if (Input.GetAxis("Horizontal") > deadZone || Input.GetAxis("Horizontal") < -deadZone)
TP_Motor.Instance.MoveVector += new Vector3(Input.GetAxis ("Horizontal"), 0, 0);
}
}
using UnityEngine;
using System.Collections;
public class TP_Camera : MonoBehaviour
{
public static TP_Camera Instance;
public Transform TargetLookAt;
public float Distance = 5f;
public float DistanceMin = 3f;
public float DistanceMax = 10f;
public float DistanceSmooth = 0.05f;
public float X_MouseSensitivity = 5f;
public float Y_MouseSensitivity = 5f;
public float MouseWheelSensitivity = 5f;
public float X_Smooth = 0.05f;
public float Y_Smooth = 0.1f;
public float Y_MinLimit = -40f;
public float Y_MaxLimit = 80f;
private float mouseX = 0f;
private float mouseY = 0f;
private float velX = 0f;
private float velY = 0f;
private float velZ = 0f;
private float velDistance = 0f;
private float startDistance = 0f;
private Vector3 position = Vector3.zero;
private Vector3 desiredPosition = Vector3.zero;
private float desiredDistance = 0f;
void Awake()
{
Instance = this;
}
void Start()
{
Distance = Mathf.Clamp(Distance, DistanceMin, DistanceMax);
startDistance = Distance;
Reset();
}
void LateUpdate()
{
if (TargetLookAt == null)
return;
HandlePlayerInput();
CalculateDesiredPosition();
UpdatePosition();
}
void HandlePlayerInput()
{
var deadZone = 0.01f;
if (Input.GetMouseButton(1))
{
// The RMB is down get mouse Axis input
mouseX += Input.GetAxis("MouseX") * X_MouseSensitivity;
mouseY -= Input.GetAxis("MouseY") * Y_MouseSensitivity;
}
// This is where the limit of the mouseY is implemented
mouseY = Helper.ClamAngle(mouseY, Y_MinLimit, Y_MaxLimit);
if (Input.GetAxis("Mouse ScrollWheel") < -deadZone || Input.GetAxis("Mouse ScrollWheel") > deadZone)
{
desiredDistance = Mathf.Clamp(Distance - Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity,
DistanceMin, DistanceMax);
}
}
void CalculateDesiredPosition()
{
// Evaluate distance
Distance = Mathf.SmoothDamp(Distance, desiredDistance, ref velDistance, DistanceSmooth);
// Calculate desired position
desiredPosition = CalculatePosition(mouseY, mouseX, Distance);
}
Vector3 CalculatePosition(float rotationX, float rotationY, float distance)
{
Vector3 direction = new Vector3(0, 0, -distance);
Quaternion rotation = Quaternion.Euler(rotationX, rotationY, 0);
return TargetLookAt.position + rotation * direction;
}
void UpdatePosition()
{
var posX = Mathf.SmoothDamp(position.x, desiredPosition.x, ref velX, X_Smooth);
var posY = Mathf.SmoothDamp(position.y, desiredPosition.y, ref velY, Y_Smooth);
var posZ = Mathf.SmoothDamp(position.z, desiredPosition.z, ref velZ, X_Smooth);
position = new Vector3(posX,posY,posZ);
transform.position = position;
transform.LookAt(TargetLookAt);
}
public void Reset()
{
mouseX = 0;
mouseY = 10;
Distance = startDistance;
desiredDistance = Distance;
}
public static void UseExistingOrCreateNewMainCamera()
{
GameObject tempCamera;
GameObject targetLookAt;
TP_Camera myCamera;
if (Camera.mainCamera != null)
{
tempCamera = Camera.mainCamera.gameObject;
}
else
{
tempCamera = new GameObject("Main Camera");
tempCamera.AddComponent("Camera");
tempCamera.tag = "MainCamera";
}
tempCamera.AddComponent("TP_Camera");
myCamera = tempCamera.GetComponent("TP_Camera") as TP_Camera;
targetLookAt = GameObject.Find ("targetLookAt") as GameObject;
if (targetLookAt == null)
{
targetLookAt = new GameObject("targetLookAt");
targetLookAt.transform.position = Vector3.zero;
}
myCamera.TargetLookAt = targetLookAt.transform;
}
}
using UnityEngine;
using System.Collections;
public class TP_Motor : MonoBehaviour
{
public static TP_Motor Instance;
public float MoveSpeed = 10f;
public Vector3 MoveVector { get; set; }
void Awake()
{
Instance = this;
}
public void UpdateMotor()
{
SnapAlignCharacterWithCamera();
ProcessMotion();
}
void ProcessMotion()
{
// Transform MoveVector to World Space
MoveVector = transform.InverseTransformDirection (MoveVector);
// Normalize MoveVector if Magnitude > 1
if (MoveVector.magnitude > 1)
{
MoveVector = Vector3.Normalize(MoveVector);
}
// Multiply MoveVector by MoveSpeed
MoveVector *= MoveSpeed;
// Multiply MoveVector by DeltaTime
MoveVector *= Time.deltaTime;
// Move the Caracter in World Space
TP_Controller.CharacterController.Move(MoveVector);
}
void SnapAlignCharacterWithCamera()
{
if(MoveVector.x != 0 || MoveVector.z != 0)
{
transform.rotation = Quaternion.Euler(transform.eulerAngles.x, Camera.mainCamera.transform.eulerAngles.y, transform.eulerAngles.z);
}
}
}
using UnityEngine;
using System.Collections;
public static class Helper
{
public static float ClamAngle(float angle, float min, float max)
{
do
{
if(angle < -360)
angle += 360;
if(angle > 360)
angle -= 360;
} while (angle < -360 || angle > 360);
return Mathf.Clamp (angle, min, max);
}
}
Probably not the cleanest solution but see if the formulas in this code helps with your problem? It is supposed to let the character move forward/backward/etc relative to how the camera is facing.
public void OnInput_AWSD$$anonymous$$ovement(int param)
{
reachedInteractTarget = false; // to turn off auto move in case it was on
switch (param)
{
case 1: // Forward
{
if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[5])) _actor.$$anonymous$$ove(_camTr.forward - _camTr.right, true); // left is held too
else if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[6])) _actor.$$anonymous$$ove(_camTr.forward + _camTr.right, true); // right is held too
else _actor.$$anonymous$$ove(_camTr.forward, true);
} break;
case 2: // Backward
{
if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[5])) _actor.$$anonymous$$ove((_camTr.forward * -1) - _camTr.right, true); // left is held too
else if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[6])) _actor.$$anonymous$$ove((_camTr.forward * -1) + _camTr.right, true); // right is held too
else _actor.$$anonymous$$ove(_camTr.forward * -1, true);
} break;
case 3: // Left
{
if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[3])) _actor.$$anonymous$$ove((_camTr.right * -1) + _camTr.forward, true); // foward is held too
else if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[4])) _actor.$$anonymous$$ove((_camTr.right + _camTr.forward) * -1, true); // backward is held too
else _actor.$$anonymous$$ove(_camTr.right * -1, true);
} break;
case 4: // Right
{
if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[3])) _actor.$$anonymous$$ove(_camTr.right + _camTr.forward, true); // foward is held too
else if (Input$$anonymous$$anager.Instance.IsActive(inputIdx[4])) _actor.$$anonymous$$ove(_camTr.right - _camTr.forward, true); // backward is held too
else _actor.$$anonymous$$ove(_camTr.right, true);
} break;
}
}
You need to post your script. Without a script all anyone will have is guesses.
Ok added all my scripts since I'm unsure where the flaw may be.
Sorry for the wall of text.
@Leslie; your script looks useful but I would like to know if there is an easier way to fix my problem.
Thank you