Search Unity

RTS style bounds that shrink as camera zooms out

Discussion in 'Cinemachine' started by MythicalCity, Apr 18, 2018.

  1. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    I'm trying to user cinemachine for an RTS style camera and I've set it up to follow a dummy object around that is controlled by the mouse/keyboard. During zoom I would like to limit the camera's position so that it doesn't show the edges of the map. So when you zoom out, the camera movement should be limited to only the center of the map, but if you zoom in, you could move the camera close to the edges of the map.

    Should I do this by limiting the dummy object or is there a better way to do this with cinemachine already?
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Can you show me the inspector of the vcam?
     
  3. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    Sure, there's not much setup yet as I've only recently started on this. This vcam is following a blank gameobject that is moved by the keyboard/mouse input. That object is currently limited to not go beyond the edges of the map. I haven't setup the zoom yet but I was thinking maybe adjust the Follow Offset of the body of the vcam to the zoom value? (I'm using a dolly instead of changing the field of view of the camera, so not technically a zoom, but dolly in/out).

    Screen Shot 2018-04-18 at 2.02.29 PM.png
     
  4. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    In a related question, how do we lock down certain rotation axis for the Aim in a virtual camera. For example, if I also want to modify the x axis rotation of the camera as it zooms out (ie: when zoomed out all the way it is 90 degrees on x, and when zoomed in all the way it is at 60 degrees on x axis) but don't want to modify any of the other axis (y or z)?

    Whenever I have the aim component set to composer and I move the camera quickly it will rotate on the y axis once the target goes past a certain point on the screen. I can turn off the aim component of course, but then it won't rotate on the x axis either. I've played around with the various dead zone, soft zone, etc. values but no matter what it always rotates on y axis.
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Interesting questions!

    1. There is no easy way out-of-the-box with a Perspective camera to confine its screen edges to stay within some bounds. You can do it with an ortho camera and a Cinemachine Confiner, but for a perspective one you'll have to put limits on the camera position, which you calculate yourself.

    2. For your zoom and angle thing, what if you tried something like this: create a MixingCamera with 2 vcam children, the first looking at 60 degrees (DoNothing in the Aim), and the second looking down at (almost) 90 degrees (again DoNothing in the Aim). The Mixing Camera will give you a continuous blend between them, the weight of which you can manipulate to control the "zoom". You can even give them different FOVs if you want.

    Note that vcams don't like to look straight up or down, unless you override the brain's global Up direction. That's why I say "almost" 90 degrees. If true 90 is really important to you, you can ask me how to accomplish that.
     
    Last edited: Apr 19, 2018
  6. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    Ok thanks. Would be great in the future if there was some examples for RTS or strategy or simulation games as well, I know unity is an FPS first engine, but would be cool to have as well :)

    Ok I'll try the mixing camera, but what do you mean by the problem with 90 degrees? I haven't seen any issues with setting the camera to look down at x90 degrees. And what would changing the up direction in the brain do? As you might have guessed my game is mostly top down, but you can zoom in to look at units from a close up side view as well.
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Right, my straight-down warning was a bit knee-jerk - it's mostly the Aim Composer that cares about it. If you have Do Nothing in the Aim you should be fine.
     
  8. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    Ok thanks. One question about the orbital transposer recentering to target heading. I'm using a camera with the orbital transposer for the "detail" view of a unit which allows the player to rotate the camera around the unit to view it from all sides. It works great but I wanted to recenter it back to a perpendicular angle every time the detail view is entered. So, say the player goes into detail view, rotates around the unit to an arbitrary angle, exits the detail view and then enters detail view on another unit. I would like the angle to reset to a default value based on the target heading (instead of keeping the same angle that was left the last time detail view was used). Can I force an immediate recenter before I turn on the camera gameobject? or do I have to enter in this default angle/position manually into the vcam's transform every time I turn on this vcam?
     
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    If your heading definition is TargetForward (or some variation of that) then you can just set orbitalTransposer.m_XAzis.Value = 0 to force the recenter.
     
  10. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    Awesome thanks!

    BTW, I've tried the mixing camera and it looks pretty good but doesn't seem to mix the 2 cameras evenly. ie:

    vcam A (zoomed out)
    position: 0, 300, 0 (and follow offset)
    rotation: 90, 0, 0

    vcam B (zoomed in)
    position 0, 40, -60 (and follow offset)
    rotaiton: 60, 0, 0

    When I set the mixing weights for both in the mixing camera component to 0.5, the MainCamera rotation is at x 90.7 instead of mixed between 90 and 60 degrees. So throughout most of the mix the camera is at around 90 degrees, it only goes towards 60 degrees when it is mixed mostly to the b cam.
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Can you show me the inspectors for the 2 vcams?
     
  12. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    MixingCam.png Vcam-B.png Vcam-A.png
    Here they are plus the mixing camera
     
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    It's because you should have null in the LookAt targets.

    However, I just tried it and realized that the Mixing camera isn't a good solution, because you want the camera pos to move in an arc, and the mixing camera just does a lerp, so the player doesn't stay in the center. Sorry to have misled you.

    Try this instead:

    Use an ordinary vcam with a FramingTransposer, like this:

    upload_2018-4-19_16-15-38.png

    Then, add a custom script to handle the zoom, as follows:

    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. [ExecuteInEditMode]
    5. public class FramingZoomRotate : MonoBehaviour
    6. {
    7.     public float minAngle = 45;
    8.     public float maxAngle = 90;
    9.     public float minDistance = 40;
    10.     public float maxDistance = 300;
    11.  
    12.     [Range(0, 1)]
    13.     public float zoom = 0;
    14.  
    15.     CinemachineVirtualCamera vcam;
    16.     CinemachineFramingTransposer framing;
    17.  
    18.     void Start ()
    19.     {
    20.         vcam = GetComponent<CinemachineVirtualCamera>();
    21.         if (vcam != null)
    22.             framing = vcam.GetCinemachineComponent<CinemachineFramingTransposer>();
    23.     }
    24.  
    25.     void Update ()
    26.     {
    27.         if (framing != null)
    28.         {
    29.             float angle = Mathf.Lerp(maxAngle, minAngle, zoom);
    30.             float distance = Mathf.Lerp(maxDistance, minDistance, zoom);
    31.             Vector3 rot = transform.rotation.eulerAngles;
    32.             if (!Mathf.Approximately(rot.x, angle) || !Mathf.Approximately(framing.m_CameraDistance, distance))
    33.             {
    34.                 rot.x = angle;
    35.                 transform.rotation = Quaternion.Euler(rot);
    36.                 framing.m_CameraDistance = distance;
    37.                 vcam.PreviousStateIsValid = false; // kill the damping
    38.             }
    39.         }
    40.     }
    41. }
    I think that will give you what you're looking for.
     
    Last edited: Apr 19, 2018
  14. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    Awesome, thank you! I think that will work as a nice zoom/tilt.
     
  15. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    The zoom script works pretty well this way when just zooming in/out but I'm finding that when zooming during movement (ie: when the follow target is moving) it gets a bit stutter-y or jumpy and is not smooth. It's almost as if the the vcam script is fighting with the zoom script to position the camera properly. Is that possible?
     
  16. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Try turning the damping to zero