References to Prefab get lost on start
I'm following a tutorial for a top-down RPG and in the beginning of this episode
he puts the player prefab(and the Canvas(stats) and Camera)in another scene so that,even when not starting from the main scene,there's always one of these objects(so that testing is easier).
When he does that there isn't any issue,but when I try it all the references to the Player and the other prefabs become null whenever the player moves from a scene to another.
This code is in the start function of the objects mantained between scenes
private static bool playerExists;//becomes true whenever a player object is created if there isn't another one in the current scene
if (!playerExists)
{
DontDestroyOnLoad (transform.gameObject);
playerExists = true;
}
else
{
Destroy (gameObject);
}
This code should destroy the prefabs in the current scene if ones from others are already present(this way there will always be one player,camera and stats per scene)
I think that this happens because in the start functions of objects local to the scene, the object references are set with FindObjectOfType() to the prefabs local to the scene(local player,camera and stats),but then they are destroyed and the new prefabs coming from another scene take their place,but with missing references.
VVV UPDATE:tested this hypotesis,put the result in reply VVV
What I don't understand is this doesn't happen in the tutorial,and before trying any wacky workaround I'd like to know why if you need more specific info/code ask and I'll post it ASAP
has he set up any fields in the inspector that you are missing? the new scene has all the prefabs that you are trying to search when loading the other scene? can you tell us what vars are the ones giving you issues? when starting from the second scene the game doesnt work?
has he set up any fields in the inspector that you are missing?
I've checked the scripts involved,and nothing seems missing
the new scene has all the prefabs that you are trying to search when loading the other scene?
Yes
can you tell us what vars are the ones giving you issues?
The most noticeable is thePlayer,reference variable in the startPoint (which is an empty object that should set the player's and Camera's transform to its location when the scen is loaded,it finds them thanks to findObjectOfType);
It is located in front of a door.It doesn't know what thePlayer is,so the one co$$anonymous$$g from the other scene spawns out of the map/wrong place,same goes for the camera(less noticeable,as it quickly moves to the player with lerp).
There's a similar issue with the questTriggers(they activate quests when the player walks on them;The quest manager is a child of the stats (singleton) gameobject);theQ$$anonymous$$(ref variable to quest manager)is null,so they give nullref exception when walked on.
when starting from the second scene the game doesnt work?
No,the game works correctly in the first loaded scene.Things get messy only when changing scene
private static Flexible$$anonymous$$usic$$anonymous$$anager _instance;
public static Flexible$$anonymous$$usic$$anonymous$$anager instance {
get {
if (_instance == null) {//in case not awake yet
_instance = FindObjectOfType<Flexible$$anonymous$$usic$$anonymous$$anager> ();
}
return _instance;
}
}
void Awake ()
{
// if the singleton hasn't been initialized yet
if (dontDestroyOnLoad) {
if (_instance != null && _instance != this) {
Debug.LogError ("Duplicate singleton " + this.gameObject + " created; destroying it now");
Destroy (this.gameObject);
}
if (_instance != this) {
_instance = this;
DontDestroyOnLoad (this.gameObject);
}
} else {
_instance = this;
}
}
only read first few lines and it sounded right away like they are using a singleton method to have presistent data? is that correct? if so make sure you DontDestroyOnLoad is set to true. otherwise when you switch scenes it will destroy. if you have a singleton method and the object is in both scenes, whichever one was created first will survive and the others will automatically destroy on scene changes.
ok i read the rest thats exactly whats going on your singlton method must be broken would you like to post the singleton method that goes in the awake?
UPDATE:
confirmed my hypotesis by using debug.Log with startpoint's thePlayer attribute value + name of the current scene,both at start and update: the reference wasn't null in the Start function's log,while in the update it was. Tried to change the execution order,putting the PlayerController script(which includes the method used above) before all the others but the references to the player were still null. Does the script execution order even affect the start functions?Are they executed in another order?
Tried to fix by putting the method above inside the awake(),but it seems like that dontDestroyOnLoad() does not work now,the player is recreated in each scene
Answer by Afelium · Mar 01, 2019 at 04:04 PM
I finally found a solution! I discovered that the Destroy() method isn't very reliable, and for some reason the references were set to the superflous prefab before its destruction. I fixed this by using the DestroyImmediate() method and now everything works fine(but I read its use is not advised).
(I still put the singleton method inside of Awake() )
Still don't understand why the guy from the tutorial didn't have to use it.