Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Player spin (rotation) but not the camera - Using mouse for direction

Discussion in 'Getting Started' started by fernandrolona, Mar 13, 2020.

  1. fernandrolona

    fernandrolona

    Joined:
    Feb 8, 2020
    Posts:
    3
    I'm not good in English, so I'm sorry already.

    I want to do the following:
    When my player jumps, let him spin around the Z axis like a special hability.

    The problem:
    I am using a script in which it is possible to move with the AWSD keys and using the mouse to turn, the player walks forward in the direction of the mouse.
    The camera is as a child of the Player.

    Until the moment everything is ok, but when I spin the player, the camera rotates along the Z axis!

    What I need:
    The camera follows the player, the mouse makes the player turn and the camera keeps "0" at Z axis when the player spins.
    It is a 3-person shooter, in which the player has to aim and walk in the direction of the mouse.


    My script to the camera:


    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class FollowPlayer : MonoBehaviour
    {
    public float mouseSensitivity = 100f;
    public float speed = 5;
    public Transform playerBody;
    float xRotation = 0f;
    // Start is called before the first frame update
    void Start()
    {
    Cursor.lockState = CursorLockMode.Locked;
    }
    // Update is called once per frame
    void Update()
    {
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
    xRotation -= mouseY;
    xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
    playerBody.Rotate(Vector3.up * mouseX);
    }
    }


    Thank you!!
     
  2. Gordon_G

    Gordon_G

    Joined:
    Jun 4, 2013
    Posts:
    358
    Get the offset vector between camera and player, rotate the camera, and position according to the offset- in pseudo code:
    1. Vector3 offsetV = camera position - player position
    2. Rotate the player first.
    3. Rotate the camera about its local axis in the opposite direction of the player rotation:
    camera localRotation = Quaternion.Inverse( player.transform.rotation )​
    4. adjust the camera position using the offset:
    camera position = camera localRotation * offsetV + player position
    I think that should work.

    note, you should make sure you're getting and setting all the positions in world coordinates - I think everything above does, but just keep an eye!
     
    Last edited: Mar 13, 2020
  3. fernandrolona

    fernandrolona

    Joined:
    Feb 8, 2020
    Posts:
    3

    How are you doing? I thank you! I understood what you meant but acted kind of weird ...
    The player is rotating to the right, and the camera rotates to the left, around the Z axis.
    Did I do it wrong? I'm still new to Unity 3D
    The camera is as a child and the Player parent.
    Here is the code with your suggestion:

    public class FollowPlayer : MonoBehaviour
    {
    public float mouseSensitivity = 100f;
    public float speed = 5;
    public Transform playerBody;
    public GameObject player;
    Vector3 offsetV;
    float xRotation = 0f;
    // Start is called before the first frame update
    void Start()
    {
    Cursor.lockState = CursorLockMode.Locked;
    offsetV = transform.position - player.transform.position;
    }
    // Update is called once per frame
    void Update()
    {
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
    xRotation -= mouseY;
    xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
    playerBody.Rotate(Vector3.up * mouseX);
    transform.localRotation = Quaternion.Inverse(player.transform.rotation);
    transform.position = transform.localRotation * offsetV + player.transform.position;
    }
    }

    It is as if the Z axis were a bearing the moment the player spins. It has to rotate independently of the camera, imagine you looking at a wheel in a suspended car facing the wheel and it spinning to the right

    Thanks for your attention =D
     
    Last edited: Mar 13, 2020
  4. Gordon_G

    Gordon_G

    Joined:
    Jun 4, 2013
    Posts:
    358
    First don't do this step: transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);

    You're taking care of the camera rotation after you rotate the player, by doing the opposite of the player rotation - that is assuming you don't want the camera to rotate at all if the player rotates.

    So, if the player rotates, you need to undo that for the camera, and you need to then reset the camera's position with respect to the player position. I think that's what the code I gave you does, but it's late here in the middle east where I live and my mind is getting a little fuzzy after coding all day!

    If removing that line above doesn't fix it, maybe it's a world vs local problem - try it without local rotation.

    But you know, you could just skip the hassle and unparent the camera from the player. Put your movement code on the player, and when your player moves just update the position of the camera using a fixed offset. Then you don't have to worry about what happens when your player rotates.
     
  5. fernandrolona

    fernandrolona

    Joined:
    Feb 8, 2020
    Posts:
    3
    Hahaha sorry for the trouble!! And thank you so much! Worked! =DD
     
  6. Gordon_G

    Gordon_G

    Joined:
    Jun 4, 2013
    Posts:
    358
    No problem - I ended up fiddling with this and it's a difficult problem. I got working after a fashion, but it was much simpler than I was trying to make it. But it's not perfect - the problem is reversing the parent rotation on the child reveals one of the difficulties with rotations. As long as the camera xyz was aligned with the object, then the camera just rotates on y (in world coordinates) as the player does. But as soon as the camera is at some angle, then rotating on y also rotates the other angles.

    Sorry for the trouble from my end, and glad to hear you got it working!