Trick: Start and Update without Start() and Update() function

Hi all. i have found some undocumented functionality in с#.
If you call the function Main() then it is performed automatically at startup. It works with the MonoBehaviour and ScriptableObject and can also automatically run Coroutine.
This feature allows you to create a very elegant code : :sunglasses:

using UnityEngine;
using System.Collections;

public class TMain : ScriptableObject  {

    IEnumerator Main () {
        Debug.Log ("Start");
        while(true){
            Debug.Log ("Update");
            yield return null;
        }
    }
}

Well now, that’s interesting…

(Though I don’t really see much point using it to re-implement existing functionality via coroutines…)

Edit:
A little playing around of my own. A quick test shows that it’s called independently of Awake and Start, with the call order such that this code…

 using UnityEngine;
using System.Collections;

publicclass MainTest : MonoBehaviour {

void Awake(){
 Debug.Log ("Awake");
}

void Start(){
 Debug.Log ("Start");
}

void Main(){
 Debug.Log ("Main");
}
}

… produces this output:

Awake
Main
Start

It should be noted that since this was a single test and that I can find no documentation on this whatsoever, the above can’t be relied upon.

I had exactly the same result. Main() performed between Awake() and Start()

Results with multiple copies of the component in a scene:

Awake
Awake
Awake
Awake
Awake
Main
Start
Main
Start
Main
Start
Main
Start
Main
Start

I’m not assuming anything about which of those Mains goes with which of those Starts. You could test that easily enough by naming your objects if you wanted to find out.

Thats quiet interesting.

Infact, first Main() of an object gets called, than Start() and OnEnable().

It’s really odd considering the context in which the term “Main” is used in traditional programming. It’s typically the entry point to a program that kicks off one or more loops. While I’m aware that some people use Start or Awake in combination with coroutines to get similar behaviour it’s always struck me as a hack, not to mention being contrary to Unity’s intended design where Update et. al. are where we’re meant to make the guts of the magic happen.

Effectivly thats only up to one’s code design. I personally think that using Start as a coroutine is perfeectly legit, especially in FSM’s.

Well, ScriptableObject can’t attach to GameObject.

We need instantiate it in the code(in MonoBehaviour class attached to GameObject).

For example;

public class script : MonoBehaviour{

void Start(){

Tmain independentScript = new Tmain();

}

}

Really, this isn’t a Trick, is another corroutine.

ScriptableObjects need to be instantiated by ScriptableObject.CreateInstance(). Just sayin. :wink:

1 Like

interesting… i was thinking about using scriptable objects in rpg-like game to store buff information… and expire time, this loop can be handy for time checks.

(sorry this is unrelated but am curious since am using scriptableobjects and i was surprised that they can have corotines)

from performance perspective…

is it good idea, to have scriptableobjects have their own loops to detect when it expires so it removes it self from referenced player?? lets say if there are 100 active.

or, i should add these objects into a “status” List inside the player, and use for loop to check every object if it is expired, then remove/destroy it from list.

am currently using the second approach, which is also good if i want to clear player from all it’s current debuffs.

but i feel using lists is annoying, and not as fun as having the buff manages it self out.

In terms of a MonoBehaviour this isn’t any more or less elegant than using Start as a coroutine.

Agreed.

Worse is that it’s undocumented and subject to change at any moment at Unity’s whim.

And also may have code that runs in an existing ‘Main’ method in the inherited class that isn’t getting ran now that you’ve shadowed it with a new ‘Main’ method.

1 Like

It is not Coroutine because it not required yield instruction

There is another trick - Create MonoBehaviour class and attach it to GameObject. Then change inheritance to ScriptableObject. You’ll get ScriptableObject as attached Component.

I agree with you should avoid use this feature but first of all you need to know about it.
I spent a lot of time before find this bug in my code. You can imagine this frustration when i see a function worked, but i not call it anywhere. So i hope i saved somebody nerve. :slight_smile:

1 Like

Wait, why do we need to know about it?

What bug in your code?

What frustration?

How does the existence of ‘Main’ resolve this bug and frustration?

I feel like using these undocumented features is a great way to booby trap your code. This is great! …if you want an unexpected surprise in Unity 5.1.7f, or some other future version.

If you assign this name to any of your methods then will get unpredictable flow of your program.
unpredictable flow == “bug” == frustration, is not it?

Ah, yeah so don’t name functions “Main” or else Unity will try to run them. Good to know!

Better not, since if you dont know about this being called just the same as Start() or OnEnable() you might have a hard time tracking down why the game suddenly blows up. :wink:

Or maybe it’s an Easter Egg from the developers?:slight_smile: