Search Unity

Question Camera 2D with Cinemachine

Discussion in 'Cinemachine' started by Elektr0n84, Oct 18, 2023.

  1. Elektr0n84

    Elektr0n84

    Joined:
    Oct 12, 2023
    Posts:
    3
    Hello everyone,

    I'm currently working on a project in Unity where I want to implement dynamic view changes using Cinemachine. The idea is to have multiple cameras with specific zone detections (using colliders, for example) that trigger the transition from one camera to another when the player enters or exits these zones.

    Currently, I'm using colliders to detect the player's entry into a specific zone, and I activate the camera associated with that zone. However, I'm wondering if there is a more efficient approach or best practices for managing these camera transitions.

    Here's an excerpt from my current code to give you an idea:


    1. Code (CSharp):
      1. public class CameraSwitcher : MonoBehaviour
      2. {
      3.     public CinemachineVirtualCamera cinemaActive;
      4.  
      5.     void OnTriggerEnter2D(Collider2D collision)
      6.     {
      7.         if (collision.CompareTag("Player"))
      8.         {
      9.  
      10.             cinemaActive.enabled = true;
      11.  
      12.  
      13.             CinemachineVirtualCamera[] allCameras = FindObjectsOfType<CinemachineVirtualCamera>();
      14.             foreach (CinemachineVirtualCamera camera in allCameras)
      15.             {
      16.                 if (camera != cinemaActive)
      17.                 {
      18.                     camera.enabled = false;
      19.                 }
      20.             }
      21.  
      22.         }
      23.     }
      24.  
      25. }
    I also set up a dynamic change of the camera offset depending on the positive or negative velocity of the character (To find out if the character goes left or right) :
    Code (CSharp):
    1. Code (CSharp):
      1. using UnityEngine;
      2. using Cinemachine;
      3.  
      4. public class CameraReturn : MonoBehaviour
      5. {
      6.     public CinemachineVirtualCamera cinemaReturnOffset;
      7.     public Rigidbody2D player;
      8.     public float smoothingFactor = 1f; // Facteur de lissage
      9.  
      10.     private Vector3 initialOffset;
      11.     private Vector3 targetOffset;
      12.  
      13.     void Start()
      14.     {
      15.         initialOffset = cinemaReturnOffset.GetCinemachineComponent<CinemachineFramingTransposer>().m_TrackedObjectOffset;
      16.         targetOffset = initialOffset;
      17.  
      18.     }
      19.  
      20.     void Update()
      21.     {
      22.         CheckVelocity();
      23.         UpdateOffset();
      24.         Debug.Log(player.velocity.x);
      25.     }
      26.  
      27.     void OnTriggerEnter2D(Collider2D collision)
      28.     {
      29.         if (collision.CompareTag("Player"))
      30.         {
      31.             // Lorsque le joueur entre dans la zone, vérifiez la vélocité
      32.             CheckVelocity();
      33.         }
      34.     }
      35.  
      36.     void CheckVelocity()
      37.     {
      38.  
      39.  
      40.         if (player.velocity.x < -0.1f)
      41.         {
      42.             targetOffset.x = -Mathf.Abs(initialOffset.x);
      43.         }
      44.         else if (player.velocity.x > 0.1f)
      45.         {
      46.             targetOffset.x = Mathf.Abs(initialOffset.x);
      47.         }
      48.  
      49.  
      50.     }
      51.  
      52.     void UpdateOffset()
      53.     {
      54.         CinemachineFramingTransposer framingTransposer = cinemaReturnOffset.GetCinemachineComponent<CinemachineFramingTransposer>();
      55.  
      56.         framingTransposer.m_TrackedObjectOffset.x = Mathf.Lerp(framingTransposer.m_TrackedObjectOffset.x, targetOffset.x, smoothingFactor * Time.deltaTime);
      57.  
      58.     }
      59. }
    Do you have any suggestions on how to improve this approach or recommendations on specific Cinemachine features that I could leverage to make these camera transitions smoother and more dynamic?

    Thank you in advance for your help!
     
  2. Elektr0n84

    Elektr0n84

    Joined:
    Oct 12, 2023
    Posts:
    3
    Here is the video to illustrate the change of offset to X-ray of the camera when the character changes direction
     
  3. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,712
    What do you mean by "smoother and more dynamic"? It looks pretty smooth already. What problem would you like to solve?

    One issue I can see is that you are modifying the FramingTransposer's settings. If you enable SaveDuringPlay, you may lose the initial setting because the play-time setting will be pushed back to the scene. An alternative approach might be to have an invisible object parented to the player, whose position is in front of the player. Use that invisible object as camera target.

    FindObjectsOfType is slow. You can use CinemachineCore.Instance.VirtualCameraCount and CinemachineCore.Instance.GetVirtualCamera() to efficiently iterate the active CM cameras in the scene.

    Take a look at the CinemachineTriggerAction script. It's designed to be placed on a trigger collider and can be used to activate and deactivate vcams among other things. You don't need custom code for that part.

    upload_2023-10-19_11-25-58.png
     
    Elektr0n84 likes this.
  4. Elektr0n84

    Elektr0n84

    Joined:
    Oct 12, 2023
    Posts:
    3
    Thank you very much for the tip, I mainly wanted to know if a better alternative was possible. I'll test this, but at first glance, it looks cool!

    And regarding the framing transposer, when I want to modify the camera's offset, is it therefore advisable to initialize these values directly within the script?
     
    Last edited: Oct 20, 2023
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,712
    The problem is that the script is reading the initial values from the FramingTransposer, which can get modified if you exit Play mode with SaveDuringPlay enabled. So anything you can do to guard against that (e.g. having the initial values as user-facing values in your script) is good.

    Another option is to explicitly support SaveDuringPlay in your script by handling the SaveDuringPlay.OnHotSave event. See an example here: https://forum.unity.com/threads/cin...ntrol-to-freelook-camera.505541/#post-3509905
     
    Elektr0n84 likes this.