2

I have a trigger that plays an animation but when i switch scene and i come back to the original scene, the animation plays again. I want to remember actioned triggers in order to play triggers once per scene. How can I do that?

The GlobalScript

public class GlobalScript : MonoBehaviour 
{
    public static GlobalScript Instance;
    public Animator ani;
    void Awake ()   
       {
        if (Instance == null)
        {
            DontDestroyOnLoad(gameObject);
            Instance = this;
        }
        else if (Instance != this)
        {
            Destroy (gameObject);
        }
      }
}

The current script (Running every time i load the scene)

    public Animator ani;
    public AudioClip sound;
    public GameObject text;
    private int seconds = 2;
    //var delay = 2.0; //This implies a delay of 2 seconds.

//  public void SavePlayer(){
//      GlobalScript.Instance.ani= ani;
//  }

    // Use this for initialization
    void Start () {
        ani= GlobalScript.Instance.ani;
        ani.enabled = false;
        text.SetActive (false);
    }

    void OnTriggerEnter(Collider other){
        AudioSource.PlayClipAtPoint (sound, transform.position);
        ani.enabled = true;
        text.SetActive (true);
        Destroy (gameObject);
        Destroy (text,3);
        //text.SetActive (true);
        //StartCoroutine(Die());
    }

    //And function itself
    IEnumerator Die(){
        //play your sound
        text.SetActive(true);
        yield return new WaitForSeconds(2); //waits 3 seconds
        Destroy(gameObject); //this will work after 3 seconds.
    }
} 
Jose
  • 49
  • 5
  • you need to persist the information that its already run somewhere. Either in a DoNotDestroy, or a static variable. But you tend to need this for lots of things, is it that you dont have this at all, or you are looking for a way to do it in the behaviour for some reason? – Ewan Oct 04 '17 at 14:55
  • GlobalScript.Instance.HasTriggeredTheAnimationAlready for example? – Ewan Oct 04 '17 at 14:57
  • I have been trying something like your last answer, one class GlobalScript and the other class, TriggerState, then i tried to save the state of elements, but it didn't work. Something like this: link – Jose Oct 04 '17 at 15:28
  • i will modify the code in order to be more specific – Jose Oct 04 '17 at 15:29

2 Answers2

0

What I would suggest is this. The idea is that you have all your game logic in normal classes that could run on a web site or console app be unit tested etc.

You then have a static instance of it in your unity app which all the Behaviours can reference to get the state of the game.

You can fill up your Game class with all the data and logic you need and not worry about persisting data in your Behaviours (which may be destroyed)

//this is your game logic which should not reference any unit objects
//its just the core logic
public class Game
{
    public List<Area> Areas {get;set;}
    public Game()
    {
        this.Areas = new List<Area>();
    }
}

public class Area
{
    public string Id {get;set;}
    public bool HasBeenVisited {get;set;}
}

///Add to DoNotDestroy object
public class GlobalScript : MonoBehaviour 
{
    public static Game CurrentGame;

    public void Start()
    {
        this.CurrentGame = new Game();
        this.CurrentGame.Areas.Add(new Area() {Id="area1"});
        //setup the game as required...
    }
}

public class ColliderBehaviour :MonoBehaviour
{
    //bind this in the editor to the name of the area its in
    public string AreaName;
    public void OnTriggerEnter(Collider other)
    {
        var area = GlobalScript.CurrentGame.Areas.First(i=>i.Id == this.AreaName);
        if(!area.HasBeenVisited)
        {
             //do the thing
             area.HasBeenVisited = true;
        }
    }
}
Ewan
  • 1,231
  • 1
  • 7
  • 5
  • Thanks for your answer, did you mean var area = GlobalScript.CurrentGame.Areas.Find(i=>i.Id == this.AreaName); instead of var area = GlobalScript.CurrentGame.Areas.First(i=>i.Id == this.AreaName);? Find and not First? First doesn't exist – Jose Oct 04 '17 at 22:35
  • 1
    i meant first, you might need to add: using System.Linq – Ewan Oct 05 '17 at 06:33
0

Another option is to use DontDestroyOnLoad. I created this script for that purpose called Persistence.cs:

public class Persistence : MonoBehavior
{
    void Awake ()
    {
        DontDestroyOnLoad (gameObject);
    }
}

Just put it on any GameObject and all of its sub-GameObjects will receive that too. What it does is to prevent the GameObjects to be deleted when switching scenes - or rather unloading the scene they are in (and therefore not trigger their OnDestroy, and not trigger Start and Awake again). Alternatively just add the line of code DontDestroyOnLoad (gameObject); into the Start or Awake of your global script.

So if you store data viewable in the inspector of such a GameObject, it will persist. Static values are the other option, but that has already been mentioned. They can't expose values to the inspector (custom editor scripts may change or circumvent that), can't have multiple instances, but appear to be more persistent (for whatever it's worth).

Battle
  • 1,251
  • 12
  • 19