Parameters to Start() and Awake() methods?

I’ve spent some time now researching into the topic, and only found two methods people use to get around this limitation… but perhaps Unity might eventually just make it possible to pass parameters through to the Start() and/or Awake() methods? It’d be a very powerful extension… Thoughts?

In particular, it’d be great if we were able to type for example, the syntax of:
gameObject.AddComponent<MyScript(Parameter1, Parameter2)>();

Idk… just seems like it wouldn’t be that farfetched of an idea to throw in… instead of us having to work around it.

May I just ask as to the way you feel this would help your implementations?

Not a rude question, don’t get me wrong but I’m unsure why you would want to be able to do that? Each component with those methods can have its own members without the need for them to be passed as parameters and I honestly couldn’t see why you’d manually call the methods.

bearing in mind, I’m super tired right now, I may be off here, I just find it quite suitable to be able to pass in conditions at the beginning of a script starting up. It’s not so much that I’d want to manually call a starting method, so much as I’d like to be able to you know… .more or less tell the script “how to start” based on the parameters I throw in with the “startup” command. The simple get around I’ve found is renaming all my constructors to “Init” then after adding them as components, calling the “init” method on it. But it just seems a little… idk. tedious… here, I’ll show you a snippet of my code so you see my usage.

Transceiver

    public class Transceiver : MonoBehaviour
    {
        public Dictionary<Classifier, float> storage = new Dictionary<Classifier, float>();
        public enum Type { Recvr, Trans }
        public enum Classifier { one, two, three, four, five }

        //Rename to Constructor for C# Only runtime.
        public void Init(string classifier, Type transceiverType)
        {
            //IF CLASSIFIED AS "ONE" STRENGTH IS 1
            //IF CLASSIFIED AS "---" STRENGTH IS -

            switch (classifier)
            {
                case "one":
                    //storage.Add(Classifier.one, 1);
                    print("Added 1");
                    break;

                case "two":
                    //storage.Add(Classifier.two, 2);
                    print("Added 2");
                    break;

                case "three":
                    //storage.Add(Classifier.three, 3);
                    print("Added 3");
                    break;

                case "four":
                    //storage.Add(Classifier.four, 4);
                    print("Added 4");
                    break;

                case "five":
                    //storage.Add(Classifier.five, 5);
                    print("Added 5");
                    break;

                default:
                    throw new System.Exception("Sorry, must use default options...\n");
            }
        }
    }

^ That is the script I’m calling. ^

Input

    public class Input : MonoBehaviour
    {
        public List<Transceiver> receivers = new List<Transceiver>();

        //Rename to constructor for C# Only Runtime.
        public void Init()
        {
            //I'm manually calling the create method because I'm only at the beginning phases and doing testing.
            CreateReceivers(2, "three");
            CreateReceivers(1, "five");
            CreateReceivers(4, "two");
        }

        private void CreateReceivers(int numReceivers, string classifier)
        {
            receivers.Add(gameObject.AddComponent<Transceiver>());
            this.gameObject.GetComponent<Transceiver>().Init(classifier, Transceiver.Type.Recvr);
        }
    }

^ That is the Script which calls the first one ^

Now the brief over view of this is that my Input creates a Transceiver and in doing so, it defines “Classifier” as well as whether the Transceiver will function as a Transmitter or a Receiver. In regular C# I can simply do

new Transceiver(classifier, Transceiver.Type.Recvr

but for MonoBehaviour I’m stuck renaming my constructor, then throwing in 2 extra lines of code… as I said, it’s just tedious to modify it, especially since I’m only using Unity to be able to visualize the activity, and the final product will not actually really even have graphics. I’ll be going backwards to re-model everything later, after I know my over all project model functions correctly.

There, I was trying to figure out how to format the code block. XD I’m too used to Stack Exchange. lol

Well, inheriting from MonoBehaviour is only required if you want to attach your script to a GameObject and have the methods such as Start and Awake run for you.

However, you should be able to just do

receivers.Add(gameObject.AddComponent<Transceiver>().Init(classifier, Transceiver.Type.Recvr));

You could also use Unity - Manual: Conditional compilation to change up bits of code so you don’t have to manually change everything.

Or as here Preprocessor directives - C# reference | Microsoft Learn can define your own.

1 Like

AH! Beautiful. Thank you much man. Greatly appreciate the tip for one-lining that sucker, as well as the links!

I’m not sure about that one-liner.
But you can also do this, which is another line but compact? :slight_smile:

Tranceiver t = gameObject.AddComponent<Tranceiver>();
receivers.Add(t);
t.Init(/* blah blah */);
1 Like

I’ll admit I didn’t test the one liner, but it should work exactly the same. I do generally prefer multiple lines for clarity though.

He just needs to make his Init methods return “this”, for the oneliner to work.

public Transceiver Init(string classifier, Type transceiverType)
{
    // ...
    return this;
}

But I agree with Brathnann, for clarity I would use multiple lines.

1 Like

Absolutely, sorry… right… just the return type :slight_smile:

1 Like

@Brathnann that one liner would not work unless you made the init method return a reference to “this”. the add method for the list would end up getting nothing since init was void.

would have to GetComponent, add to list then call init.

intent is more clear if you do it this way too.

but yeah i don’t see how parameters for Awake, Start or OnEnable would help you, it is Unity calling those methods for you, not you calling them, and it is Unity Constructing the object or getting reference to a existing one for you which is why you cant simply use a constructor as well. It is pretty common for people to just build there own Init or SetData method in this case.

1 Like

lol that’s what I am doing rn. x)

Well to everyone, thanks for the feedback, I’ve only just come to understand the majority of C# and am only just applying it within Unity… it’s not all that different of course, but as I said before, it was late and I think I mostly posted out of half curiosity, but also half irritability. :smile: lol very good input from you all though! Thank you! :smile:

this is a very intriguing way of doing it, quite suitable for my needs of dynamically naming the reference… Gotta say, you all here on Unity are much more friendly than Stack Exchange. Hahaha! at least in the little experience I’ve had with both so far.

I think @Brathnann 's most important comment got lost on the way:

For whatever you’re doing, it seems like it would be best to just not have the class be a MonoBehaviour, and use the constructor as usual:

public class Transceiver { //not MonoBehaviour

    public Transceiver(string classifier, Type transceiverType) { //you get to have a constructor now
        ....
    }
}

Of course, if this Transceiver is supposed to be attached to a GameObject and handle stuff in that way, that’s not an option. But whenever you’re putting behaviour somewhere, it’s generally a good idea to think through if you really need this to be a MB or if it can be a plain old class.

1 Like

Definitely, I’ve certainly fought a couple different patterns tossing and throwing options, but the main thing is, I need to be able to visualize all instances of the class that are created, in the Inspector, under the list… and from my testing, that only seems to work under the condition of the class instance extending from MB. I’ve tried just tagging the class with “[Serializable]” but that doesn’t seem to work… so Idk, I’m just sticking to MB for now. The other two issues I’m having are
1.) The List is only populating with the parent script instances… not the newly Instantiated ones, and
2.) I can’t seem to figure out how to dynamically name each instance reference based on a static variable…

I made a post for the 2nd one already, but if you happen to know a quick fix for either or both of those troubles, no one seems to have an answer to those yet… namely the 2nd… the 1st is probably just bad syntax or something. Lol I haven’t looked at that yet as functionality is still fine.