Search Unity

Instantiate with constructor is it possible?

Discussion in 'Scripting' started by Maraku Mure, May 12, 2015.

  1. Maraku Mure

    Maraku Mure

    Joined:
    May 2, 2015
    Posts:
    28
    Hi guys,
    I need an advice...I'm trying to reorganize some scripts in my personal game project "Do it so you will learn" =P

    In this project I need to instantiate a prefab enemy one by one (so when the first enemy will die, the seconds will be instantiated).

    I want to pass some argument when the enemy is created, I know that a constructor functions with the "new" code i.e.:

    Code (CSharp):
    1. public class Example {
    2.        public int health;
    3.  
    4.        public Example(int baseHealth, int level)
    5.        {
    6.                   health = baseHealth * level;
    7.        }
    8. }
    9.  
    10. public class anotherClass
    11. {
    12.           Example ex;
    13.  
    14.           void Start() {
    15.                  ex = new Example(500,2);
    16.           }
    17. }

    But how to do when I have to instantiate a prefab and I want to pass arguments to the constructor?
     
  2. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    Personally, I would use MonoBehaviours instead of Object class. That way when I instantiate an opponent with code:
    Code (CSharp):
    1. public GameObject enemyPrefab;
    2. public Transform spawnPoint;
    3.  
    4. public GameObject SpawnEnemy(int level, int hp)
    5. {
    6.      GameObject enemy = Instantiate( enemyPrefab, spawnPoint.position, Quaternion.identity) as GameObject;
    7.    
    8.      enemy.GetComponent<ActorController>().level = level;
    9.      enemy.GetComponent<HealthComponent>().value  = hp;
    10.  
    11.      return enemy;
    12. }
    I can set all relevant data when he is instantiated. Not to mention using MonoBehaviour, you can inspect your script values in inspector whereas using just object would need extra work with serialisation to make it work if I'm not mistaken.

    Please note this is just a basic example, personally I would use some other way to assign data to your enemy, like loading values from a database or something.
     
    StrawBox, DonPuno and ndb796 like this.
  3. Maraku Mure

    Maraku Mure

    Joined:
    May 2, 2015
    Posts:
    28
    Hi Fajlworks and thanks for your reply.

    Actually my function is this one:
    Code (CSharp):
    1.     public void CreateEnemy()                          
    2.     {
    3.         enemyInstance = Instantiate (enemyObj [Random.Range (0, enemyObj.Length)], new Vector2 (0, 0), Quaternion.identity) as GameObject;             // Instantiate a random monster among those referenced.
    4.         if (enemy == null) {
    5.             enemy = enemyInstance.GetComponent <Enemy> ();
    6.         }
    7.  
    8.     }
    All values are calculated inside the Enemy class. Now I need to pass the enemylevel to enemy class because I wrote a saving and a loading functions so I need to pass the enemy level when I load...
     
  4. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    Hmm, how does Enemy class look like? What is "enemylevel" you are referring to? Is it a int or another class? What are those saving and loading functions? Are those PlayerPrefs or your custom code?

    Since you didn't provide any extra info, I'll assume you need:

    Code (CSharp):
    1. public void CreateEnemy()                      
    2. {
    3.     enemyInstance = Instantiate (enemyObj [Random.Range (0, enemyObj.Length)], new Vector2 (0, 0), Quaternion.identity) as GameObject;             // Instantiate a random monster among those referenced.
    4.     if (enemy == null)
    5.     {
    6.         enemy = enemyInstance.GetComponent <Enemy> ();
    7.         enemy.level = 10; // I guess? O.o
    8.  
    9.        // or
    10.  
    11.         enemy.level = GameManager.Instance.currentLevel; // I assume GameManager loads/saves current level
    12.     }
    13. }
     
  5. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    Code (csharp):
    1.  
    2.     enemyInstance = Instantiate(...);
    3.     enemy = enemyInstance.GetComponent<Enemy>();
    4.    
    5.     if(enemy)
    6.     {
    7.         enemy.Initialise(...parameters...)
    8.     }
    9.  
    Code (csharp):
    1.  
    2. //in enemy class
    3.  
    4. public void Start()
    5. {
    6.     /// setup stuff that isn't dependant on parameters
    7. }
    8.  
    9. public void Initialise(...parameters...)
    10. {
    11.     /// setup stuff from the parameter values
    12. }
    13.  
     
    Fajlworks likes this.
  6. Maraku Mure

    Maraku Mure

    Joined:
    May 2, 2015
    Posts:
    28
    Ok :D I thought there was another way to declare a constructor or something similar =)
     
  7. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    the unity game engine "constructs" GameObjects and Components and the like... I'm really not the one to comment on what it does internally for that to happen (voodoo and something to do with sacrificing virgin chickens I suspect). You're not working directly inside that when you instantiate something, you're just given the completed "thing" at the end of the instantiation.
     
    eisenpony likes this.
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You can use a factory pattern to allow for constructor like behaviours

    Code (CSharp):
    1. public class Factory : MonoBeheviour {
    2.  
    3.     bool isInitialised;
    4.  
    5.     void Start () {
    6.          if(!isInitialised) {
    7.              Debug.LogError("component can only be created with factory method", this);
    8.              Destroy (this);
    9.              return;
    10.          }
    11.     }
    12.  
    13.     public static void AddFactory (GameObject target, ...) {
    14.         Factory clone = target.AddComponent<Factory>();
    15.         // Do initialisation
    16.         clone.isInitialised = true;
    17.     }
    18. }
     
    Fajlworks and Ryiah like this.