Search Unity

[SOLVED] Rotate Camera around player using non-parented camera?

Discussion in 'Scripting' started by topherbwell, Jun 8, 2015.

  1. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    I am currently using a camera that is following the player by script, from a near top down view. This is allowing for the player to rotate toward or away from the camera, which is what I want, but when the character moves behind walls it can be problematic. I am looking for a way to make the camera rotate around the character when mouse+right mouse held down, and for the camera to stay in said position until readjusted again using mouse+right mouse button.

    Here is the move script and the camerafollow script that I am currently using.
    Code (csharp):
    1.  
    2. usingUnityEngine;
    3. usingSystem.Collections;
    4.  
    5. public class topDownMovement : MonoBehaviour
    6. {
    7.      public float speed = 10.0F;
    8.      public float rotationSpeed = 100.0F;
    9.      
    10.      void Update() {   //"Strafe" is a custom axis I set up in the input manager
    11.           float strafe = Input.GetAxis ("Strafe") * speed;
    12.           float translation = Input.GetAxis("Vertical") * speed;
    13.           float rotation = Input.GetAxis("Horizontal") * rotationSpeed;
    14.  
    15.           strafe *= Time.deltaTime;
    16.           translation *= Time.deltaTime;
    17.           rotation *= Time.deltaTime;
    18.           transform.Translate(strafe, 0, 0);
    19.           transform.Translate(0, 0, translation);
    20.           transform.Rotate(0, rotation, 0);
    21.     }
    22. }
    23.  
    Code (csharp):
    1.  
    2. usingUnityEngine;
    3. usingSystem.Collections;
    4.  
    5. public class cameraFollowPlayer : MonoBehaviour
    6. {
    7.      public GameObject target; //target is the player object
    8.      public float xOffset = 0;
    9.      public float yOffset = 0;
    10.      public float zOffset = 0;
    11.  
    12. void LateUpdate() {
    13. this.transform.position = newVector3(target.transform.position.x + xOffset, target.transform.position.y + yOffset, target.transform.position.z + zOffset);
    14.  
    15.  }
    16. }
    17.  
     
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    I'll give you a quick answer now, and I'll give you a more detailed answer if you need me to.

    Change your floats xOffset, yOffset, zOffset into a Vector3 offset. After that, you can rotate it like this:
    Code (CSharp):
    1. offset = Quaternion.Euler(xDegrees, yDegrees, zDegrees) * offset;
    put in any numbers you want for xDegrees, yDegrees, and zDegrees (don't forget to multiple Time.deltaTime), and keep in mind when you multiply Quaternions and vectors, you MUST have the quaternion first. (Quaternion * vector, NOT vector * Quaternion)
     
    topherbwell likes this.
  3. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Thank you so much for the prompt response. I am new to Unity and Scripting, so the context of this went a bit over my head. If you do have time for a more detailed explanation on this, I would appreciate it. I can't believe how helpful the Unity community has been so far!
     
  4. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Well the offset is basically how far away from the player the camera is, so the camera position will be the player position + the offset.

    You can image the offset vector as a line from the player to the camera. When you rotate the vector, it will rotate around the player, but keeps it's length, giving you the "rotate around" effect as opposed to "rotate in place".

    A quaternion is a fancy way of storing rotation information and solves a problem called "Gimbal lock", but that's a bit advanced, so for now know that it's a rotation and quaternions are usually difficult to use and understand. Luckily for us, Unity does the tricky work so we can view and set quaternions as x, y, and z rotations in degrees. Quaternion.Euler() will create a quaternion with the passed-in degree values, and quaternion.eulerAngles will get the degree values out of an existing quaternion. A quaternion * a vector will give you that vector rotated by that quaternion.

    In case you're not familiar with Vector math, Vectors can be many things, but they are usually positions OR direction. Learning to use them both ways will make your programming life a lot easier. Normalized vectors and their usefulness is another good thing to know.
     
    topherbwell likes this.
  5. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    After reading your comments I was able to do some more informed searches. I found this script in the forums which pretty much does what I am looking for, except I would like for the camera to start behind the character, and this seems to just start in random place. It does work, though. I am going to see if I can figure out how to make the rotate be rightclick+plus mouse rather than just mouse. Thank you again! This has been very helpful!
    Code (csharp):
    1.  
    2. usingUnityEngine;
    3. usingSystem.Collections;
    4.  
    5. public class OrbitCamera : MonoBehaviour {
    6.  
    7.      public float turnSpeed = 4.0f;
    8.      public Transform player;
    9.  
    10.      private Vector3 offset;
    11.  
    12.      voidStart ()
    13.       {
    14.      offset = newVector3(player.position.x, player.position.y + 8.0f, player.position.z + 7.0f);
    15.       }
    16.  
    17.       voidLateUpdate()
    18.       {
    19.      offset = Quaternion.AngleAxis (Input.GetAxis("Mouse X") * turnSpeed, Vector3.up) * offset;
    20.      transform.position = player.position + offset;
    21.      transform.LookAt(player.position);
    22.       }
    23. }
    24.  
     
  6. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Here is the camera script now. This is attached to a camera, let the player turn independently of the camera, and allows the camera to orbit the player when the the user holds down right mouse button and moves mouse left or right. But this does not follow the player if the right mouse button is held down. Please help.

    If anyone can help, I would like to improve this by making the camera zoom towards/away from the player by using the mouse wheel! Any help appreciated!

    Code (csharp):
    1.  
    2. usingUnityEngine;
    3. usingSystem.Collections;
    4.  
    5. public class OrbitCamera : MonoBehaviour {
    6.  
    7.      public float turnSpeed = 4.0f;
    8.      publicTransform player;
    9.  
    10.      private Vector3 offset;
    11.  
    12.      void Start ()
    13.           {
    14.           offset = newVector3(player.position.x, player.position.y + 8.0f, player.position.z + 7.0f);
    15.            }
    16.  
    17.      void LateUpdate()
    18.           {
    19.           if (Input.GetMouseButton (1)) {
    20.           offset = Quaternion.AngleAxis (Input.GetAxis ("Mouse X") * turnSpeed, Vector3.up) * offset;
    21.           transform.position = player.position + offset;
    22.           transform.LookAt (player.position);
    23.            }
    24.       }
    25. }
    26.  
     
    Last edited: Jun 9, 2015
  7. manlaikin1994

    manlaikin1994

    Joined:
    May 15, 2015
    Posts:
    179
  8. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    To clarify, I only want the camera to orbit when right mouse button is held down, but I want the camera to follow player at all times. I want the orbit to lock when right mouse is not held down, so that the cursor is free to move about the screen without moving the camera. Any help appreciated!
     
  9. manlaikin1994

    manlaikin1994

    Joined:
    May 15, 2015
    Posts:
    179
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class OrbitCamera : MonoBehaviour
    5. {
    6.  
    7.     public float turnSpeed = 4.0f;
    8.     public Transform player;
    9.    
    10.     private Vector3 offset;
    11.    
    12.     void Start ()
    13.     {
    14.         offset = new Vector3(player.position.x, player.position.y + 8.0f, player.position.z + 7.0f);
    15.     }
    16.    
    17.     void LateUpdate()
    18.     {
    19.         transform.position = player.position + offset;
    20.         transform.LookAt (player.position);
    21.  
    22.  
    23.         if (Input.GetMouseButton (1))
    24.         {
    25.             offset = Quaternion.AngleAxis (Input.GetAxis ("Mouse X") * turnSpeed, Vector3.up) * offset;
    26.         }
    27.     }
    28.  
    29. }
    30.  
    Do u mean sth like this...?
     
  10. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Not something like that. EXACTLY like that! Thank you so much! I copy/pasted and that is doing exactly what I was trying to do.