Maintain fixed vision while the player turn
Hi, I have spent a week researching how I can achieve this but I didn't.
Basically, I have a player divided into three objects: the body, the head as child of the body and the camera as child of the head. The camera as usually only rotates on the x axis (up and down), the head on the other hand only rotates on the y axis (left and right). With this I get a regular view for a 3D player.
In the game you can jump from platform to platform, but these platforms can be rotated at any angle and when the player collides with them, the body is reoriented to be aligned on the y axis of these platforms. Something as if those platforms were the new ground.
My problem here is that I wanted to keep the player's vision fixed at the same point it was before the jump, even though the body is rotating towards the new orientation. This obviously does not happen since by rotating the body the head remains in its same local rotation. I just tried not to rotate the head, the problem here was that by turning the body, and not the head, the head rotates from its old orientation.
I leave here the script that controls the rotation of the player:
public class RotationRB
{
public bool lockRot;
private Transform player;
private Transform head;
private Transform myCam;
private float maxCameraRot, rotSpeed;
private int rotatingCount;
private Vector3 camRot;
public RotationRB(Transform player, Transform head, Transform cam, float maxCamRot, float rotSpeed)
{
this.player = player;
this.head = head;
myCam = cam;
maxCameraRot = maxCamRot;
this.rotSpeed = rotSpeed;
}
public void Rotate(float h, float v)
{
#region Rotacion
if (!lockRot)
{
head.Rotate(0, h, 0);
camRot = myCam.localEulerAngles + new Vector3(-v, 0, 0);
camRot.x = ClampAngle(camRot.x, -maxCameraRot, maxCameraRot);
myCam.localEulerAngles = camRot;
}
#endregion
}
float ClampAngle(float angle, float min, float max)
{
if (angle < 0f) { angle = 360 + angle; }
if (angle > 180f) { return Mathf.Max(angle, 360 + min); }
return Mathf.Min(angle, max);
}
#region Public Methods
//This method reset player rotation when touching ground before a platform
public void ResetPlayer()
{
PlayerRB.player.RotateTo(player, Quaternion.identity);
}
public Vector3 LookingDirection()
{
return myCam.TransformDirection(Vector3.forward);
}
//This coroutine rotates an obj to a new orientation and is called from player manager (PlayerRB.player.RotateTo())
public IEnumerator RotationCoroutine(Transform obj, Quaternion rot)
{
lockRot = true;
rotatingCount++;
while (obj.rotation != rot)
{
obj.rotation = Quaternion.RotateTowards(obj.rotation, rot, rotSpeed * Time.fixedDeltaTime);
yield return new WaitForFixedUpdate();
}
rotatingCount--;
if(rotatingCount == 0) lockRot = false;
}
public IEnumerator RotationCoroutine(Transform obj, Transform unrotObj, Quaternion rot)
{
lockRot = true;
rotatingCount++;
Quaternion unRot = unrotObj.rotation;
while (obj.rotation != rot)
{
obj.rotation = Quaternion.RotateTowards(obj.rotation, rot, rotSpeed * Time.fixedDeltaTime);
unrotObj.rotation = unRot;
yield return new WaitForFixedUpdate();
}
rotatingCount--;
if (rotatingCount == 0) lockRot = false;
}
#endregion
First of all thank you very much for reading and I hope that I have managed to explain. Let me know if you need any extra information or I have not explained something properly. UnityAnswers also doesn't allow me to upload a couple of gifs that I have to illustrate the explanation.