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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

When camera rotates, player rotates too

Discussion in 'Scripting' started by Innos, May 5, 2015.

  1. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Hello again,

    I have a 3rd person camera script which I got from 3dbuzz. I don't know how many of you have played the legendary gothic from piranha bytes, but I am trying to accomplist the same thing. When I move my mouse (without pressing right or left mouse button) the 3rd person character rotates to where the mouse is rotating.
    The current script that I have make the character rotate to where camera rotates when left mouse button is pressed and if he is idle, the camera rotates around him without making him to rotate too. So how will I be able to do so?
    Here is my current camera script in case you need it :D
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class TP_Camera : MonoBehaviour {
    4.     public static TP_Camera Instance;
    5.     public Transform TargetLookAt;
    6.     public float Distance = 5f;
    7.     public float DistanceMin = 3f;
    8.     public float DistanceMax = 10f;
    9.     private float mouseX = 0f;
    10.     private float mouseY = 0f;
    11.     private float startDistance = 0f;
    12.     private float desiredDistance = 0f;
    13.     public float X_Mouse_Sensitivity = 5f;
    14.     public float Y_Mouse_Sensitivity = 5f;
    15.     public float MouseWheelSensitivity = 5f;
    16.     public float Y_MinLimit = -40f;
    17.     public float Y_MaxLimit = 80f;
    18.     public float DistanceSmooth = 0.05f;
    19.     private float velDistance = 0f;
    20.     private Vector3 desiredPosition = Vector3.zero;
    21.     public float X_Smooth = 0.05f;
    22.     public float Y_Smooth = 0.1f;
    23.     private float VelX = 0f;
    24.     private float VelY = 0f;
    25.     private float VelZ = 0f;
    26.     private Vector3 position = Vector3.zero;
    27.     void Awake()
    28.     {
    29.         Instance = this;
    30.     }
    31.     void Start ()
    32.     {
    33.         Distance = Mathf.Clamp (Distance, DistanceMin, DistanceMax);
    34.         startDistance = Distance;
    35.         Reset ();
    36.  
    37.     }
    38.  
    39.     void LateUpdate ()
    40.     {
    41.         if (TargetLookAt == null)
    42.             return;
    43.         HandlePlayerInput ();
    44.         CalculateDesiredPosition ();
    45.         UpdatePosition ();
    46.  
    47.     }
    48.     void UpdatePosition()
    49.     {
    50.         var posX = Mathf.SmoothDamp (position.x, desiredPosition.x, ref VelX, X_Smooth);
    51.         var posY = Mathf.SmoothDamp (position.y, desiredPosition.y, ref VelY, Y_Smooth);
    52.         var posZ = Mathf.SmoothDamp (position.z, desiredPosition.z, ref VelZ, X_Smooth);
    53.         position = new Vector3 (posX, posY, posZ);
    54.         transform.position = position;
    55.         transform.LookAt (TargetLookAt);
    56.     }
    57.  
    58.     void CalculateDesiredPosition()
    59.     {
    60.         //evaluate distance
    61.         Distance = Mathf.SmoothDamp (Distance, desiredDistance, ref velDistance, DistanceSmooth);
    62.         //calculate desired position
    63.         desiredPosition = CalculatePosition (mouseY, mouseX, Distance);
    64.     }
    65.     Vector3 CalculatePosition(float rotationX, float rotationY, float distance)
    66.     {
    67.         Vector3 Direction = new Vector3 (0, 0, -distance);
    68.         Quaternion rotation = Quaternion.Euler (rotationX, rotationY, 0);
    69.         return TargetLookAt.position + rotation * Direction;
    70.     }
    71.     void HandlePlayerInput()
    72.     {
    73.         var deadzone = 0.1f;
    74.         if (Input.GetMouseButton (1)) {
    75.             //if The Right Mouse Button is pressed,get axis
    76.             mouseX += Input.GetAxis ("Mouse X") * X_Mouse_Sensitivity;
    77.             mouseY -= Input.GetAxis ("Mouse Y") * Y_Mouse_Sensitivity;
    78.         }
    79.         mouseY = Helper.ClampAngle (mouseY, Y_MinLimit, Y_MaxLimit);
    80.         if (Input.GetAxis ("Mouse ScrollWheel") < -deadzone || Input.GetAxis ("Mouse ScrollWheel") > deadzone)
    81.         {
    82.             desiredDistance = Mathf.Clamp(Distance - Input.GetAxis ("Mouse ScrollWheel") * MouseWheelSensitivity, DistanceMin, DistanceMax);
    83.         }
    84.  
    85.     }
    86.     public void Reset()
    87.     {
    88.         mouseX = 0;
    89.         mouseY = 10;
    90.         Distance = startDistance;
    91.         desiredDistance = Distance;
    92.     }
    93.     public static void UseExistingOrCreateNewMainCamera()
    94.     {
    95.         GameObject tempCamera;
    96.         GameObject targetLookAt;
    97.         TP_Camera myCamera;
    98.         if (Camera.main != null)
    99.         {
    100.             tempCamera = Camera.main.gameObject;
    101.         }
    102.         else
    103.         {
    104.             tempCamera = new GameObject("Main Camera");
    105.             tempCamera.AddComponent<Camera>();
    106.             tempCamera.tag = "Main Camera";
    107.         }
    108.         tempCamera.AddComponent<TP_Camera>();
    109.         myCamera = tempCamera.GetComponent("TP_Camera") as TP_Camera;
    110.         targetLookAt = GameObject.Find("targetLookAt")as GameObject;
    111.         if (targetLookAt == null)
    112.         {
    113.             targetLookAt = new GameObject("targetLookAt");
    114.             targetLookAt.transform.position = Vector3.zero;
    115.         }
    116.         myCamera.TargetLookAt = targetLookAt.transform;
    117.     }
    118. }
    119.  
    Thanks in advance!
     
  2. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    bump. Anyone?
     
  3. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Found this code for the camera but seems little off :/ It is slow actually, when I move my mouse, the player rotates after 1-2 seconds and doesn't rotate smoothly :/ any ideas?
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class LookAtMouse : MonoBehaviour
    4. {
    5.     // speed is the rate at which the object will rotate
    6.     public float speed;
    7.     void FixedUpdate ()
    8.     {
    9.         // Generate a plane that intersects the transform's position with an upwards normal.
    10.         Plane playerPlane = new Plane(Vector3.up, transform.position);
    11.         // Generate a ray from the cursor position
    12.         Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    13.         // Determine the point where the cursor ray intersects the plane.
    14.         // This will be the point that the object must look towards to be looking at the mouse.
    15.         // Raycasting to a Plane object only gives us a distance, so we'll have to take the distance,
    16.         //   then find the point along that ray that meets that distance.  This will be the point
    17.         //   to look at.
    18.         float hitdist = 0.0f;
    19.         // If the ray is parallel to the plane, Raycast will return false.
    20.         if (playerPlane.Raycast (ray, out hitdist))
    21.         {
    22.             // Get the point along the ray that hits the calculated distance.
    23.             Vector3 targetPoint = ray.GetPoint(hitdist);
    24.             // Determine the target rotation.  This is the rotation if the transform looks at the target point.
    25.             Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
    26.             // Smoothly rotate towards the target point.
    27.             transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
    28.         }
    29.     }
    30. }
     
  4. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    for those of us who haven't played Gothic, could you explain what it is you are trying to achieve? maybe with some pseudocode so we can see the logic clearly?
     
  5. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Thanks for replying mate!
    What I am trying to do is when mouse axis goes right, the player camera(which is a child of player) faces right and so does the player, when mouse axis goes left, the player camera faces left and so does the player.
    here is a video to show you what I want to do:

    Look how the player reacts when mouse is moved right or left(without holding any mouse button)
     
  6. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,887
    You need to start with the basics. Rotating a character in code is the same as in the editor. You have to change their Transform > Rotation > Y when you move the mouse left/right.

    You can use Transform.Rotate to make this easier.

    So get your mouse delta:
    Code (CSharp):
    1. float mouseX = Input.GetAxis("Mouse X");
    Then just get your character's Transform component:
    Code (CSharp):
    1. public Transform characterT;
    Now just use the Rotate function that comes with Transform to change it.
    Code (CSharp):
    1. characterT.Rotate(0f, mouseX, 0f);
    Now make the camera face the same way as the character.

    The easiest is to have a GameObject hierarchy of
    CameraParent (put code on this) > CameraGO (actual camera). Move the CameraGO back, then just position/rotate the CameraParent to match the characterT.
    Code (CSharp):
    1. cameraParent.transform.position = characterT.position;
    2. cameraParent.transform.rotation = characterT.rotation;
     
    blizzy likes this.
  7. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Thanks very much for hepling! But because I am a newbie, in both programming and in unity I have some questions :D
    I have adjusted this code on my script but I get an error that cameraParent does not exist in the current context, so I guess I will have to declare cameraParent in some way?

    Also characterT is my char's tag? if not, how will the code know where to adjust the characterT code to?
     
  8. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,887
    The code will be something like this...

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerControllerScript : MonoBehaviour {
    5.  
    6.     void Update()
    7.     {
    8.         // GET MOUSE DELTA/MOVEMENT
    9.         float mouseX = Input.GetAxis("Mouse X");
    10.  
    11.         // ROTATE PLAYER ON Y AXIS
    12.         transform.Rotate(0f, mouseX, 0f)
    13.     }
    14.  
    15. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CameraParentScript : MonoBehaviour {
    5.  
    6.     public Transform followThis; // Click-drag your Player in here.
    7.  
    8.     void Update()
    9.     {
    10.         transform.position = followThis.position;
    11.         transform.rotation = followThis.rotation;
    12.     }
    13.  
    14. }
     
  9. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    I bow to your wisdom!!! Thanks a bunch! So simple code, yet so hard to think of!
     
  10. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Now I tried to imply based on what you taught me :D, to make the player rotate on x axis so he will be able to look up and down.(ie, player wants to see the skybox or wants to see a flower which is on his feet)
    I configured it to this
    Code (CSharp):
    1. void Update()
    2.     {
    3. / GET MOUSE DELTA/MOVEMENT
    4.         float mouseX = Input.GetAxis("Mouse X");
    5.         float mouseY = Input.GetAxis ("Mouse Y");
    6.      
    7.         // ROTATE PLAYER ON Y AXIS
    8.         transform.Rotate (0f, mouseX, 0f);
    9.         //rotate player on x axis
    10.         transform.Rotate (mouseY, 0f,0f);
    11. }
    But now when I run and move my mouse up or down, the player either runs flying or runs under the ground :D
    So I will have to make him stay always grounded while rotating... Hmmm
    Well I tried using a rigid body and freeze my player on x axis or even y axis and had some really weird results which are not the acceptable ones...
    Any ideas?

    Thanks in advance!
     
  11. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,887
    Yeah, you have to move the camera up/down, not the player. The player should only rotate on the Y, not the X. CharacterControllers will only work when they are upright.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CameraParentScript : MonoBehaviour {
    5.  
    6.     public Transform followThis; // Click-drag your Player in here.
    7.  
    8.     void Update()
    9.     {
    10.         // MATCH POSITION
    11.         transform.position = followThis.position;
    12.  
    13.         // MATCH POSITION (smooth version example)
    14.         //transform.position = Vector3.Lerp(transform.position, followThis.position, 1f * Time.deltaTime);
    15.  
    16.         // GET OFFSET (Mouse movement on X axis)
    17.         Vector3 offset = new Vector3(Input.GetAxis("Mouse Y"), 0f, 0f);
    18.  
    19.         // MATCH ROTATION (Add offset - note you have to Multiply instead of "+" when using Quaternions)
    20.         transform.rotation = followThis.rotation * Quaternion.Euler(offset);
    21.     }
    22.  
    23. }
    24.  
    Now it should make the rotation equal to the player, but then adds on the mouse movement (offset).
     
    Last edited: May 8, 2015
  12. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Thanks for helping!
    I modified the code to the code your wrote and now when I try to move up or down, seems like it tries to do it and then immediately goes back to default view... Either if I move up or down it will only move so little that it's hard to see that it actually made a tiny slight move up or down.
    Looking at camera inspector while trying it I see that x and z axis are changing numbers(good thing) when I try to to move up or down and then it goes immediately back to zero(which should stay where we left it if mouse isn't moving anymore,right?).Why the values are beeing resseted?

    btw
    This rocks!
     
    Last edited: May 8, 2015
  13. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
  14. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,887
    Oops try this. Line 17 was making a new Vector3 (0,0,0) every time, resetting it, instead of adding to what was already there.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class CameraParentScript : MonoBehaviour {
    4.  
    5.     public Transform followThis; // Click-drag your Player in here.
    6.     public Vector3 offset;       // Mouse movement will be stored in here.
    7.  
    8.     void Update()
    9.     {
    10.         // MATCH POSITION
    11.         transform.position = followThis.position;
    12.  
    13.         // GET OFFSET (Add mouse movement on X axis)
    14.         offset += new Vector3(Input.GetAxis("Mouse Y"), 0f, 0f);
    15.  
    16.         // MATCH ROTATION & ADD OFFSET (Note you have to Multiply instead of "+" when using Quaternions)
    17.         transform.rotation = followThis.rotation * Quaternion.Euler(offset);
    18.     }
    19. }
     
    Last edited: May 11, 2015
  15. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    You're the best! It works!
     
  16. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    And if I want my camera to not rotate on 360 degrees on x axis, but only 60 degrees, how should I approach it?

    Thanks in advance!
     
  17. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,887
    Try something like:
    Code (csharp):
    1. offset.x = Mathf.Clamp(offset.x, -60f, 60f);
    Put it in under Line 14.
     
  18. Innos

    Innos

    Joined:
    Apr 17, 2015
    Posts:
    21
    Works! Thanks again!