- Home /
How can I access a GameObjects components using an instantiation variable?
I am trying to dynamically spawn enemies. All variables are declared and set prior to the instantiation code.
_enemy_1 = Zombie; (Zombie is a prefab.) _zombie_level is a variable, which is in a Zombie script attached to its prefab.
_spawned_enemy_1 = Instantiate(_enemy_1, _enemy_1_spawn_position, Quaternion.identity);
Zombie _Zombie = _spawned_enemy_1.GetComponent<Zombie>();
_Zombie._zombie_level = _enemy_1_level;
This is what I have so far and it works fine. However, I don't want to hard-code anything (if possible), which means not using the prefab name Zombie to GetComponent.
Is there a way I can access the _zombie_level variable using _spawned_enemy_1 as the GameObject? _spawned_enemy_1 is not a prefab, so I am receiving errors. I hope my explanation was clear and I appreciate any suggestions.
Thank you!
I am not sure if it is what you want, but you could simply skip the 2nd line
_spawned_enemy_1.GetComponent<Zombie>()._zombie_level = _enemy_1_level;
Thanks for the quick response. However, I'm trying not to use "Zombie" at all. Perhaps, I'll need to change "_zombie_level" to just "_level" since it may not end up being a zombie. I hope I make sense!
Since _enemy_1 = Zombie, I attempted to use: _spawned_enemy_1.GetComponent<_enemy_1>();
It didn't work. I wanted to use: _spawned_enemy_1._zombie_level = (an integer variable; 1, 2, etc.);
With the above mentioned changed it would then be: _spawned_enemy_1._level = 1 or another integer.
Any other suggestions would be much appreciated. Is my implementation way off?
I'm asking a question out of confusion. Are there other enemy types which has _level field named differently but has same purpose?
Answer by IINovaII · Jan 08, 2020 at 03:43 PM
Doing it that way will only lead to bloating code and can become unmanageable as the number of enemies grows. Using the game object name to differentiate enemies is a terrible practice. If all you wanted to do is access level variable which all the enemies have, you can do this either through inheritence or by composition.
Inheritance Method
All enemies should inherit from the same class which contains the variable level. It would look something like this.
public class Enemy : Monobehaviour
{
public int Level;
}
public class Zombie : Enemy {}
You can get the component to set the zombie's level like this.
Enemy enemy = _spawned_enemy_1.GetComponent<Enemy>();
enemy.Level = _enemy_1_level;
You can check if it's a zombie or not by doing something like this.
if(enemy is Zombie)
Debug.Log("This is a zombie.");
Composition Method
You can do the similar thing using interfaces. Add an interface called ILevelable to Zombie class. It would look something like this.
public interface ILevelable{
int Level {get;set;}
}
public class Zombie : Monobehaviour, ILevelable{
public int Level {get; set;}
}
You can just access the enemy via the interface like this as long as they contain this interface.
ILevelable enemy = _spawned_enemy_1.GetComponent<ILevelable>();
enemy.Level = _enemy_1_level;
Using interfaces would also benefit making it easier for Unit testing. Breaking it down into more components as you did with levelable is what I think aligns with Unity's patterns.
It's encouraged to use composition over inheritance in games development, at least. You can easily swap in/out easily unlike in inheritances. Inheritances can get too difficult to maintain when the level of inheritance is too high.
That's exactly what I was trying to do.
I've already implemented it and cleaned up a LOT of my code in the process. Your explanation was great as well.
Item marked as Best Answer. Reputation point granted.
Thanks much!
I'm glad that I was able to help you out. -Nova
Answer by Brithingr · Jan 07, 2020 at 04:42 PM
_spawned_enemy_1.getComponent<neededComponent>();
. Dont forget to use an explicit typification when instatiat and object
I'm not sure how to use explicit typification.
The only way I've been able to get it to work is by specifically using "Zombie" as such: _spawned_enemy_1.getComponent(Zombie);
I am unable to replace "Zombie" with a variable, since the variable is not a prefab GameObject. Would an explicit typification at instantiation resolve it? Can you give an example?
If explicit typification does not work (although I hope it does), would it be possible to create a blank "_enemy_1" prefab without a sprite or script attached to it. Afterward instantiation, set a parent, script, and sprite?
Answer by MrBunny · Jan 07, 2020 at 06:30 PM
Something like this might work. I believe unity will try and pull the first component it can find that is using the IZombie interface.
public interface IZombie
{
int zombie_level { set; }
}
public class Zombie : MonoBehaviour, IZombie
{
public int _zombie_level = 0;
public int zombie_level { set => _zombie_level = value; }
}
public class mySpawner : MonoBehaviour
{
GameObject _enemy_1;
Vector3 _enemy_1_spawn_position;
GameObject _spawned_enemy_1;
public void SpawnMe(int _enemy_1_level)
{
_spawned_enemy_1 = Instantiate(_enemy_1, _enemy_1_spawn_position, Quaternion.identity);
var _Zombie = _spawned_enemy_1.GetComponent<IZombie>();
_Zombie.zombie_level = _enemy_1_level;
}
}
Answer by evildead9000 · Jan 08, 2020 at 02:41 PM
Thanks for all for the suggestions. However, they weren't quite what I was looking for. I didn't want any reference at all to Zombie or to hard code it. I was only able to get it to work using a function, which contained a switch if the _spawned_enemy_1.name matches, so it would still work dynamically.
Get_Enemy_Component(_spawned_enemy_1.name, _enemy_1_level);
Here is the function:
private void Get_Enemy_Component(string enemy_Type, int _enemy_level)
{
switch(enemy_Type)
{
case "Zombie(Clone)":
Zombie _Zombie = _spawned_enemy_1.GetComponent<Zombie>();
_Zombie._level = _enemy_level;
break;
}
}
As I add more enemies, I can add more switch cases. I didn't want any reference to Zombie because I will make "_enemy_1" equal a different prefab (for game level 2 and so forth), like "Creature" for example. I'll then add a case to it in the switch; that way I can use the same code to call upon whatever prefab I choose.
I'm still kind of new to Unity, and there may be a better way, but it's working well now.
As per IINovaII's comments above, this way does indeed get messy.
Your answer
Follow this Question
Related Questions
Enable/Disable a Component by using a String Variable for the Component name 2 Answers
Problem: Random Instantiating more than one prefab? 1 Answer
Accessing a variable of a script from another scene. 7 Answers
Change variable of ex2D Sprite using the component ExScreenPosition via code .js script 0 Answers
Access the same component 1 Answer