- Home /
How to create Prefab with property
I couldn't figure it out by myself. I need some sort of system / object like this in C#
units {
weight : float = 1.5;
points : float = 0.5;
}
so the thing is, each of my enemy prefab should have this type of property. So when i will spawn an enemy like
Instantiate (enemies[0], position, rotation);I like to access enemies[0] points and weight information like
enemies[0].weight;Please help me out.. thanks in advance :)
enemies[0].points;
Answer by Bunny83 · Jun 25, 2012 at 12:49 PM
You can do it like you did, but not if you store GameObject references. You should attach an EnemyScript to each of the prefabs and change the reference type to this script. If each enemy has already a specialized script attached, you might want to create an EnemyBaseClass from which all other enemy scripts are derived from:
public class EnemyBaseClass : MonoBehaviour
{
public float weight;
public float points;
}
// For example a script for the Asteroid enemy:
public class Asteroid : EnemyBaseClass
{
// Asteroid specific stuff
public float size;
}
Now you can setup your script above like this:
// [...]
public EnemyTypes CurrentEnemyType = EnemyTypes.Asteroid;
private Dictionary<EnemyTypes, EnemyBaseClass> Enemies = null;
public EnemyBaseClass AsteroidEnemy;
//[...]
void Start() {
GameStartTimer = Time.time;
Enemies = new Dictionary<EnemyTypes, EnemyBaseClass>(3);
Enemies.Add(EnemyTypes.Asteroid, AsteroidEnemy);
Enemies.Add(EnemyTypes.MiniCraft, MiniCraftEnemy);
Enemies.Add(EnemyTypes.Banzai, BanzaiEnemy);
}
Another thing is that Instantiate will create an instance of the given prefab, so it makes no sense to change the prefab itself. Instantiate will return the newly created object. Instantiate will return the same type that you provide. So we give an EnemyBaseClass component so it will return that component of the cloned gameobject. However it need to be casted since Instantiate can clone any kind of Unity objects.
EnemyBaseClass clone = (EnemyBaseClass)Instantiate(Enemies[CurrentEnemyType], Position, Quaternion.identity);
clone.weight = 25.0f;
Keep in mind that the actual script that is attached to the enemy can be any derived type of EnemyBaseClass. But since our reference is of type EnemyBaseClass we can only access the EnemyBaseClass stuff which all enemy types share.
That means for example you attach an Asteroid-script to your asterois prefab and drag it onto the AsteroidEnemy variable so it will be added to the dictionary. Since the Asteroid script is also an EnemyBaseClass you can so this. From your instantiate scripts point of view it only have to work with the general EnemyBaseClass, but the actual instance will have an AsteroidEnemy script.
That's the basic idea of inheritance ;)
Hi again... i got it.. Now ive implemented something like this, is it ok..
public class UnitBudget { public float weights { get; set; } public float points { get; set; }
} public class GameController : $$anonymous$$onoBehaviour { public enum EnemyTypes { Asteroid, $$anonymous$$iniCraft, Banzai, FooFighter, DoggyTrail, $$anonymous$$otherShip }
public EnemyTypes CurrentEnemyType = EnemyTypes.Asteroid;
[...]
private UnitBudget[] uBudget = new UnitBudget[3];<br/>
private Dictionary < EnemyTypes, GameObject > Enemies = new Dictionary < EnemyTypes, GameObject >(3);
private Dictionary < EnemyTypes, UnitBudget > UnitBudgets = new Dictionary < EnemyTypes, UnitBudget >(3);
void Awake() { for (int i = 0; i < 3; i++) { uBudget [i] = new UnitBudget(); uBudget [i].weights = i 1; uBudget [i].points = i 2;
}
UnitBudgets.Add(EnemyTypes.Asteroid, uBudget [0]);
UnitBudgets.Add(EnemyTypes.$$anonymous$$iniCraft, uBudget [1]);
UnitBudgets.Add(EnemyTypes.Banzai, uBudget [2]);
Debug.Log(UnitBudgets[EnemyTypes.$$anonymous$$iniCraft].weights);
// which is giving me 1 } }
Sure, if this extra data (weights,points) should be the same for one enemytype it's ok that way. But if the values are really just calculated the way you have it at the moment, you don't need to store it at all ;) a function that calculates it would be enough ;)
At the moment it seems that the EnemyType ordinal value (the actual integer value from the enum) equals your "i" variable in your for-loop.
A function that calculates the "weight" or the "points" for a certain enemy could look like this:
public static float GetEnemyWeight(EnemyTypes aType)
{
return ((int)aType) * 1.0f;
}
public static float GetEnemyPoints(EnemyTypes aType)
{
return ((int)aType) * 2.0f;
}
Oh, btw, your EnemyType
`s` enum should be named EnemyType
since this a variable of this data type describe one enemy type.
But this does not instantiate the prefab which has this script. How do you instantiate the prefab?
Have you missed the 3rd code section in my answer? The only where i instantiate the prefab? ^^. You may want to re-read the whole answer, maybe you missed something else or did not fully understand what's the point here.
$$anonymous$$eep in $$anonymous$$d that the prefab instantiation has to be done on an object that is already in the scene. Prefabs are just passive assets resting in the assetdatabase and wait for being instantiated.
Answer by Mizuho · Jun 25, 2012 at 08:57 AM
Use an Accessor: http://msdn.microsoft.com/en-us/library/aa287786%28v=vs.71%29.aspx.
Or attach a script to your prefab.
Thanks a bunch.. I think i got it. but i couldn't implement it in my current script public enum EnemyTypes { Asteroid, $$anonymous$$iniCraft, Banzai, FooFighter, DoggyTrail, $$anonymous$$otherShip }
public EnemyTypes CurrentEnemyType = EnemyTypes.Asteroid;
private Dictionary Enemies = new Dictionary (3);
void Start() {
GameStartTimer = Time.time;
Enemies.Add(EnemyTypes.Asteroid, AsteroidEnemy);
Enemies.Add(EnemyTypes.$$anonymous$$iniCraft, $$anonymous$$iniCraftEnemy);
Enemies.Add(EnemyTypes.Banzai, BanzaiEnemy);
}
// so if i want to spawn any enemy i use -- Enemies[CurrentEnemyType]--
Instantiate(Enemies[CurrentEnemyType], Position, Quaternion.identity);
So i was hoping if i could use like
Enemies[CurrentEnemyType].weight
The way you declared your Dictionary, Enemies[CurrentEnemyType] will return a type GameObject
, which knows nothing of your properties. As $$anonymous$$izuho suggested, create a script dealing with these properties/members, attach it to your GameObject. Then you could do something like
Enemies[CurrentEnemyType].GetComponent<$$anonymous$$yScriptClassDealingWithEnemyAttributes>().weight
(note doing GetComponent() on-the-fly is rather expensive, you might want to store a reference to your script directly in the dictionary (ins$$anonymous$$d of the GO), or cache it some other way.
Ah... thats right. I will try it. so.. Can i make it this way then..
Enemies
{
weight: float;
points: float;
prefab: GameObject;
}
so I will create all my enemies so each one will contain those three properties.. enemies[0].prefab containing the gameobject and so on..
sorry if im wrong in this way.. i used to do it in Javascript object.. so is there any way to do it in C# thanks for helping :)
Your answer
Follow this Question
Related Questions
Spawning too many Objects when loading the World (k_eresultlimitexceeded) 0 Answers
Multiple Cars not working 1 Answer
How to use tag for all players in the Instantiate. 0 Answers
Distribute terrain in zones 3 Answers
how to spawn object on the player C# 2 Answers