Cinemachine camera issue when returning from another scene

, ,

The Cinemachine Camera is not snapping to the player after scene load (Cinemachine 3.1.4, Unity 6)

This is part of the Unity 2.5D Turn-Based RPG: Build Your Own Turn-Based Battles & Environments
course.

Heading into battle > Changes scene to battle scene > defeat/win > load back to the overworld scene with the correct player position works all fine.

When running the game directly from the overworld scene, the problem doesn’t exist, and everything works.

The issue is apparent when I start the game from another scene (the main menu scene > prologue scene > overworld scene) as I enter a battle and load back, the camera races forward from its original start position (at the start of the overworld scene) all the way to the player (where the player had the battle), creating a noticeable delay, and furthermore, the player doesnt load in the correct postion either which is weird.

I’m not sure exactly what the problem is, since it works when loading straight from the overworld scene.
Perhaps it’s an initialisation order or something to do with cinemachine.
I tried many things, such as turning the xyz position damping to 0, which cut the camera straight to the player (which is good), but it created a small glitch where it momentarily shows the last frame of the battle.

I would really appreciate any help as I’ve been trying to troubleshoot this for a while :frowning:

Update

I added a visual fade out from the battle scene which hides the glitch!

Now, the spawning issue.

At the moment, it seems like wherever I enter a battle in the overworld scene, and then enter the battle scene and load back into the overworld, I’m always loading in the same place, and it’s always where I initiated my first battle.

And another issue, when I recruit another character, she doesn’t load back with me in the overworld scene and ends up back in her original position in the overworld before I recruit her. Also, a dublicate ends up following me after returning out of nowhere a few seconds later.

That was going to be my suggestion. Not much else you can do to stop that first frame buffer. I’ve always stuck to using a transition. You’ll find this in lots of games between scenes.

At the end of the battle, you should be spawning in the location where you were when you entered the battle, so this is normal… unless you’re meaning that in successive battles, you’re going back to that first location, that’s not normal.

The position is stored in PartyManager when you change scenes, and should be getting set every time you start an encounter in PlayerController.FixedUpdate()

This one I"m not sure at all about, since the JoinableCharacterScript should be checking with the PartyManager to see if the character is in the party. If it is, then it should be SetActive(false). That’s called on Start (and PartyManager is a Singleton, so it should already be there if a character had already been recruited).

I doubly can’t explain the actual follow character being spawned a few seconds later, this should be happening right away. That almost sounds like a coroutine is managing it (which it should’t be).

Paste in your CharacterManager.SpawnOverworldMembers() method.

Thank you very much for the response both on the video and here.
Yeah, it also makes the battle seem smoother between transitions. I need to add a fade-in for the transition to the battle scene next!

Sorry if I didn’t word it well. I meant that the character is indeed returning to the first location, which, as you said, is not normal. It’s either not updating the saved player position correctly before entering battle or not restoring that position properly after loading back into the overworld, since it’s always where the first battle commenced.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class CharacterManager : MonoBehaviour
{
    [SerializeField] private GameObject joinPopup;
    [SerializeField] private TextMeshProUGUI joinPopupText;

    private bool infrontOfPartyMember;
    private GameObject joinableMember;
    private PlayerControls playerControls;
    private List<GameObject> overworldCharacters = new List<GameObject>();

    private const string PARTY_JOINED_MESSAGE = " Joined The Party!";
    private const string NPC_JOINABLE_TAG = "NPCJoinable";

    private void Awake()
    {
        playerControls = new PlayerControls();
    }
    // Start is called before the first frame update
    void Start()
    {
        playerControls.Player.Interact.performed += _ => Interact();
        
    }

    // Public method to be called once PartyManager is initialized
    public void InitCharacterVisuals()
    {
        Debug.Log("CharacterManager: InitCharacterVisuals()");
        // clear any old visuals
        foreach (var go in overworldCharacters) Destroy(go);
        overworldCharacters.Clear();

        // now spawn fresh
        SpawnOverworldMembers();
    }


    private void OnEnable()
    {
        playerControls.Enable();
    }

    private void OnDisable()
    {
        playerControls.Disable();
    }
    // Update is called once per frame
    void Update()
    {

    }

    private void Interact()
    {
        if (infrontOfPartyMember == true && joinableMember != null)
        {
            MemberJoined(joinableMember.GetComponent<JoinableCharacterScript>().MemberToJoin);//add member
            infrontOfPartyMember = false;
            joinableMember = null;
        }
    }

    private void MemberJoined(PartyMemberInfo partyMember)
    {
        GameObject.FindFirstObjectByType<PartyManager>().AddMemberToPartyByName(partyMember.MemberName);// add party member
        joinableMember.GetComponent<JoinableCharacterScript>().CheckIfJoined();// disable joinable member
        // join pop up
        joinPopup.SetActive(true);
        joinPopupText.text = partyMember.MemberName + PARTY_JOINED_MESSAGE;
        SpawnOverworldMembers(); // adding an overworld member
    }

    private void SpawnOverworldMembers()
    {
        List<PartyMember> currentParty = GameObject.FindFirstObjectByType<PartyManager>().GetCurrentParty();
        Debug.Log(" Current party count: " + currentParty.Count);


        Debug.Log("SpawnOverworldMembers called.");

        for (int i = 0; i < overworldCharacters.Count; i++)
        {
            Destroy(overworldCharacters[i]);
        }
        overworldCharacters.Clear();

        

        for (int i = 0; i < currentParty.Count; i++)
        {
            if (i==0) // first member will be the player
            {
                GameObject player = gameObject; // get the player

                GameObject playerVisual = Instantiate(currentParty[i].MemberOverworldVisualPrefab,
                transform.position, Quaternion.identity); // spawn the member visual

                playerVisual.transform.SetParent(player.transform); // settting the parent to the player

                player.GetComponent<PlayerController>().SetOverworldVisuals(playerVisual.GetComponent<Animator>(),
                playerVisual.GetComponent<SpriteRenderer>()); // assign the player controller values
                playerVisual.GetComponent<MemberFollowAI>().enabled = false;
                overworldCharacters.Add(playerVisual); // add the overworld character visual to the list
            }
            else // any other will be a follower
            {
                Vector3 positionToSpawn = transform.position;// get the followers spawn position
                positionToSpawn.x -= i;

                GameObject tempFollower = Instantiate(currentParty[i].MemberOverworldVisualPrefab,
                positionToSpawn, Quaternion.identity);// spawn the follower

                tempFollower.GetComponent<MemberFollowAI>().SetFollowDistance(i); // set follow ai settings
                overworldCharacters.Add(tempFollower); // add the follower visual to our list
            }
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == NPC_JOINABLE_TAG)
        {
            //enable our prompt
            infrontOfPartyMember = true;
            joinableMember = other.gameObject;
            joinableMember.GetComponent<JoinableCharacterScript>().ShowInteractPrompt(true);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject.tag == NPC_JOINABLE_TAG)
        {
            //disable our prompt
            infrontOfPartyMember = false;
            joinableMember.GetComponent<JoinableCharacterScript>().ShowInteractPrompt(false);
            joinableMember = null;
        }
    }
}

I’m not seeing what could be causing this here. I’ll need to take a closer look at the project.
Zip up your project and upload it to https://gdev.tv/projectupload.

  • Be sure to remove the Library folder from the zip to conserve space
  • Be sure to tag me (Brian T) as the requesting instructor
  • Be sure to include a link back to this message so I can easily get back to you.
1 Like

Hi Brian,

I’m having trouble uploading the project file using the upload feature in the link.

I’ve instead sent you an email with the project file attached (as a sharedrive link)

I hope this is okay

Thanks

UPDATE:

I re-saved the player’s position inside a new FadeManager script just before loading the battle scene, which seems to have fixed the player position problem. Now, to fix the duplication of the character!

Hi Brian,

I hope all is well

Did you have any updates?

I could use the help at the moment.

Apologies, I misunderstood and thought your isssues had been resolved.
In terms of the download you sent, I never received said email (or it was filtered out so that I never saw it).

Can you try to upload the project again to https://gdev.tv/projectupload

Be sure to zip the project and remove the Library folder to conserve space.
Be sure to tag me (Brian T) as the requesting instructor and include a link back to this topic.

Hi Brian, apologies for the late response.

I’m still having trouble with my character reappearing after scene load. I think the game is having trouble saving preferences and is instead restarting the scene after loading back from the battle scene, which reinstates the recruited character.

That upload website just does not work for me at all. The upload portion always gives me an error, so I’ve copied the necessary information and pasted it in an email alongside a link to my zip file.

I haven’t received this email. I’m not sure where you sent it. Try sending it to [email protected]