Structuring my Unity3d project

Started by
2 comments, last by Alundra 8 years, 6 months ago

In my first unity3d project (an RPG) I wasnt very clear about how to structure my project. So I decided to use an old method: created a class named GameInstance containing all the game related info, like the player instance, item factory class, game settings and time, etc. It also handles events. This class is created in the first scene, the main menu. The only disadvantage I have found is that I cant test scenes indpendently, as the GameInstance is attached to a GameObject in the first scene (and marked as DontDestroyOnLoad()), the other scenes dont have it.

I would like to know if there are more optimal or adequate approach for this issue, so I can improve my code in future projects.

Advertisement
The answer to that question might be extremely large.
As for your practical example, I would create a scenemanager class, which handles switching between scenes, loading them etc. You can create 1 scenemanager object within your GameManager class

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

You want to learn about singletons. It is something some people claim is bad programming practice, but used properly I disagree, and this can be one of those uses.

You create that game controller as a singleton. Make sure that it will work in any scene created at any time, as in it isn't dependent on something in the main menu, rather can load defaults for your settings, or from a file, or whatever, but it has to work anywhere, starting at any time. If you make it a singleton, it checks if another instance of itself is in existence, and if so, deletes itself. In this manner, you put one in each scene, including the main menu, and yes, it needs to keep the dontdestroyonload call. So, the first one that gets instanced stays around, but you have them all over the place, so that you can test any scene you want.



Here the singleton class code thread safe using C# :


using UnityEngine;
using System.Collections;

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
  // Private-Data.
  private static T PrivateInstance;
  private static object PrivateLock = new object();
  private static bool ApplicationIsQuitting = false;

  // Get the singleton instance.
  public static T Instance
  {
    get
    {
      // Check if the application is quitting.
      if(ApplicationIsQuitting)
      {
        Debug.LogWarning("[Singleton] Application quitting.");
        return null;
      }

      // Lock to be safe about threading.
      lock(PrivateLock)
      {
        // Check if the private instance is null.
        if(PrivateInstance == null)
        {
          // Check if we have more than one instance found.
          if(FindObjectsOfType(typeof(T)).Length > 1)
          {
            Debug.LogError("[Singleton] More than one instance found !");
            return PrivateInstance;
          }

          // Find the object.
          PrivateInstance = (T)FindObjectOfType(typeof(T));

          // Check if the private instance is null.
          if(PrivateInstance == null)
          {
            GameObject Singleton = new GameObject();
            PrivateInstance = Singleton.AddComponent<T>();
            Singleton.name = "[Singleton]"+ typeof(T).ToString();
            DontDestroyOnLoad(Singleton);
            Debug.Log("[Singleton]" + typeof(T) + " created.");
          }
        }

        // Return the private instance.
        return PrivateInstance;
      }
    }
  }

  // Called when the application is quitting.
  public void OnDestroy()
  {
    ApplicationIsQuitting = true;
    Debug.Log("[Singleton]" + typeof(T) + " destroyed.");
  }
}

You can create a singleton class using this class as base class :


using UnityEngine;
using System.Collections;

public class SoundManager : Singleton<SoundManager>
{
  // Private-Data.
  private bool MusicOnOffState;

  // Set the music on/off.
  public void MusicOnOff()
  {
    SetGetMusicOnOffState = !MusicOnOffState;
  }
}

You can then acces the class in every script of your unity project using Instance function :


SoundManager.Instance.MusicOnOff();

Here another way to have one game object which never destroys when you load another scene :


using UnityEngine;

public class SingletonActor : MonoBehaviour
{
  // Private-Data.
  private static SingletonActor Instance;

  // Awake is called when the script instance is being loaded.
  void Awake()
  {
    if(Instance)
    {
      DestroyImmediate(this.gameObject);
    }
    else
    {
      DontDestroyOnLoad(this.gameObject);
      Instance = this;
    }
  }
}

This topic is closed to new replies.

Advertisement