- Home /
How can I instantiate a object with a constructor?
I created a constructor for my NPCs. I struggle with instantiating them (as a gameobject) via the constructor with its own health etc. And what can I do, to set for each instantiated Gameobject NPC the health etc? I want to something like this: Instantiate(NPC[0], NPC[0].Position, NPC[0].Rotation). I want to Instantiate a prefab with its health etc from the constructor. I cant change the properties from the array of NPC constructors in the inspector, so i need to do it by code.
NPC constructor:
[System.Serializable]
public class NPC : Obstacle
{
public bool HasPath { get; set; }
public GameObject Path { get; set; }
public NPC(float hp, int id, Vector3 position, Quaternion rotation,GameObject prefab, bool hasPath, GameObject path) : base(hp, id, position, rotation, prefab)
{
HP = hp;
ID = id;
Position = position;
Rotation = rotation;
HasPath = hasPath;
Path = path;
Prefab = prefab;
}
public void CreateNPC()
{
Instantiate(this.Prefab, this.Position, this.Rotation);
}
}
Answer by rh_galaxy · Apr 04, 2021 at 07:56 AM
A variant of the answer above is that you can skip the extra classes and just Init the Instantiated object directly.
//Level.cs
public class GameLevel : MonoBehaviour
{
//drag your prefab with Enemy-script
//attached to this var in the Inspector
public Enemy oEnemyObjBase;
//List<Enemy> aEnemyList;
void BuildLevel()
{
Enemy oEnemy = Instantiate(oEnemyObjBase, this.transform);
oEnemy.Init(10.0f);
//aEnemyList.Add(oEnemy); //you can also save the enemy in a list for easy access
}
//...
}
//Enemy.cs
public class Enemy : MonoBehaviour
{
float fHealth;
public void Init(float health)
{
fHealth = health;
}
//....
}
Right and additionally you could aim for a chaining structure as you may know from other languages. So you can implement your Init method like this:
public Enemy Init(float health)
{
fHealth = health;
return this;
}
That way you can simply chain the Init method after your Instantiate call in a single line which gives a more "constructor like" feeling:
Enemy oEnemy = Instantiate(oEnemyObjBase, this.transform).Init(10.0f);
Thanks rh_galaxy and Bunny83, this is a really nice solution. What exactly is return this
doing in this Init function? It's the one part where I don't quite understand why it's necessary.
As I said it allows "chaining". Usually when you call Instantiate you get back a reference to the newly created object. If you directly call a method on that instance, you can not store that instance in a variable at the same time. If the Init method is a normal method without a return type (void) the example line at the end of my comment would not work. By having the Init method returning its own instance you can chain either method calls or, as in my example, store or use the reference afterwards.
Actually the example that rh_galaxy gave is exactly this case. He first stores the reference in a variable and then calls the method on that stored reference. So if you want to store the enemy in a list like in the commented out example you need those 3 lines. When Init returns its own instance you can simply do
aEnemyList.Add( Instantiate(oEnemyObjBase, transform).Init(10.0f) );
Here the return value of the Init method will actually be passed into the Add method of aEnemyList.
This is not "necessary" as you called it. The answer of rh_galaxy works fine as it is. I thought I already made it clear by introducing my comment with:
additionally you could ....
... That way you can simply chain the Init method after your Instantiate call in a single line which gives a more "constructor like" feeling
: The whole concept is known as Fluent interface.
Answer by KoenigX3 · Apr 04, 2021 at 07:03 AM
If you have NPC objects with custom values, and you want to instantiate gameobjects with those NPC components, you could use something like this:
GameObject go = Instantiate(this.Prefab, this.Position, this.Rotation);
go.AddComponent<NPC>().Setup(this);
Since I cannot control the constructor, I use the Setup() method to set the values. As a parameter, I would use another NPC object, and basically copy the values from it.
public void Setup(NPC npc)
{
HP = npc.HP;
ID = npc.ID;
//...
}
Answer by amitDklein · Dec 10, 2021 at 08:58 PM
Hey, I just found this article. It basically say that you can create a object with the variables and then instantiate it.
.
Your answer
Follow this Question
Related Questions
Can't assign an instantiated class to an array? 1 Answer
Instantiating gameobjects in an array / class problem | NullReferenceException: 0 Answers
How to add GameObject to List using a constructor method 1 Answer
Selecting the currently active gameobject in an array to move its values 0 Answers
Material[] Object reference not set when instantiating 2 Answers