Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
5
Question by cregox · Apr 26, 2013 at 04:51 PM · componentconstructors

Add component in one line with parameters

I'm not sure I follow why components can't have constructors.

Is it just an enforced code design practice? If not, can we add a component with a one-liner constructor?

Is it to prevent some kind of bad initialization? But isn't AddComponent already allowed to be used only in the same places we could change the component's values anyway? If not, couldn't the constructor simply be limited to those cases?

In any case, I'm just wondering if we can shorten lines of code. So instead of writing something like this:

 MyComponent myComponent = AddComponent<MyComponent>();
 myComponent.MyInitialValue = "Initial Value";

We could write something like this:

 MyComponent myComponent = AddComponent<MyComponent>("Initial Value");

Or at very least (trying to prevent horizontal scroll bars here):

 MyComponent myC = AddComponent("MyComponent", "Initial Value") as MyComponent;


And, of course, allowing us to have as many parameters as we want, just like we would have on a regular constructor.

Just for reference, I've already shortened many lines of code by writing my own `GetOrAddComponent`.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

6 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by cregox · May 01, 2013 at 06:54 PM

Using @dannyskim's suggestion, about Factory Design Patterns...

I'm using a slightly different way of implementing. I think doing it without reflection (like AddComponent("Initial Value") ) is basically impossible. Just get my GetOrAddComponent code there and see if you can.

So, I've mixed up what I wanted with danny's and this is what I came up with:

 public class MyComponent : MonoBehaviour {
   string parameter = null;

   public static MyComponent CreateComponent (GameObject where, string parameter) {
     MyComponent myC = where.AddComponent<MyComponent>();
     myC.parameter = parameter;
     return myC;
   }

And then use as such:

 MyComponent myC = MyComponent.CreateComponent(gameObject, "Initial Value");

The difference here is that I don't create a GameObject, just like AddComponent does not as well. So you're expected to pass along one (again, just like the original), to which gameObject is the current one, by code convention.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
9

Answer by Eric5h5 · Apr 26, 2013 at 05:18 PM

AddComponent returns Component, so:

 AddComponent<MyComponent>().myInitialValue = "Blah";
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image cregox · Apr 26, 2013 at 05:20 PM 1
Share

Interesting! But seems like this is 1/nth of an answer, since it can only reduce for 1 parameter and if we need the instance as suggested on the question, it's not even convenient to use! Although, in practice, it will be good enough many times. :-)

avatar image
2

Answer by dannyskim · Apr 26, 2013 at 05:12 PM

I would suggest using a Factory Design Pattern:

http://answers.unity3d.com/questions/160610/passing-values-into-base-constructor-with-monobeha.html

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by Don-Tako · Oct 14, 2020 at 01:59 PM

Not a one line solution but clean enough without coding any extra methods....

 MyComponent component = AddComponent<MyComponent>();
 component .value1 = "blah";
 component .value2 = "bleh";
 component .value3 = "blih";
 

or

 MyComponent component = obj.AddComponent<MyComponent>();
 component .value1 = "blah";
 component .value2 = "bleh";
 component .value3 = "blih";
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by sisus_co · Dec 28, 2021 at 05:15 PM

It is possible to achieve this without needing to use any reflection - though it requires some ground work to be laid first:

1. Create an interface that defines a method that can be used to pass the argument.
2. Make the interface generic to allow defining the type of the argument in the implementing class.
3. Create an extension method that adds the component and then passes the provided argument through the method defined in the interface.
4. Create classes that implement the interface, assigning the received argument to a member field in the body of the method.
5. To allow passing multiple arguments create copies of the interface and extension method with multiple generic arguments.

So first you'll need something like this:

 public interface IInitializableWithArgument<TArgument>
 {
     void Initialize(TArgument argument);
 }
 
 public class MyComponent : MonoBehaviour, IInitializableWithArgument<string>
 {
     public string myInitialValue;
 
     public void Initialize(string myInitialValue)
     {
         this.myInitialValue = myInitialValue;
     }
 }
 
 public static TComponent AddComponent<TComponent, TArgument>
     (this GameObject gameObject, TArgument argument)
         where T : MonoBehaviour, IInitializableWithArgument<TArgument>
 {
     var component = gameObject.AddComponent<TComponent>();
     component.Initialize(argument);
     return component;
 }
 


After this creating components with arguments becomes easy as pie:

 MyComponent myComponent = gameObject.AddComponent<MyComponent, string>("Initial Value");
 


To see this pattern being put to use in practice you can take a look at my own asset Init(args).

Note that one downside with this system is that the Awake and OnEnable event functions will get called before the Initialize method, so one needs to be careful inside these functions to avoid NullReferenceExceptions taking place (there are ways around this issue as well, but it requires some more complicated code).

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to make sure custom init methods are called? 1 Answer

2D Animation does not start 1 Answer

Using GetComponent in multiple scripts for same component? C# 2 Answers

How to access a Component from another Child when current is Destroyed 1 Answer

Changing a variable from one script to another C# 4 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges