- Home /
How to instantiate a prefab with a script attached?
I've been searching for this for days now and feel stupid because it seems like it should be ridiculously simple...
My game requires me to create and destroy different characters in an environment. I have a prefab called "human" with an attached class "Human" that handles all of its attributes and behaviors.
At runtime I want to create a certain amount of these humans with randomized attributes. I've been searching through these forums for examples, but none of the code seems to work for what I'm doing. I feel like my problems are just syntax, but I've seen so many alternate solutions that haven't worked now that my mind is mud. Rather than copy code, I'm hoping someone can explain how this would ideally be done in Unity from scratch. Thanks for any help!
Answer by Statement · Dec 17, 2012 at 12:37 AM
So let's take a time to think about your problem. You say that you have a human prefab. I will just picture this in my head as a character with a script on it that defines some attributes and leave out the exact details about how it's working inside. Just to give us something to think about in our coder heads, I will make a mock here with some properties that we want to change:
public class Human : MonoBehaviour
{
// The thing we want to modify at runtime.
public Attributes attributes;
// More code that defines what humans do,
// like program awesome scripts or post
// images about cats on facebook...
}
// The set of attributes that our human has access to.
[System.Serializable]
public class Attributes
{
[Range(0, 20)] public float strength = 10;
[Range(0, 20)] public float dexterity = 10;
[Range(0, 20)] public float intelligence = 10;
}
So, a prefab has it's defined values for strength, dexterity and intelligence. Depending on how you want to model your game and spawner logic, perhaps the spawner can decide what the attributes should be for the human and totally overwriting the values? Or perhaps your spawner has links to several different prefabs, so it chooses one of the prefabs when it should spawn a human? It's up to you, I'll try and explain how to make the attributes somewhere of a middle ground between fully designed attributes (hand crafted by a designer) and fully randomized values (binary grinded by computer).
So you could define two extremes of attributes that you want to generate values for, hopefully unique for every human that spawns. In this solution, you could pick a random value for strength, dexterity and intelligence that is defined by a min and a max attribute collection. See the code below:
public class HumanSpawner : MonoBehaviour
{
public Human prefab;
[Range(0, 10)] public int humansToSpawn = 5;
public Attributes min;
public Attributes max;
void Start ()
{
for (int i = 0; i < humansToSpawn; ++i) {
Human human = (Human)Instantiate (prefab);
human.attributes = MakeRandomAttributes ();
}
}
// Have a better way of making random attributes?
// Perhaps you have a set of several templates instead,
// carefully balanced by a designer? Then change this code.
Attributes MakeRandomAttributes ()
{
Attributes result = new Attributes ();
result.strength = Mathf.Lerp (min.strength, max.strength, Random.value);
result.dexterity = Mathf.Lerp (min.dexterity, max.dexterity, Random.value);
result.intelligence = Mathf.Lerp (min.intelligence, max.intelligence, Random.value);
return result;
}
}
This is one way of doing it, but also consider having a public Human[] allPossiblePrefabs; and pick one of those instead, or any mix in between. It's up to you to define what you actually want to randomize. Then decide how you want to randomize it. Should it be finely controlled? Should it be emergent and chaotic?
Caveat: If you are on Unity 3.5, remove the [Range(x,y)] snippets. They are only available in Unity 4 and doesn't do anything more than add fancy sliders to the inspector.
O$$anonymous$$G. Can't thank you enough Statement, I had a similar question, but your way of organizing things helped me more than the answer to the question. Thank you!
Answer by GabeOfThrones · Dec 17, 2012 at 01:52 AM
Wow. Thanks so much for answering so quickly and completely! I was able to solve the syntactical problem I was having immediately with your code!
The key line that I was botching was this:
Human human = (Human)Instantiate (prefab);
It's interesting how you handled the attributes. I may try that style. Currently I was just simply trying to set properties of the Human class. For example:
public class Human : MonoBehaviour
{
public int speed
}
Once I've instantiated human, I try setting speed like:
human.speed = 5;
I don't seem to have access to the object's properties. Do I need to do something additional to get access to those?
Again, thanks for the help, Statement!
Your answer
Follow this Question
Related Questions
Referencing gameObject from script after Instantiate 0 Answers
autolink to prefab? 0 Answers
How many time does a prefab takes to load?? 1 Answer