- Home /
How to spawn Prefab to a certain position.
Test scenario: 2D game. Lets say our hero runs to a magical area, stepping into that area spawns a magical door (a prefab) a certain number of units to the right. I need it to be independent to the spawning triggers location. That way I can put as many of them, and wherever I want them to be. After some searching I found a few scripts of instantiate, but they only spawn ON the trigger, not next to. I have experience in JavaScript. And I was pretty fluent, but haven't touched it in about a year.
This is the simple code I'm using right now:
public var prefab : GameObject;
private var instObj : GameObject;
function OnTriggerEnter2D(other: Collider2D) {
if(other.gameObject.name == "NLT"){
Debug.Log("Box went through!");
}
instObj = Instantiate(prefab,transform.TransformPoint(Vector3.forward), Quaternion.identity);
}
Futhermore, while we're here, I want to be able to randomly select from 3 TYPES of Doors, and then randomly from those 3 types. My line of thinking would be assign them to a class, then tell it to choose "randomly" from that class? (There's probably a better method to it) But the last time I told code to do anything randomly was with C++ about 6 years ago. I've dabbled (right now) Random.Range giving me an Int. Which I can use. i.e. Range of 1-4. Depending on if it gives me a 1/2/3, Thats what "class" of door I get. What I want to do next is choose 1 from 10 different doors in that specific class.
So, our hero runs into a magic spot, script chooses either door class 1, 2, or 3. Then, it chooses one door from 1-10 from that class. This interaction needs to happen randomly whenever our hero runs into a magic spot, no matter how many he runs into. When the door is chosen, it is spawned X units away. That's my goal.
So if you kind people could help me start learning how to do that, I would be very glad.
Answer by DanielAtYatek · Aug 31, 2014 at 06:51 PM
Hi, Your trigger function seems to be fine, it should spawn 1 unit away from the centre of the game object that has the trigger. However, TransformPoint is affected by scale so if your gameobject's or its parent's scale is not 1 on all the axis, you can get really strange results. In that case you shouldn't use transformpoint. Try this: (sorry, I'm more of a C# person so first I write it in C#)
Vector3 newPostion = new Vector3(transform.position.x + 1.0f, transform.position.y, transform.position.z); instObj = (GameObject)Instantiate(prefab, newPosition, Quaternion.identity);
In Javascript it must be something like this:
var newPosition : Vector3; newPosition = transform.position + Vector3(1,0,0); instObj = Instantiate(prefab, newPosition, Quaternion.identity);
I'm not sure I understand the second part of your question, but I'll try to come up with something.
Chosen as best answer because it helped me accomplish exactly what I originally asked for. Thank you to everyone who joined in.
Answer by AlwaysSunny · Aug 31, 2014 at 06:00 PM
You're on the right track. I don't know whether lists work the same in Javascript, but you could have a public collection of doors, and grab a random index using Random.Range(0, myDoors.Count);
assuming you always want these doors to spawn N number of units to the right of your trigger, you can select a random number N, then add it using transform.TransformPoint(Vector3.forward + N)
Thanks everyone. That JS snippet is working almost perfectly. but it spawns relative to the contact point. Now I'll try to figure out why after I post this, but maybe you guys can faster. in any case, i'm closer. So thanks! EDIT: I figured it out. I had moved the spawning script over to the trigger ins$$anonymous$$d of the player when I added the snippet to fix it, but experienced a crash. Then forgot to move it over again when I booted back up.
The second part, imagine this: There are three types of chests. WEAPONS class chests, POWER-UP class chests, and HEALING class chests. in each of those classes, there are 10 (or so) different types of chests that can be chosen. I.e. if Weapons>Sword/Axe/Dagger/??? Etc
I think I would need a script to perhaps choose an Int from 1 to 3, create an array I can fill with prefabs. Then, have the script check which int is chosen, and choose something from each array. OR, have the script randomly grab something with certain tags. Such as "Randomly choose an item with a tag 'weapon'/'health'/'power-up'.
I do think that an array/list would work better because i don't want the same thing to be chosen twice. Perhaps make it so once it's chosen, it's excluded from the list/array??
soo
var chestType = Random.Range(0,4);
function *something*{
*Create weapons array*
*Create Health Array*
*Create PU Array*
if(chestType == 1){
*Choose randomly from Weapons array*
*Then remove it from array*
}
if(chestType == 2){
*Choose randomly from Health array*
*Then remove it from array*
}
if(chestType == 3){
*Choose randomly from PU array*
*Then remove it from array*
}
I don't really know any other language except JS. But I'm guessing that's the logic might run.
I'll help by suggesting you ditch Javascript. ;)
Any time you want several types of objects which have very similar properties / behaviors, you should consider making them variants of - or derivations of - a class. In your case, seems like you'd want a Chest class and a Door class, since you've got various chests and doors that do different things, appear different, etc, but are basically very similar.
Say you wanted to use the variant method, ins$$anonymous$$d of derivations. Frankly this seems more appropriate for a simple game. You'd have a single Chest class, but create several prefabs in the inspector. Each prefab can have its own model, material, whatever.
When you want a random chest, you have a list of those prefabs somewhere, and select a random element of that list to instantiate. The behavior of the chest/door/whatever could be driven by a switch that exa$$anonymous$$es the chest's enum "type" variable.
In response to your edited comment:
Yeah, you could remove whatever you chose from the array. For a simple project just go with that. However, it's good practice to keep prefabs untouched, including collections of prefabs. In that case, you'd keep a list of the indexes you've chosen, and keep choosing new random indexes until you get one that isn't on the list, use that unused index to instantiate the prefab, then add it to the list too.
EDIT: I have a code I pieced together. It spawns three level chunks. The first two from one list (normal levels), the third from another list (Boss levels). I plan on having this called only once per loadable session. So I think it's almost exactly what I need.
I want the player to reach a "safe zone" after getting through those three level sections. Then I want the previously loaded sections to be destroyed (to save on processing consumption), and a brand new section to be created. How would I do that? Assign those prefabs a class, and have the script destroy everything with that class identifier? Each section is going to be different, so each of them can all have their own different identifiers.
With this method, I wouldn't need to remove anything from the list, as each section would be calling from different lists. As far as I can tell, it's not too complicated to work. Would someone $$anonymous$$d taking a gander at the code and tell me if it'll screw me over down the road, or for a simple function, It'll work just fine? Thanks!
public var prefab : GameObject[];
public var bossLevels : GameObject[];
private var instObj : GameObject;
var HasSpawned : boolean = false;
function OnTriggerEnter2D(other: Collider2D) {
if(other.gameObject.name == "2D Character"){
if(HasSpawned == false){
var toSpawn : GameObject = prefab[Random.Range(0, prefab.Length)];
var toSpawn2 : GameObject = prefab[Random.Range(0, prefab.Length)];
var toSpawn3 : GameObject = bossLevels[Random.Range(0, prefab.Length)];
var newPosition : Vector3; newPosition = transform.position + Vector3(50,0,0);
instObj = Instantiate(toSpawn, newPosition, Quaternion.identity);
var newPosition2 : Vector3; newPosition = transform.position + Vector3(90,0,0);
instObj = Instantiate(toSpawn2, newPosition, Quaternion.identity);
var newPosition3 : Vector3; newPosition = transform.position + Vector3(136,0,0);
instObj = Instantiate(toSpawn3, newPosition, Quaternion.identity);
}
HasSpawned = true;
}
}
Your answer
Follow this Question
Related Questions
Monster Spawner 3 Answers
Spawn object in random areas 2 Answers
Randomly generated number 0 Answers
How can I make my prefab fire out at a random velocity every 2 secs 2 Answers
Prefab connection is not breaking? 0 Answers