- Home /
What makes a prefab alter their variables at runtime?
My game has enemies all based on prefabs. When they get hurt they lose health, set as a float variable. Seems pretty straight forward.
Only problem, the enemy prefabs also lose their health. Likewise, every other variable, regardless of when it's public, private or static, gets changed. This buggers up the game the next time I test it, and I have to reset the variables manually.
Every variable is either public or private.
What can cause a prefab's variables to alter like this? I had no idea it's even possible to alter a prefab's variables via script.
I'm also finding it impossible to break the prefab connection.
Is there any way to avoid this, or simply break the prefab connection?
Answer by _dns_ · Apr 19, 2014 at 02:03 PM
Hi,
Prefabs are objects stored on the disk as assets files. When in the editor or starting the game, Unity will instantiate those objects in memory (only if they are referenced by some object in the scene). Example: in the scene, you have an object "MySpawner" that has a member "public GameObject MyMonsterPrefab" that you assigned to a prefab with a drag & drop operation in the inspector.
Then, when launching the game, Unity will instantiate a copy of MyMonsterPrefab and assign it to MySpawner.MyMonsterPrefab. The thing is that if other objects also reference the same prefab = you have multiple MySpawner in the scene, they will all share the same MyMonsterPrefab instance. That is MySpawner1.MyMonsterPrefab and MySpawner2.MyMonsterPrefab will be the same object in memory if they reference the same prefab.
Another point is that Unity will write to disk any change done to this prefab in memory. This is very convenient for editor code but is not what you want in the game. This prefab instance is your original object, you don't want to modify it, you need to make a copy first.
So the best usage of prefab is to be a template: you need to copy this prefab to another location in memory = Instantiate it. This is done with the Instantiate() function from the GameObject class. For example, in MySpawner class, you will have some code in Start() that will do "MyMonsterInstance = Instantiate( MyMonsterPrefab)", then you can move, rotate, change life value of this new MyMonsterInstance object as much as you want, this MyMonsterInstance is unique in memory.
Well, this post is longer than expected :) I guess there are other posts or documents that explains instance and prefabs. It's an important aspect of Unity and when you'll master it you'll do very nice stuff with it ! :)
Answer by Dataforge · Apr 21, 2014 at 03:48 AM
For all you future Googlers out there who run into the same problem, here's how I ended up solving it:
My enemy has a script that went something like this:
var weaponName : Transform;
var weaponObject : Transform;
weaponObject = Instantiate(weaponName, position, rotation);
Again, all seems pretty simple. The problem was, 'weaponName' was also the name of the prefab. So, somehow Unity got confused which caused the problem above. When I changed the name of the prefab the problem went away.