It’s not possible without an extra class. All callbacks from Unity are directed to an instance. Unity doesn’t call static methods of classes. So if your “Grass” class should manage itself you would have to pick one of them to do the management stuff as well. While this is possible, it’s a horrible approach. A manager should always be seperate from the things it manages.
If Unity would have implemented something like EditorApplication.update for the runtime it would be possible without an extra class. In the editor you could do:
public class Grass : ScriptableObject
{
static List<Grass> m_List = new List<Grass>();
static bool m_Initialized = false;
static void Initialize()
{
if (!m_Initialized)
{
EditorApplication.update += OnUpdate;
m_Initialized = true;
}
}
static OnUpdate()
{
// do something
}
// other instance stuff here
void OnEnable()
{
Initialize();
m_List.Add(this); // add itself to the list.
}
}
Unity doesn’t have a static update delegate to which you can subscribe at runtime. However you could use a seperate helper class like my CoroutineHelper to achieve the same thing. Instead of the m_Initialited boolean you could simply store the “Run” instance to know it’s already running:
public class Grass : ScriptableObject
{
static List<Grass> m_List = new List<Grass>();
static Run m_UpdateJob = null;
static void Initialize()
{
if (m_UpdateJob == null)
m_UpdateJob = Run.EachFrame(OnUpdate);
}
// [ ... ]
}
This will ensure that OnUpdate is called once every frame as soon as the first “Grass” instance has been created. This does also work at runtime. The CoroutineHelper class is a selfmanaged singleton. It automatically creates an instance if one is needed. All coroutines which are started by the static methods the Run class provides will run on that singleton instance.
Unity is completely event driven. You don’t have control of the programs main loop. That’s part of the engines core. So you can’t have your code execute somehow every frame without having an instance which receives an event from the engine.
Another approach for a selfmanaging class would be this:
public class Grass : MonoBehaviour
{
int m_LastFrame = -1;
void Update()
{
if (Time.frameCount > m_LastFrame)
{
m_LastFrame = Time.frameCount;
// do something that should only happens once per frame here
}
// other update things should be done here.
// this part is executed for every instance of "Grass".
}
}
While this is possible, it adds a bit overhead to each Grass instance. If your class actually doesn’t need an Update itself it’s just wasted performance to have an Update method in every instance.
With this approach the first Grass instance which get his Update called will do the “extra work”. Once it’s done it updates the int variable so all other instances will ignore that part until the next frame.