Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question [SOLVED]Different Between AddComponet<> and directly adding scripts into gameobjects

Discussion in 'Scripting' started by zoeyz0102, Dec 19, 2022.

  1. zoeyz0102

    zoeyz0102

    Joined:
    Nov 9, 2022
    Posts:
    20
    Hi guys !
    Recently I am working on an project which I need to add Mutiple scripts into one gameobjects. So I'd like to using one script to add them all.

    However, there are some uninitialized feild parameters such as List<object> in the plugins I used. If I add those plugins' scripts into the gameobjects, the feild parameters will be init automatically. While I was apply this.transfrom.gameobject.AddComponent, there will be "Object reference not set to an instance of an objec" error.

    Dose anyone know how to sove this issue without adding extra init methods? Thanks
     
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,572
    This is quite vague. Do you need to add them at runtime or do you just want to add multiple scripts at once in the editor? Those are two very different things. Adding components in the editor (the authoring tool), the inspector will take care of initializing and serializable fields when the object is serialized / deserialized for the first time. If you add a component at runtime through scripts, nothing of that would happen so you are yourself responsible for initializing any fields / variables. A common solution is to just add a field initializer like you would in normal C#.

    Code (CSharp):
    1. public class MyComponent : MonoBehaviour
    2. {
    3.     public List<Transform> objs  = new List<Transform>();
    4.     // [ ... ]
    5. }
    6.  
    This would make sure the variable does have an actual List instance. Of course this list would be empty.

    If instead you want to be able to add additional components in the editor when you add a certain component, you can do that with the RequireComponent attribute. Note that RequireComponent is also a pure editor feature. It only applies when adding components in the editor, NOT when adding them through AddComponent at runtime.

    As I said in the beginning, it's not that clear what exact usecase you have.

    If you want to write an editor script to add components, which again is a different topic, you should use the correct editor function to do that. In this case Undo.AddComponent. Though to be honest, I'm not sure if adding a component this way would actually initialize the fields of the component if it's not viewed in the inspector. You may have to try it out. Keep in mind that editor scripts are seperate from runtime scripts. You can not use editor functions / classes in runtime scripts. Those are extensions for the editor.
     
    zoeyz0102 and lordofduct like this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,954
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,384
    This is happening because when you add a script through the editor, and when the game loads the scene with that GameObject, it deserializes its state from the scene file. In doing this it automatically initializes all serialized fields, the unity serializer leaves no field null!

    When you use AddComponent, it isn't passed through this deserialization step, and therefore all your serialized fields are not ran through and populated. You must manually do that yourself. May it be in the Awake method, or directly where the field is declared.

    It'd be a good habit to do something like this:
    Code (csharp):
    1. public MyScript : MonoBehaviour
    2. {
    3.  
    4.     public List<float> myList = new List<float>(); //instantiate at point of declaration
    5.     public List<GameObject> otherList;
    6.  
    7.     void Awake()
    8.     {
    9.         if (otherList == null) otherList = new List<GameObject>();
    10.     }
    11.  
    12. }
    If for whatever reason you can't do it this way because the data that gets put in it is dependent on information being passed to it (i.e. what would usually be dealt with via a parameterized constructor), that's where Factory Patterns like what Kurt-Dekker suggested come into play.

    Heck... I too like Kurt generally will stick with the Factory Pattern for all scenarios just for consistency sake. Makes for easier reading.

    ...

    I'm with Bunn83 though... is there a reason you need to add all of these components at runtime rather than at designer time?
     
    zoeyz0102 and Bunny83 like this.
  5. zoeyz0102

    zoeyz0102

    Joined:
    Nov 9, 2022
    Posts:
    20
    Thanks for your answer. Actually, I am a beginer of Unity script coding,hadn't using Unity or C# until 1 month ago. I am still play around to find the way that achieve one goal with different methods. Now I understood the differ between adding script through Editor and GameObject.AddComponent.