Forum begins after the advertisement:

 


[Part 5 Bug Fixes] SceneFader Error, Scene Transition Issues, Cast after Heal

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 5 Bug Fixes] SceneFader Error, Scene Transition Issues, Cast after Heal

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #14602
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    This is a supplementary post written for Part 5 of our Metroidvania series, and it aims to address 2 things:

    1. Missing information in the video, and;
    2. Address common issues / questions that readers run into, and possible solutions for these questions.

    For convenience, below are the links to the article and the video:


    Table of Contents

    Missing Information in the Video

    1. SceneFader NullReferenceException Error
    2. Player hit while in scene transition stops cutscene

    Common Issues

    1. Errors after transitioning scenes
    2. Player casts after healing

    Missing Information in the Video

    1. SceneFader NullReferenceException Error

    [Caused by the SceneTransition script firing before the SceneFader is initialised.]

    • In SceneFader.cs script, change Start() to Awake() while leaving the code fadeOutUIImage = GetComponent<Image>(); the same.
        private void Start Awake()
        {
            fadeOutUIImage = GetComponent<Image>();
        }

    2. Player hit while in scene transition stops cutscene

    [Caused by inefficient code that does not prevent player from taking damage while in cutscene]

    • In PlayerController.cs WalkIntoNewScene(), set pState.invincibility to true in the first line, and set to false in the last.
    • Then, add a line in FlashWhileInvincible() to prevent the player from flashing while pState.cutscene is true.
    • Finally, in SceneTransition.cs OnTriggerEnter2D(), set the player’s pState.invincible to true before loading scene.

    PlayerController.cs

        public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay)
        {
            pstate.invincible = true;
    
            //If exit direction is upwards
            if(_exitDir.y > 0)
            {
                rb.velocity = jumpForce * _exitDir;
            }
    
            //If exit direction requires horizontal movement
            if(_exitDir.x != 0)
            {
                xAxis = _exitDir.x > 0 ? 1 : -1;
                Move();
            }
    
            Flip();
            yield return new WaitForSeconds(_delay);
            pstate.invincible = false;
            pState.cutscene = false;
        }
    
        void FlashWhileInvincible()
        {
            if (pState.invincible && !pState.cutscene)
            {
                if(Time.timeScale > 0.2 && canFlash)
                {
                    StartCoroutine(Flash());
                }
            }
            else
            {
                sr.enabled = true;
            }
        }

    SceneTransition.cs

        private void OnTriggerEnter2D(Collider2D _other)
        {
            if (_other.CompareTag("Player"))
            {
                GameManager.Instance.transitionedFromScene = SceneManager.GetActiveScene().name;
    
                PlayerController.Instance.pState.cutscene = true;
                PlayerController.Instance.pState.invincible = true;
    
                StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo));
            }
        }

    Common Issues

    3. Errors after transitioning scenes.

    [There are multiple problems that can arise from this, some listed here, that can be solved by a note found in the Forum Post:]

    • 1. Mana isn’t being reset
    • 2. Invincibility and time stop is non-functional
    • 3. Hearts healed to full
    Make sure that there is only one scene containing your Prefabs with singleton scripts such as the Player and Canvas. Entering a scene with a second singleton instance will cause NullReferenceException errors as scripts cannot differentiate or single out one script instance from multiple.

    4. Player casts after healing.

    [This is addressed in [Part 6] Article of the Metroidvania, but not in the video.]

    In our PlayerController Script, let’s make a change to reset the castOrHealTimer in the CastSpell() method instead of GetInputs(). This relocation ensures that the timer doesn’t reset when you release the Cast/Heal button before CastSpell() is called.

    PlayerController.cs

        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Attack");
    
            if (Input.GetButton("Cast/Heal"))
            {
                castOrHealTimer += Time.deltaTime;
            }
            else
            {
                castOrHealTimer = 0;
            }
        }
    
        void CastSpell()
        {
            if (Input.GetButtonUp("Cast/Heal") && castOrHealTimer <= 0.05f && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost)
            {
                pState.casting = true;
                timeSinceCast = 0;
                StartCoroutine(CastCoroutine());
            }
            else
            {
                timeSinceCast += Time.deltaTime;
            }
    
            if (!Input.GetButton("Cast/Heal"))
            {
                castOrHealTimer = 0;
            }
    
            if(Grounded())
            {
                //disable downspell if on the ground
                downSpellFireball.SetActive(false);
            }
            ...
        }
    Note: Change the if parameter of both Heal() and CastSpell() to a higher float value if needed as 0.05f is a very limited time for a player to tap and fire a spell.

    That will be all for Part 5. Hopefully this can help you on any issues you may have. However, if you find that your issues weren’t addressed or is a unique circumstance, you can submit a forum post to go into detail on your problem for further assistance.

    #17502
    Mewvern
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    When i load into a new scene, my canvas gets destroyed on load

    #17503
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    When a canvas in Unity gets destroyed upon loading a new scene, it usually indicates that the canvas is part of the scene that is being unloaded. Here are a few strategies you can use to prevent your canvas from being destroyed on scene load:

    1. Use DontDestroyOnLoad

    If you want your canvas to persist across scene loads, you can use the DontDestroyOnLoad function in your script. Here’s how you can do this:

    1. Create a new script (e.g., CanvasManager.cs).
    2. Attach this script to your canvas GameObject.
    3. In the Start method, call DontDestroyOnLoad.
    using UnityEngine;
    
    public class CanvasManager : MonoBehaviour
    {
        private void Awake()
        {
            DontDestroyOnLoad(gameObject);
        }
    }

    2. Singleton Pattern

    If you want to ensure that only one instance of your canvas exists, you can implement a singleton pattern. This can help avoid issues if you accidentally load the scene multiple times.

    using UnityEngine;
    
    public class CanvasManager : MonoBehaviour
    {
        private static CanvasManager instance;
    
        private void Awake()
        {
            if (instance == null)
            {
                instance = this;
                DontDestroyOnLoad(gameObject);
            }
            else
            {
                Destroy(gameObject);
            }
        }
    }

    3. Loading the Canvas in the New Scene

    If the canvas is meant to be scene-specific, consider creating its prefab and instantiate it in each scene. You can do this in the Start method of a GameManager or similar script.

    4. Scene Management

    Make sure you are not accidentally destroying the canvas through your scene management logic. If you are loading scenes additively or using SceneManager.LoadScene, ensure you know how your scenes are set up and how they interact with each other.

    5. Check Scene Settings

    If you’re using Unity’s UI system, ensure that the canvas is set up correctly in the scene hierarchy. Sometimes issues can arise from the way GameObjects are structured or how prefab instances are managed.

    Debugging Steps

    • Check the Console for any errors or warnings that might indicate why the canvas is being destroyed.
    • Ensure that the canvas is not being referenced or destroyed through other scripts unintentionally.

    After applying these strategies, test your game again to see if the canvas persists as expected. If you continue to face issues, please share more details about your scene setup and any relevant scripts.

    #17504
    Mewvern
    Level 3
    Participant
    Helpful?
    Up
    0
    ::

    When I load into other scenes, the “cutscene” bool stays true and never goes back to false

    #17505
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It sounds like you’re dealing with a boolean variable that controls whether a cutscene is currently active in your game. If the variable stays true when you load new scenes, it might be due to how you’re managing the state of that variable across scene transitions. Here are a few steps you can take to troubleshoot and resolve the issue:

    1. Check where you set the boolean: Ensure that you are setting the “cutscene” boolean back to false at the appropriate time. This could be in a script that runs when you enter a new scene or after the cutscene has finished.

    2. Use a Singleton or Persistent Object: If you want to maintain the state of the “cutscene” boolean across scenes, consider using a singleton (a single instance of a class that persists) or a script that is marked to not be destroyed on load. This way, you can control when the boolean is set to false.

      Here is an example of how you could set up a simple singleton:

      public class CutsceneManager : MonoBehaviour
      {
          public static CutsceneManager Instance { get; private set; }
          public bool cutsceneActive = false;
      
          private void Awake()
          {
              if (Instance == null)
              {
                  Instance = this;
                  DontDestroyOnLoad(gameObject);
              }
              else
              {
                  Destroy(gameObject);
              }
          }
      
          public void StartCutscene()
          {
              cutsceneActive = true;
          }
      
          public void EndCutscene()
          {
              cutsceneActive = false;
          }
      }
    3. Resetting the Boolean: If you are using DontDestroyOnLoad, make sure that you explicitly reset the boolean when you want to end the cutscene. You can do this in the scene loading logic or in the Start or Awake methods of your scene scripts.

    4. Debugging: Add debug logs to check the state of the boolean when you load a new scene. This will help you to see whether the boolean is being set as expected.

      private void Update()
      {
          Debug.Log("Cutscene Active: " + CutsceneManager.Instance.cutsceneActive);
      }
    5. Scene Management: If you are using Unity’s scene management, ensure that the logic for setting the cutscene boolean is not being skipped or ignored when transitioning to the new scene.

    6. Check for Errors: Look through the console for any errors or warnings that might indicate what’s going wrong with the scene transition or the boolean management.

    If you can provide a bit more detail about how and where you’re managing the “cutscene” variable, I’d be happy to help further!

    #17510
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    @mewvern can you share your codes here?

    #17538
    Mewvern
    Level 3
    Participant
    Helpful?
    Up
    1
    ::

    Sorry for a late response. I fixed the canvas problem I just had to continue the video where they made it a singleton. I also fixed the cutscene problem, I auto filled “stopCoroutine” accidently. Thanks

    has upvoted this post.
Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: