I have a controller class for the health of a GameObject. It is not a MonoBehavior but it will be used by MonoBehavior objects.
using System;
using UnityEngine;
[Serializable]
public class HealthController{
[SerializeField]
private int max_health;
private int health;
public HealthController {
this.health = this.max_health; // this doesnt work because its called before serialisation
}
}
so I want to be able to set the maximum health in the unity editor: thats why max_health
is a SerializeField. But now i also want the variable health
initally to be set to the the maximum health without introducing a second SerializeField for it. Thats why I tried to put the line this.health = this.max_health
to the constructor: but this doesn#t work because the constructor seems to be called before the serialisation.
The only solution i could think of is adding a public void Initialize()
instead of the contructor to the HealthController and then explicitly calling this in the Start() method of the Monobehavior owning this controller.
using System;
using UnityEngine;
[Serializable]
public class HealthController{
[SerializeField]
private int max_health;
private int health;
public void Initialize() {
this.health = this.max_health;
}
}
public class Player : MonoBehaviour
{
public HealthController health;
public void Start() {
health.Initialize();
}
}
But this seems too complicated to me: Is there a better solution on how to do this?
CodePudding user response:
If you use lazy initialization, you don't need to worry about explicitly initializing HealthController
objects. You could mark health
as a nullable with ?
and then route access it through a property:
private int? health;
public int Health {
get {
if (!health.HasValue) {
health = max_health;
}
return health.Value;
}
private set {
health = value;
}
}
CodePudding user response:
You can add the ISerializationCallbackReceiver
interface to your HealthController
object. Admittedly, this might be a bulldozer, when all you need is a hammer. But, the functionality Unity provides when you implement the interface can often help a project.
You then use it like:
[Serializable]
public class HealthController : ISerializationCallbackReceiver
{
[SerializeField]
private int max_health;
private int health;
// required to satisfy the interface requirements.
public void OnBeforeSerialize() { }
public void OnAfterDeserialize ()
{
health = max_health;
// .. then any further post deserialisation work you might want to do.
}
}
Here’s the Unity docs for ISerializationCallbackReceiver
.