- Home /
How can I modify my script to allow more prefabs?
Hello Unity folks,
I have customized a script for my game but I have a couple of questions about it.
The script I have is choosing the prefab (I have several but the script won't allow me to add more than 1 in the inspector) and is stacking that prefab on itself to end up with an endless game. The game exists of obstacles that the main character has to dodge. This script recognizes the distance the player has traveled and is spawning and deleting the prefabs out of view.
I would like to adjust that script so u can drag more prefabs into the inspector. I would like to adjust the script so it would choose the prefabs randomly.
the inspector looks like this:
The script I have is:
using UnityEngine;
using System.Collections.Generic;
public class LevelManager : MonoBehaviour {
public Transform prefab;
public int numberOfObjects;
public float recycleOffset;
public Vector3 startPosition;
public Vector3 minSize, maxSize, minGap, maxGap;
public float minX, maxX;
private Vector3 nextPosition;
private Queue<Transform> objectQueue;
void Start () {
objectQueue = new Queue<Transform>(numberOfObjects);
for(int i = 0; i < numberOfObjects; i++){
objectQueue.Enqueue((Transform)Instantiate(prefab));
}
nextPosition = startPosition;
for(int i = 0; i < numberOfObjects; i++){
Recycle();
}
}
void Update () {
if(objectQueue.Peek().localPosition.y + recycleOffset < PlayerMovement.distanceTraveled - 15f){
Recycle();
}
}
private void Recycle () {
Vector3 scale = new Vector3(
Random.Range(minSize.y, maxSize.y),
Random.Range(minSize.x, maxSize.x),
Random.Range(minSize.z, maxSize.z));
Vector3 position = nextPosition;
position.y += scale.y * 1f;
position.x += scale.x * 1f;
Transform o = objectQueue.Dequeue();
o.localScale = scale;
o.localPosition = position;
objectQueue.Enqueue(o);
nextPosition += new Vector3(
Random.Range(minGap.y, maxGap.y) + scale.y,
Random.Range(minGap.x, maxGap.x),
Random.Range(minGap.x, maxGap.x));
if(nextPosition.x < minX){
nextPosition.x = minX + maxGap.x;
}
else if(nextPosition.x > maxX){
nextPosition.x = maxX - maxGap.x;
}
}
}
The original script was spawning cubes which were also randomly adjusted by size. I managed to turn this off, but that is the reason it is still in the script. If somebody knows how to remove this it would be better and more efficient, but it is not priority :P
Thank you in advance :)
Answer by DiegoSLTS · Feb 15, 2015 at 01:30 PM
Replace:
public Transform prefab;
with:
public Transform[] prefabs;
and you'll be able to add more than one prefab in the inspector.
Replace:
objectQueue.Enqueue((Transform)Instantiate(prefab));
with:
objectQueue.Enqueue((Transform)Instantiate(prefabs[Random.Range(0,prefabs.Length)]));
and you'll get a random prefab from the list.
To remove the random scaling I think it's enough removing "minSize, maxSize" (this will also remove them from the inspector) and replacing the Recycle method with:
Vector3 position = nextPosition;
position.y += 1f;
position.x += 1f;
Transform o = objectQueue.Dequeue();
o.localPosition = position;
objectQueue.Enqueue(o);
nextPosition += new Vector3(
Random.Range(minGap.y, maxGap.y) + 1f,
Random.Range(minGap.x, maxGap.x),
Random.Range(minGap.x, maxGap.x));
if(nextPosition.x < minX){
nextPosition.x = minX + maxGap.x;
}
else if(nextPosition.x > maxX){
nextPosition.x = maxX - maxGap.x;
}
(I removed all the references to minSize and maxSize and anything related to the scale, and since you want the scale to be always 1, I replaced things like scale.y and scale.x with just "1f")
Hey Diego thank you so much for the quick reply. I am really appreciating your help considering my lacking skills in program$$anonymous$$g. I have applied your code and it is working with randomly choosing the prefabs but it is also distributing the prefabs randomly in the field. Prefab1 goes on a random Y axis as well as the other prefabs. The pairs stay together on that line (prefab1 will follow up itself until there is a gap because of prefab 2 which is somewhere else doing the same thing). Is it possible to put somewhere in the script a code that everything will stick to a fixed Y number or is there a better option?
I'm not sure what the code's supposed to do, but if you want all the instantiated objects with the same "y" remove this line:
position.y += 1f;
... and change this:
nextPosition += new Vector3(
Random.Range($$anonymous$$Gap.y, maxGap.y) + 1f,
Random.Range($$anonymous$$Gap.x, maxGap.x),
Random.Range($$anonymous$$Gap.x, maxGap.x));
... to this:
nextPosition += new Vector3(
Random.Range($$anonymous$$Gap.y, maxGap.y) + 1f,
0,
Random.Range($$anonymous$$Gap.x, maxGap.x));
I guess it should be enough. Note that I just removed all the things that could change the "y" value of the position.
Hey Diego thanks for the information I think only removing position.y += 1f; did the job. I have another question because my prefabs are spawned random when I press start and for the whole game it will be spawned in that order. Do you maybe know what I have to change to the script that every single prefab-spawn will be random during runtime? :)
Well, your code recycles enemies when they reach a certain y position and move them back to the enemies queue, that's why you get the same pattern.
If you don't want to recycle you don't really need a queue, you have to destroy an enemy when it goes out of screen and create a new random one. Since your code uses a queue to store references of all enemies you can keep it, but ins$$anonymous$$d of:
Transform o = objectQueue.Dequeue();
o.localPosition = position;
objectQueue.Enqueue(o);
... do:
Transform o = objectQueue.Dequeue();
o.Destroy(); // destroy the enemy
o = (Transform)Instantiate(prefab); //create a new random one
o.localPosition = position;
objectQueue.Enqueue(o);
I haven't tested it, but something like that should work.
I get this error when I apply the code in my script.