Home > OS >  Unity 2D: Making the Player Gameobject Reactivate after being turned off
Unity 2D: Making the Player Gameobject Reactivate after being turned off

Time:07-25

I can't get the Player Gameobject to reappear. The player deactivates the moment the Timeline starts when they touch the box collider, but the player never reactivates. I have tried using Player.SetActive(true) in the coroutine and even using an Invoke method with no luck. Any ideas on how to fix this? Please help.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

public class TimelineTrigger : MonoBehaviour
{
    // calling items for Unity
    public PlayableDirector timeline;
    public GameObject Player;
    public GameObject CutsceneCollider;
    public GameObject CutsceneMC;

    // Start is called before the first frame update
    void Start()
    {
        // calls the playable director and turns off the MC for the scene
        timeline = timeline.GetComponent<PlayableDirector>();
        CutsceneMC.SetActive(false);
    }

    void Update()
    {
        Player = GameObject.FindGameObjectWithTag("Player");
    }

    private void EnableAfterTimeline()
    {
        Player = GameObject.FindGameObjectWithTag("Player");
        Player.SetActive(true);
    }

    public void OnTriggerEnter2D (Collider2D col)
    {
        if (col.CompareTag("Player"))
        {
            // plays the cutscene and starts the timer
            timeline.Play();
            Player.SetActive(false);
            Invoke("EnableAfterTimeline", 18);
            CutsceneMC.SetActive(true);
            StartCoroutine(FinishCut());
        }

        IEnumerator FinishCut()
        {
            // once the cutscene is over using the duration, turns off the collider and the MC.
            yield return new WaitForSeconds(17);
            CutsceneMC.SetActive(false);
            CutsceneCollider.SetActive(false);
        }
    }
}

CodePudding user response:

If you have only one Player instance and it's accessible from the start, you'd better set it once in the Start method.

void Start()
{
    // calls the playable director and turns off the MC for the scene
    timeline = timeline.GetComponent<PlayableDirector>();
    CutsceneMC.SetActive(false);
    Player = GameObject.FindGameObjectWithTag("Player");
}

void Update()
{
}

private void EnableAfterTimeline()
{
    Player.SetActive(true);
}

CodePudding user response:

The issue here is that coroutines in Unity can't be run on inactive GameObjects, so FinishCut never gets executed.

This can be worked around by having a separate MonoBehaviour in the scene to which the responsibility of running a coroutine can be off-loaded. This even makes it possible to start static coroutines from static methods.

using System.Collections;
using UnityEngine;

[AddComponentMenu("")] // Hide in the Add Component menu to avoid cluttering it
public class CoroutineHandler : MonoBehaviour
{
    private static readonly MonoBehaviour monoBehaviour;

    static CoroutineHandler()
    {
        var gameObject = new GameObject("CoroutineHandler");
        gameObject.hideFlags = HideFlags.HideAndDontSave; // hide in the hierarchy
        DontDestroyOnLoad(gameObject); // have the object persist from one scene to the next
        monoBehaviour = gameObject.AddComponent<CoroutineHandler>();
    }

    public static new Coroutine StartCoroutine(IEnumerator coroutine)
    {
        return monoBehaviour.StartCoroutine(coroutine);
    }
}

Then you just need to tweak your code a little bit to use this CoroutineHandler to run the coroutine instead of your inactive GameObject.

public void OnTriggerEnter2D (Collider2D col)
{
    if (col.CompareTag("Player"))
    {
        // plays the cutscene and starts the timer
        timeline.Play();
        Player.SetActive(false);
        Invoke("EnableAfterTimeline", 18);
        CutsceneMC.SetActive(true);
        CoroutineHandler.StartCoroutine(FinishCut()); // <- Changed
    }

    IEnumerator FinishCut()
    {
        // once the cutscene is over using the duration, turns off the collider and the MC.
        yield return new WaitForSeconds(17);
        CutsceneMC.SetActive(false);
        CutsceneCollider.SetActive(false);
    }
}
  • Related