[Solved] Cinemachine question - switching player objects

Hello again,

I have a Dracula player object that transforms to a Bat player object after a keycode is pressed and vice versa.
The way I do this is by instantiating the Bat object, and destroy the Dracula object afterwards.

The problem is that since I use a Cinemachine camera that follows the Dracula, when I switch to Bat, the Cinemachine camera doesn’t have an object to follow, since of course the Dracula object is destroyed.

I do not have any experience with Cinemachine. How do I fix it so when the Bat object is live the camera follows it?

In CinemachineVirtualCamera, leave the Follow variable in the Inspector empty and create a function that can instantiate both players when conditions are met:

    private void InstantiatePlayer()
    {
        if(your player is Dracula)
        {
            Instantiate(draculaPrefab, new Vector3(x, y, z), Quaternion.identity);
        }
        else if(your player is the bat)
        {
            Instantiate(batPrefab, new Vector3(x, y, z), Quaternion.identity);
        }

        player = GameObject.FindGameObjectWithTag("Player");
        CinemachineVirtualCamera cinemachineVirtualCamera = FindObjectOfType<CinemachineVirtualCamera>();
        cinemachineVirtualCamera.m_Follow = player.transform;
    }

You could make an empty Player object that contains both of the player transformations and just toggle between them without changing the cinemachine follow target.
Else you probably need to change it via script. CinemachineVirtualCamera Class - Cinemachine Documentation

I tried that, never managed to have it work…

thank you very much guys!

before I saw justin’s comment, I was working on APSchmidt’s solution, and

It works perfectly! :smile:

What I wanted is fixed.

Now I have another tweak I need to make.

I use a deadzone (in Cinemachine), if the Dracula is moving and I change to Bat (and vice versa), since the camera resets position on the new object, the deadzone centers very fast - and it seems kind of ugly.

It only happens when the object is moving because the deadzone is usually not centered on the previous player object

is there a way this can be fixed?

I’m not using a dead zone but you can certainly set the new dead zone the same way you just did for the Follow variable.

Look at the scripting documentation for the right way to access the dead zone by script: https://docs.unity3d.com/Packages/com.unity.cinemachine@2.3/api/Cinemachine.CinemachineVirtualCamera.html

Probably:

cinemachineVirtualCamera.m_DeadZoneWidth =
cinemachineVirtualCamera.m_DeadZoneHeight =
cinemachineVirtualCamera.m_DeadZoneDepth =

just under the m_Follow line in your Instantiate player function. Leave also the fields empty in the Inspector.

I’ll try the code.

I played with the LookAhead option a little bit, it kind of centers it. so when bat is live it’s kind of in the center of the deadzone … it seems to work fine so far.

thanks again!

I managed accessing CinemachineComposer with the code below but setting the value of m_DeadZoneHeight doesn’t work; it stays at 0 in play mode. I’m not getting any error message.

        CinemachineComposer cinemachineComposer = cinemachineVirtualCamera.AddCinemachineComponent<CinemachineComposer>();
        Debug.Log("cinemachineComposer = " + cinemachineComposer);
        cinemachineComposer.m_DeadZoneHeight = 0.5f;

Edit: I was wrong, Debug.Log shows that m_DeadZoneHeight is set to 0.5f but the new value is not set on the slider in the Inspector.

Console message:

5363661--542478--Capture.JPG

Slider in play mode:

5363661--542481--Capture2.JPG

You’ll just have to repeat the code for m_DeadZoneWidth and m_DeadZoneDepth. :slight_smile:

The whole thing now, in order:

        CinemachineVirtualCamera cinemachineVirtualCamera = FindObjectOfType<CinemachineVirtualCamera>();
        CinemachineComposer cinemachineComposer = cinemachineVirtualCamera.AddCinemachineComponent<CinemachineComposer>();
        cinemachineVirtualCamera.m_Follow = player.transform;
        cinemachineComposer.m_DeadZoneHeight = 0.5f;
        Debug.Log("Player Follow Camera = " + cinemachineVirtualCamera);
        Debug.Log("cinemachineComposer = " + cinemachineComposer);
        Debug.Log("m_DeadZoneHeight = " + cinemachineComposer.m_DeadZoneHeight);

this is how i solved it:

instead of destroying and instantiating a new object (bat or dracula),

I only used the Dracula object, and in the Animator I set a transition bool parameter to switch from the Dracula Animation to the Bat Animation, so now it seems that the Dracula becomes a Bat and vice versa - so in other words I changed the sprite and not the object.

In the Cinemachine camera I set it to follow the Dracula object at all times, since now Dracula and Bat are the same object, the camera position doesn’t reset.

Further than that,
with a bool statement asking if the Dracula is live or not, I can fix the player movement accordingly (bat needs vertical axis etc)…, or the collider offsets and size etc

It works fine so far, hopefully as I develop the game I don’t get any other issues with this solution.

I really appreciate your time Schmidt!! Thank you very much!

You’re welcome!

Accessing Cinemachine via script is not as straightforward as it is for other stuff so I’m glad to have found out how to do that, even if you don’t use it. :slight_smile:

There’s a slim chance that my efforts will be useful to someone else.