- Home /
When or where do I set a prefab script subclass property?
I have a GargoylePrefab
in Unity that is assigned to a list of objects in my component Units
. The prefab has a Gargoyle
script attached to it (which inherits from the abstract Enemy
).
.
I am having trouble setting the inherited property EnemyType Type
in my GargoylePrefab
object according to the script. When I try accessing the script component of the prefab and logging its Type
property, I get an unexpected/unwanted result ( Invalid
instead of Gargoyle
).
.
Am I setting the value in the wrong place? I have also tried setting it in Gargoyle.Awake()
but the result is the same. How do I fix this problem?
.
See below for implementation overview:
// EnemyType.cs
public enum EnemyType { Invalid, Gargoyle }
// Enemy.cs
public abstract class Enemy : MonoBehaviour {
// Because EnemyType's first definition is "Invalid"
// Subclasses of Enemy have to set their type to something else
// to avoid having an unwanted or undefined type
public EnemyType Type { get; protected set }
...
}
// Gargoyle.cs
public class Gargoyle : Enemy {
private void Start() {
Type = EnemyType.Gargoyle;
}
}
// Units.cs
public class Units : MonoBehaviour {
public GameObject[] EnemyPrefabs;
public void OutputPrefabTypes() {
// This is just a method for testing.
// I -know- only one GameObject (GargoylePrefab) is in the array.
foreach (GameObject prefab in EnemyPrefabs) {
Enemy genericRef = prefab.GetComponent<Enemy>();
Gargoyle gargoyleRef = prefab.GetComponent<Gargoyle>();
Debug.Log(genericRef.Type); // Expected: Gargoyle, Actual: Invalid
Debug.Log(gargoyleRef.Type); // Expected: Gargoyle, Actual: Invalid
}
}
}
Answer by prateems · Feb 28, 2018 at 07:22 PM
The lack of instantiation of the prefabs stored in EnemyPrefabs
is the issue, as Start()
and Awake()
lifecycle methods are only called on instantiated instances of the prefab.
.
The solution is a design change:
public abstract class Enemy : MonoBehaviour {
public abstract EnemyType GetEnemyType();
...
}
public class Gargoyle : Enemy {
public override EnemyType GetEnemyType() {
return EnemyType.Gargoyle;
}
}
And then calling GetComponent<Enemy>().GetEnemyType()
. Doing this provides the desired results.
Answer by JedBeryll · Feb 28, 2018 at 05:33 PM
Possible cause: OutputPrefabTypes is called before Gargoyle.Start Thus it has the default value of EnemyType. Fixes: either set Gargoyle's execution order to a smaller value so it's called sooner (could get messy if you have many scripts) or make sure Gargoyle is initialized before calling any methods on it.
Your comment led me to realize that instantiation was indeed the problem. Because the Start()
and Awake()
code only runs on instantiation, and only for the instantiated instance of the game object, I would never get the desired output with the way I set it up.
I added my revised solution as an answer.
Your answer
Follow this Question
Related Questions
Is it possible to set variables for classes? 2 Answers
SteamVR - Spawning Prefab on Controller,SteamVR - Spawning Objects on Controller 0 Answers
Exit Prefab Mode from custom editor 0 Answers
C# Parent-SubClass set inherited properties help 1 Answer
I need to make two bullet controllers (friendly and enemy) Should I inherit? 1 Answer