Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How can i make a camera rotate automatically after a while around a object

Discussion in 'Scripting' started by Rachzella, Sep 14, 2019.

  1. Rachzella

    Rachzella

    Joined:
    Oct 9, 2015
    Posts:
    78
    Hello coders, I have a simple question.
    I have been playing this game recently and i wanted to have the camera mechanics much like it, as it's well done, useful. and looks great. The camera system i'm talking about is the garage camera in CSR 2, if you don't know what it is i'll explain. When you are in the garage. the camera is set to the car. and can't move in different position then rotating around it. From up to down till the floor coliders, and the top view. and left to right around the vehicle. the camera starts roltating automatically after 30 seconds of inactivity. but you can also use the touch screen to roltate it. i wanted to do this myself. but i didn't get the camera to work with it. Does anyone know how i can make this?

    This is currently how it works.
    https://i.imgur.com/vtdeg7m.mp4 it rotates around the car. but i can't use the touch screen or mouse to move the camera. and it starts to imidiately rotate.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class CameraRotate : MonoBehaviour
    5. {
    6.    public float speed;
    7.    void Update (){
    8.        transform.Rotate(0, speed * Time.deltaTime, 0);
    9.    }
    10. }
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    In order to stop it from rotating all the time, track when the user goes idle and how much time passed since then. Then only start the idle rotation if enough time has passed since then. You also probably want to rotate around an object. All in all, the below code example should do what you want. You only need to replace the contents of isIdle() with whatever makes a player idle or not in your case. For testing purposes i added the playerIdling bool, which you can set in the inspector. You'll see that the rotation starts timeBeforeRotate-many seconds after the bool is changed to true.

    Code (CSharp):
    1. public class IdleCamRotation : MonoBehaviour
    2. {
    3.     [SerializeField] private float speed;
    4.     [SerializeField] private float timeBeforeRotate = 2f;
    5.     [SerializeField] private Transform rotateAround;
    6.     private float lastTimeNotIdle;
    7.  
    8.     [SerializeField] private bool playerIdling = true; // testing variable only!
    9.  
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         lastTimeNotIdle = Time.realtimeSinceStartup; // initialize at "now"
    15.     }
    16.  
    17.     // Update is called once per frame
    18.  
    19.     void Update()
    20.     {
    21.         // Check if the player is idle
    22.         if (!isIdle())
    23.         {
    24.             // When we are not idling, update the time of last non-idle action
    25.             lastTimeNotIdle = Time.realtimeSinceStartup;
    26.         }
    27.  
    28.         // Calculate how long we are idling
    29.         float diff = Time.realtimeSinceStartup - lastTimeNotIdle;
    30.  
    31.         // Only rotate when we waited timeBeforeRotate seconds after the last user action
    32.         if (diff > timeBeforeRotate)
    33.         {
    34.             transform.RotateAround(rotateAround.position, Vector3.up, speed);
    35.         }
    36.     }
    37.  
    38.     private bool isIdle()
    39.     {
    40.         // Code for whatever makes a player idle or not idle in your situation
    41.         return playerIdling;
    42.     }
    43. }
    As for figuring out when the player is idling or not, it probably makes sense to make lastTimeNotIdle (or better call it lastActionTime) a global variable and update it to "now" whenever the player does something that is not idling - for example tapping the screen. Needless to say, going with this approach you can remove the whole isIdle() method and so on from the above example, since the idle status is then tracked implicitely by updating the time variable each time the player does something.
     
    Last edited: Sep 14, 2019
    Rachzella likes this.
  3. Rachzella

    Rachzella

    Joined:
    Oct 9, 2015
    Posts:
    78
    Thanks that worked for the idle part. But the camera doesn't allow to be moved with mouse or touch screen. (I'm making it a mobile game so best to adjust it to mobile) so all i would need more is zooming. and the camera movement with one finger.
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Well, sure. Of course it doesnt, because we never made it do that ;)
    To be honest, there are a tons of tutorials on normal camera rotation, so i thought i'd focus on the idle camera part.

    To move the camera via mouse, simply get the mouse inputs and use another transform.RotateAround, where the horizontal mouse input influences the speed. For the other mouse axis (up-down instead left-right) change the axis of rotation from Vector3.up to Vector3.right. Again, there are plenty of tutorials on this if you have problems. As for touch.. i have not really worked with touch, but since touch without gestures is basically the same as a mouse pointer, i imagine it works pretty much the same. I'd get the mouse one to work first, so you get a feel for it. Then introducing touch shouldnt be too hard.
     
  5. Rachzella

    Rachzella

    Joined:
    Oct 9, 2015
    Posts:
    78
    Hmm. It doesn't seem to work for me. it doesn't give errors, but it doesn't move either. maybe i got the code wrong or the placement wrong. Could you help me out there?
     
  6. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    I feel like you are missing some understanding. Please try to google for "Mouse Orbit Unity" or something along those lines, follow a tutorial, try to understand how it works and implement it in another script. Now you have a working script that allows you to move the camera with your mouse, and another script that allows you to automatically rotate around an object when idle. Now you can try to combine the two.

    I'm really not a huge fan of just posting full solutions, but rather helping people fix a specific problem after they tried it themselves and ran into a problem they cant fix. Give a man a fish and he will return tomorrow, asking for another. Teach a man how to fish and he is well fed for the rest of his life.
     
    Rachzella likes this.
  7. Rachzella

    Rachzella

    Joined:
    Oct 9, 2015
    Posts:
    78
    It's not that i need a full code. but rather a solution. cause what i have is the script you gave, which rotates it after given time. and the orbit script. but the camera doesn't move. it only works as in looking around. follows the mouse location.
    I'm not an real advanced coder. i'm trying to learn, and understand which every part of a code does. But i want it to be able to rotate around the car using the mouse click as well. not the mouse cursor location. If it makes sense to you how i described it.
     
  8. Rachzella

    Rachzella

    Joined:
    Oct 9, 2015
    Posts:
    78
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ManualCameraRotate : MonoBehaviour
    6. {
    7.     public float speedH = 2.0f;
    8.     //public float speedV = 2.0f;
    9.  
    10.     private float yaw = 0.0f;
    11.     private float pitch = 0.0f;
    12.  
    13.  
    14.  
    15.     // Use this for initialization
    16.     void Start()
    17.     {
    18.  
    19.     }
    20.  
    21.     // Update is called once per frame
    22.     void Update()
    23.     {
    24.  
    25.         yaw += speedH * Input.GetAxis("Fire1");
    26.         //pitch -= speedV * Input.GetAxis("Fire1");
    27.  
    28.         transform.eulerAngles = new Vector3(pitch, yaw, 0.0f);
    29.  
    30.     }
    31. }
    this is what i currently have setup in the script that manages the manual rotation from the player. and it's asigned to fire1 (Mouse0) but this happens
    https://i.imgur.com/fbwkFwR.mp4

    it does rotate now. but at the wrong position not around the car. but at the camera point. and it's only one sided.
     
  9. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    If you manage to move the camera left and right with mouse input, then you are probably setting its position instead of using transform.RotateAround similar to the example above. Do it like this for example:
    Code (CSharp):
    1.         Vector2 mouseInput = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
    2.         if (mouseInput != Vector2.zero)
    3.         {
    4.             lastTimeNotIdle = Time.realtimeSinceStartup;
    5.             transform.RotateAround(rotateAround.position, Vector3.up, speed * mouseInput.x);
    6.             // Do whatever else based on the mouse input
    7.         }
     
    Rachzella likes this.
  10. Rachzella

    Rachzella

    Joined:
    Oct 9, 2015
    Posts:
    78
    Yes that did it. I changed the Void Update() with that code. And added Serialized fields for RotateAround and speed not it works. it does follow my mouse x and y position. i'm not sure if that'll cause confilicts for mobile but it works now. Much appereciated.