- Home /
System.Serializable, Constructors, Defaults
I was just wondering what the best practice was for constructors and custom classes. Currently I have a MonoBehaviour that contains a List that contains a CustomClassWithoutSerializableAttribute. I want to know the best way to default the third class. It looks like the following:
Character.cs
public class Character : MonoBehaviour
{
public List<Ability> m_abilities;
}
Ability.cs
[System.Serializable]
public Ability : IAbility
{
[SerializeField]
private int m_somethingSetInEditor;
private Damage m_damage;
public Ability()
{
m_damage = new Damage(10);
}
}
Damage.cs
public Damage
{
public Damage(int number)
{
}
}
Damage is null at the end of this chain of events. I've been trying to find the best practice for this. Eventually I want to move Ability out of the Inspector, but for now, I want to be able to iterate quickly on this and want to know the best practice for this type of thing.
Should Ability be deriving from ScriptableObject and initializing m_damage in the Start() function?
Hi. Did you find a solution for this? Now I have the same problem. Neither constructor nor private Damage m_damage = new Damage(10);
work.
Please don't try to hijack another question. See my answer below. If you have a similar problem, you should ask a seperate question. We can't handle your specific case here in the comments. $$anonymous$$ake sure you include your actual code that reproduces the problem. Obviously the code "IGoByChad" posted is not his actual code as the "class" keyword is missing in both class definitions. If you don't want to post your actual code, make sure if you create a repro-sample that it actually has the same problem.
btw:
private Damage m_damage = new Damage(10);
does work as well. Of course the Damage instance it not serialized, but each time the Unity serialization system is recreating / deserializing the Ability class, the Damage instance will be recreated as well.
Note: If you use the constructor of the Ability class, make sure you initialize it in the parameterless constructor as this is used by Unity. FieldInitializers however should work as well as they run even before the constructor.
Thanks a lot. The problem was with the absence of parameterless constructor.
Answer by Bunny83 · Feb 03, 2017 at 11:49 AM
The question is old, but since it got bumped:
I can't reproduce your problem. The Damage instance is not null. My test case:
[System.Serializable]
public class Ability
{
[SerializeField]
private int m_somethingSetInEditor;
private Damage m_damage;
public Damage damage { get { return m_damage; } }
public Ability()
{
m_damage = new Damage(10);
}
}
public class Damage
{
public int val;
public Damage(int number)
{
val = number;
}
}
public class Character : MonoBehaviour
{
public List<Ability> m_abilities;
void Start ()
{
foreach (var a in m_abilities)
{
Debug.Log(a.damage.val);
}
}
}
This prints out "10" for each ability that i "create" in the inspector. Though be aware that Unity does not support inheritance for custom serializable classes. So your Ability array can only contain Ability instances if you want Unity to serialize them. You can not store derived classes in that List. Well, you can but they won't be serialized. If you need inheritance you have to use ScriptableObject and create seperate assets for each ability. In that case inheritance would work.
In this example range is being set to whatever I set it to in the inspector, but I never get the message "Constructor called..." in my console. When i try to do anything else in the constructor it just doesn't happen
using UnityEngine;
using System.Collections.Generic;
[System.Serializable]
public class Ability
{
private int damage;
public Ability(int damage)
{
this.damage = damage;
}
}
[System.Serializable]
public class RangedAbility : Ability
{
[SerializeField]
public int range;
[SerializeField]
public int damage;
public RangedAbility(int range, int damage) : base(damage)
{
this.range = range;
Debug.Log("Constructor called...");
}
}
public class Character : $$anonymous$$onoBehaviour
{
public RangedAbility[] m_abilities;
void Start ()
{
foreach (var a in m_abilities)
{
Debug.Log(a.range);
}
}
}