0

I have a Unity project with various scenes. My First Person Controller has a script where I keep several variables which I want to keep for the whole game.

I will be changing scenes constantly, so my script has

void Awake() { DontDestroyOnLoad(transform.gameObject); }

so that my variables' value won't be lost. Now, I placed my object on scene 1, and my object is available when I load the first scene. When I change scenes everything behaves as expected: my variables' values are conserved. However, when I return to scene 1, my First Person Controller object isn't destroyed and now I have two First Person Controllers ( the one I brought from the other scene and the one that is inside scene 1).The camera doesn't know which one to follow.

How can I instantiate my GameObject only the first time a scene is loaded?

5 Answers 5

3

There is no way to avoid the duplicate Awake call if you reload a scene with that object. Two ways you could handle this are:

  • Have a scene dedicated to static initilization. Put all your permanently loaded scripts here with DontDestroyOnLoad and always start the app with this scene.
  • Store a static reference to the first initialised object. Destroy self in Awake if an instance already exists.

Example for the second option:

static private MyClass instance = null;
void Awake() {
    if (instance != null) {
        Destroy(this);
        return;
    }
    instance = this;
}
Sign up to request clarification or add additional context in comments.

1 Comment

The pre-scene instantiation is genius! It did what I needed it to do. Good idea.
0

If you are instantiating your First Person Controllers at the start of the load, when instantiating, you can do a conditional check to see if it already exists in the scene (then delete or not instantiate). As far as saving information across scenes, I suggest you use PlayerPrefs instead.

Comments

0

You could put your first person controller (indeed, your whole player if you like) in a prefab.

Then instead of having an instance of the prefab in the scene, write a Spawner component with a reference to the prefab. The Spawner can check (in Awake) if the first person controller already exists, and only instantiate the prefab if it doesn't already exist.

Comments

0

I know this is an older post but it in top few results of Google when I was searching for a way to auto instantiate a static GameObject in unity. not sure about older versions but this works flawlessly with 5.6.1. I needed a way to store game settings and access them from many many scenes. I also needed access to certain unity functions(like screen res, etc) that are only accessible from a MonoBehaviour so a plain static class was not an option. what I came up is basically a singleton type unity GameObject, that if you obtain a reference to the Instance, and there isn't one of these in the scene, it auto creates it. if one exists, (changed back to a scene where it was created) the duplicate self destructs so that there is only ever one of these in the game.

The reason I wanted this was because I use Unity ScriptableObjects to store data as they can be edited from the inspector both during edit and runtime and the changes during runtime do not revert (very handy if your working with the older OnGUI because you can store the rect locations in a scriptable object and watch your controls move around during runtime and the locations don't revert when you stop play mode)

this is my very basic class (removed my specific data from it)

using UnityEngine;

public class GameSettings : MonoBehaviour
{
    private static GameSettings _instance;

    public static GameSettings Instance
    {
        get
        {
            if (_instance != null) return _instance;
            else
            {
                Setup();
                return _instance;
            }
        }
    }

    public void Start ()
    {
        DontDestroyOnLoad(this);
    }

    public void Awake()
    {
        if (_instance != null) Destroy(this);
    }

    public static void Setup()
    {
        GameObject settings = GameObject.Find("GameSettings");
        if (settings == null)
        {
            settings = new GameObject("GameSettings");
            settings.AddComponent<GameSettings>();
        }
        _instance = settings.GetComponent<GameSettings>();
    }
}

You can use this 2 ways:

1: add it to a GameObject in your very first scene (so you can modify the values from the inspector). If you ever change back to that scene it won't create a duplicate due to the check for _instance. If you do add it to a scene manually make sure that you edit the GameObject.Find string to the name of your GameObject or else it will create a new one.

2: Simply create the reference to the ClassName.Instance which will auto create the object if it doesn't exist.

Example Implementation Script for a scene:

public class TestScene : MonoBehaviour
    {
        private GameSettings _settings;

        public void Awake()
        {
            _settings = GameSettings.Instance;
        }
        public void Start()
        {
        }

        public void Update()
        {

        }
    }

now all you do is add your public data (strings, int, etc) as public non static members of the GameSettings class and simply use _settings.MemberName to get access to the data.

hope this helps someone looking for a way to auto create GameObjects on the fly. This also works if you build a Prefab and have this script attached to any of its objects. Can be handy for auto creating UI Elements on the fly in specific scenes.

If you only need it in one scene and don't need it to persist across level loads (for example auto instantiating certain UI elements in certain scenes like say npc dialog etc) simply remove the DontDestroyOnLoad from the start function of the class thats attached to the prefab.

Comments

0

Create a static void function with the attribute RuntimeInitializeOnLoadMethod and the RuntimeInitializeLoadType.BeforeSceneLoad attribute argument, and it will be invoked just before the first scene loads. From that function you should be able to create your desired game object etc.

using UnityEngine;

public class GameStartupHelper
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void OnBeforeSceneLoad()
    {
        Debug.Log("OnBeforeSceneLoad(");
        // Create your stuff from here...
    }
}

ps. No need to add the class to any scene, it's enough just to keep the script file in the project for the callback to get called.

See this post for further explanation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.