So I am making a 2D RPG game. When I load a new scene, I have DontDestroyOnLoad() attached to my player script, this is so that my players (soon to be) stats and equipment will not be removed. However, when I go back to the starting scene, where my player spawned, it duplicates the player every time the scene is laoded.
Any Suggestions? Here is my code. Any help would be nice, thanks.
using UnityEngine;
using System.Collections;
public class Player : Entities {
void Start () {
DontDestroyOnLoad (this);
}
void Update ()
{
if (Input.GetKey (KeyCode.W))
{
GetComponent<Rigidbody2D>().transform.position += Vector3.up * speed * Time.deltaTime;
}
if (Input.GetKey (KeyCode.A))
{
GetComponent<Rigidbody2D>().transform.position += Vector3.left * speed * Time.deltaTime;
}
if (Input.GetKey (KeyCode.S))
{
GetComponent<Rigidbody2D>().transform.position += Vector3.down * speed * Time.deltaTime;
}
if (Input.GetKey (KeyCode.D))
{
GetComponent<Rigidbody2D>().transform.position += Vector3.right * speed * Time.deltaTime;
}
}
}
public class MusicPlayer : MonoBehaviour
{
private void Awake()
{
int numMusicPlayers = FindObjectsOfType().Length;
if (numMusicPlayers != 1)
{
Destroy(this.gameObject);
}
// if more then one music player is in the scene
//destroy ourselves
else
{
DontDestroyOnLoad(gameObject);
We have a tutorial on how to make one dontdestroyonload script that you can use as many times as you like without duplication when traveling back and forth between scenes.
Make a GameObject named for example _GM ( Game manager ) and place it in your first scene, but no other.
Make an empty GameObject for your spawn position, or just simply check the Vector3 coordinates where you’d like to spawn.
In the start method of _GM do this:
Void Start()
{
DontDestroyOnLoad(this)
//Position to spawn your player
Vector3 position = GameObject.Find("SpawnPoint").transform.position;
//If your player prefab doesn't exist in the scene, then instantiate it
if (GameObject.Find("Player") == null)
{
GameObject player = Instantiate(player, position, Quaternion.rotation) as GameObject;
}
}
If you switch scenes then you can either:
1.)reinstantiate it at a new position
2.)set the position of your player again, but you have to attach the DontDestroyOnLoad script to it aswell if your going with the 2nd method!
I might be a bit late to help you any further, but I wanted to answer for everyone searching an easy solution to this:
I would recommend using the Singleton pattern.
You would use a baseclass that guarantees there is only one Instance of an Object at a time.
The code for the baseclass is:
using UnityEngine;
/// <summary>
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton<MyClassName> {}
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static T Instance
{
get
{
if (m_ShuttingDown)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed. Returning null.");
return null;
}
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
That’s all you have to do to have a perfectly smooth running system. I would personally recommend the Singleton-Pattern for all kinds of game managers, resource managers, pooling managers, player objects and so on. Everything that is persistent throughout the game should use this base class to avoid complicated bugs when introducing the object to the scene and removing it again, transporting it between scenes and avoiding multiple Objects. On top, it is good practice and clean code.
You can use this.gameobject wherever gamebject is written in the code above, as gameobject in the script directly refers to the GameObject that this component is attached to. So to optimize the code, I have used directly gameobject .