Search Unity

Question How to move FPS camera to location of different virtual camera

Discussion in 'Cinemachine' started by Jinxology, May 9, 2023.

  1. Jinxology

    Jinxology

    Joined:
    Jul 13, 2013
    Posts:
    95
    In my first-person game, I have an FPS controller object with a virtual camera (vmCam1) child set to Body: 3rd person follow and Aim: POV. At times, I swap to a virtual camera (vmCam2) to focus on a scene from a different position in the room. After a few seconds, I want to move the FPS controller object to be aligned with the view of vmCam2. In other words, just teleporting them to vmCam2's position and rotation. I am using:
    Code (CSharp):
    1. FPSController.transform.position = Camera.main.GetComponent<CinemachineBrain>().ActiveVirtualCamera.VirtualCameraGameObject.transform.position;
    Problem: The FPScontroller doesn't move. I use print statements to show it's position after setting the transform.position, and the transform is indeed at vmCam2's location for an instant, but it seems to teleport back to vmCam1's last position as soon as I disable vmCam2.
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,720
    The Cinemachine paradigm is that if you assign tracking targets to the vcams (e.g. a follow target), then the vcam will position itself according to the algorithm's constraints and the target's position. You can't just set the vcam's position manually, because that is telling it to do something that contradicts what you are already telling it to do. That's why your position doesn't stick.

    3rdPersonFollow + POV is an unusual combination, and not an intended usecase. Can you describe the camera behaviour that you want, prior to the teleport? Then we can figure out a vcam setup that's appropriate for your needs. Once we have that, we can turn to making the teleport work.
     
  3. Jinxology

    Jinxology

    Joined:
    Jul 13, 2013
    Posts:
    95
    Thanks for the quick reply! I'm actually moving the parent object of the vmCam1. I figured that the vmCam1 would come along for the ride when I changed its parent's position. Also, FWIW, vmCam1 is set to follow and look at its parent, the FPSController object that has components of rigidBody, capsule collider, etc.

    Oh ok, that's good to know. I'm just going for the typical first person style control (WADS to move, mouse to aim). What would be the recommended setup for that?
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,720
    Having the vcam be a child of something whose transform you control is fine. In that case, you should set the Body section of the vcam to Do Nothing, since its position is being adequately controlled. A POV in Aim will then rotate the vcam relative to its parent transform.

    The way Cinemachine works, the current active vcam drives the transform of the main camera (which should be a separate GameObject, not parent or child of the vcam). To change camera to another viewpoint, just make another vcam somewhere else with a higher priority and activate it. The CMBrain on the main camera will see this and move the main camera to the new position (with a cut or a blend, depending on the brain settings). You don't move vcam1 - you leave it alone - and when vcam2 is deacivated, main camera control will return to vcam1.
     
  5. Jinxology

    Jinxology

    Joined:
    Jul 13, 2013
    Posts:
    95
    Moving between the virtual cameras is working great. My primary issue remains though. I activate vcamera 2 (which has a higher priority), the view changes just fine. Then, when a worldUI button is clicked, I set the position and rotation of the container of vcamera1 to be the same as vcamera2 (thereby "teleporting" the player to the position & view of vcam2). I debug/print the location to console to be sure and it indeed matches vcam2's transform.

    However, visibly in the scene view, the vcam1 container has not moved. Presumably, the position changed and was immediately set back to it's original location by something? Strangely, sometimes it works, but usually it does not. I've tried await Task.Delay and wait until end of frame a few times, but that yields the same success/fail rate.
     
  6. Jinxology

    Jinxology

    Joined:
    Jul 13, 2013
    Posts:
    95
    Thanks for all your help Gregoryl. I figured out my issue. I was setting transform.position instead of RigidBody.position. For rotation, the camera was rotating, but I was not setting my manually rotationX and rotationY in my Update on my FPScontroller, so when movement was renabled, it was using the last values that it remembered. Sorry for wasting your time with this, it appears that it wasn't camera related.
     
    Gregoryl likes this.