LazyValues

in the fighter script we dont check if the current weapon is null anymore. basically we dont check if it has been restored in restore state before we initialize it in start. Is this because Equipweapon that gets called in restorestate sets currentweapon.value, initializes the lazyvalue so it wont initialize again when we do currentweapon.ForceInit() in start?

That’s correct.

The way LazyValue works is that if the value has not been assign the first time it is read, then the Initializer is called. If, however, the value is assigned before the initializer is called, then there is no need to call the Initializer (in fact, it would be a problem because the initializer would now overwrite the real value).

Here’s a more abstract example:

private LazyValue<string> whatsMyName;

private void Awake()
{
    whatsMyName = new LazyValue<string>(SetDefaultName);
    //whatsMyName.value = "David Jones";
}

private void Start()
{
    whatsMyName.ForceInit();
    Debug.Log($"My name is {whatsMyName.value}");
}

private string SetDefaultName()
{
     return "David Bowie";
}

If you run this script (obviously within a MonoBehaviour, I didn’t include the class wrapper), The Debug will return “David Bowie” when you run it. In this example, when ForceInit() is called, the value hasn’t been set, so it calls SetDefaultName();

Of course, you don’t even need ForceInit() at this point, and if you comment out that line, you’ll still get “David Bowie” (We use ForceInit() in the Fighter because we really really need the weapon to be spawned at that point, so we force the issue).

Now uncomment the line in Awake() that sets the value to David Jones and run it again…
When Start calls ForceInit() nothing happens because the value has already been set to David Jones. SetDefaultName will never be called because it isn’t needed. Our Debug will now read the real name of one of my favorite musicians.

thnx so much for clearing that up!