I have 2 singleton (each in its own empty GO); a one named GlobalEvents and other SpecialEventsManager. the scripts all over my scene can subscribs to the Actions that are in GlobalEvents, no problem, but my SpecialEventsManager script get an error when trying to
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpecialEventsManager : MonoBehaviour
{
public static SpecialEventsManager Instance { get; private set; }
public Action<bool> SellingAction;
private bool isSelling;
public bool IsSelling { get => isSelling; set { if (isSelling != value) { isSelling = value; SellingAction?.Invoke(isSelling); } } }
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
private void OnEnable()
{
GlobalEvents.Instance.AreSelling += startSelling; //Object reference not set to an instance of an object
}
private void OnDisable()
{
GlobalEvents.Instance.AreSelling -= startSelling;
}
private void startSelling(bool value)
{
IsSelling = value;
}
}
If there is no SpecialEventsManager already instantiated, then Instance will be null. I’m just guessing that may be your problem. I think I see a bug in StartSelling(bool). If isSelling != value, then you set it to !value, which is its current value. So, that method can never change the value of isSelling. The startSelling(bool) method is redundant, both because you already have a similar method with different casing, and because you could just call the IsSelling property directly to achieve the same effect. Sometimes it makes sense to have a method that does the same thing as a property setter, for delegate purposes, but you shouldn’t make redundancies if you don’t expect to need them. Also, the isSelling field is capitalized like it’s a local variable, even though its a class instance field. The usual convention is to put an underscore at the beginning like _isSelling, but that’s just a convention not a rule. I prefer capital first letters for everything that is scoped to the class level, so I would do _IsSelling, but only when IsSelling is already taken, as in this case. Not sure why you need two different event managers that seem to care about the same selling event.
This code is just another example of a defective singleton.
If you ever find yourself asking “is this instance null?” then you are working with a defective singleton. Delete it and make one that plays nice with Unity3D.
Some super-simple Singleton examples to take and modify:
Simple Unity3D Singleton (no predefined data):
Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:
These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance
Alternately you could start one up with a [RuntimeInitializeOnLoad] attribute.
There is never a reason to drag a GameObject into a scene if it will be DontDestroyOnLoad.
If you do:
you may drag it into something else that isn’t DDOL. FAIL
you may drag something else into it that isn’t DDOL. FAIL
Just DO NOT drag anything into a scene that will be marked DontDestroyOnLoad. Just Don’t Do It!