- Home /
Trying to instantiate random enemy prefab from array
I've been teaching myself how to use Unity for the past month or so now. I originally wrote my Enemy Spawner script with hard coded values, and decided to clean and optimize it by using a coroutine and an array. I've now hit a snag with the instantiate.
I know WHAT I need to do, but I'm still unfamiliar with Unity.
function SpawnRandomEnemy()
{
//var EnemyPrefab = ChooseRandomPrefab();
var RandomIndex = Random.Range(0, EnemyDroneArrayLength);
Instantiate(EnemyDroneArray[RandomIndex, transform.position, Quaternion.identity]);
//Enemy_Drone_1.Instantiate(Enemy_Drone_1, transform.position, Quaternion.identity);
//Enemy_Drone_2.Instantiate(Enemy_Drone_2, transform.position, Quaternion.identity);
}
I've left the commented lines in to show what I've been trying. I know that those last 2 lines are not what I want, however they are, in a sense. I know that I want to randomly spawn either enemy 1 or enemy 2 (as I add more basic enemies, this would go up). The last 2 lines will cause both enemies to spawn at the same time, instead of one or the other. With this snippet of code, however, I am receiving this error:
Assets/Main Scene/Scripts/Enemy_Spawn_Script.js(69,32): BCE0017: The best overload for the method 'Array.get_Item(int)' is not compatible with the argument list '(int, UnityEngine.Vector3, UnityEngine.Quaternion)'.
I understand that RandomIndex is an int, I'm just not sure what I am overlooking here. Probably something so simple that the answer is staring me in the face, and I'll slap myself once I realize what it is.
The entire script can be found here: http://pastebin.com/zyJ8CUuF. The snippet is located between lines 65 - 73.
Edit: To give a better idea, I have a GameObject "Enemy Spawner" that bounces left and right constantly, and will randomly spawn an enemy at a random interval. The enemies just fall down from the top of the screen to the bottom.
Answer by hamstar · Mar 28, 2014 at 01:25 PM
It would be good to move the length variable assignment into Start to make sure the Array has been initialised before you check its length.
I also recommend you stick to convention of beginning variable names with a lower-case letter, in order to differentiate them from properties and methods/functions.
You can declare your array like this and just drag the prefabs into the array in the inspector:
#pragma strict
public var enemyDrones : Transform[];
private var enemyDronesLength : int;
function Start () {
enemyDronesLength = enemyDrones.Length;
}
They're initializing. I get the same length return in both locations (2) on the inspector. However I still get 'ArgumentException: The prefab you want to instantiate is null.' as an error. Somehow, somewhere, it's not pulling the prefab to instantiate.
There is no need to separately define Enemy_Drone_1 and Enemy_Drone_2 as variables. Define the array like this:
var enemyDrones : Transform[];
Now define the size of the enemyDrones array in the object inspector (i.e. 2), then drag the 2 prefabs, one at a time, into the Element0 and Element1 slots.
I'll mark this as solved since this worked! Bad news is I somehow mucked something up to where the level no longer increases, and the player doesn't spawn.
Also, the coroutine how I had it would fire once as soon as I started the game, and wouldn't trigger again. So I took the coroutine out and changed it back to how I had it. Looks like I have some more digging to do though!
I'm on my phone so can't really type code. Your coroutine doesn't have anything to keep it running.It will just pause at the end then stop. If you want it to keep repeating, you should place all the code in the coroutine inside a loop. Such as while(true) { // code }
Well, let me ask this: What would the benefit of a coroutine that pauses between 1 and 3 seconds be over just saying if Time.time > nextspawn + last spawn, then adjust nextspawn as needed?
Answer by MillZzie · Apr 06, 2014 at 01:07 PM
If You make a boundary and attach this script to like a cube game object without the mesh rendered then you can attach prefabs to the scripts which spawn randomly on the y axis in the boundary hope this helped.
using UnityEngine;
using System.Collections;
public class EnemySpawnerController : MonoBehaviour {
private Collider collider;
public int hazardCount;
//public int hazardCountMax;
//public int hazardCountMin;
public int WaveWait;
//public int WaveWaitMin;
//public int WaveWaitMax;
//float WaitMax =10f;
//float WaitMin = 5f;
public float spawnWait;
public float SpawnValueX;
public GameObject[] EnemyPrefabs;
void Start ()
{
collider = GetComponent<Collider> () as Collider;
StartCoroutine (SpawnWaves ());
}
private Vector3 MakeRandomSpawnPosition()
{
Vector3 local = collider.transform.position;
local.x = SpawnValueX - (collider.transform.localScale.x/2);
local.y = Random.Range(local.y, local.y + collider.transform.localScale.y) - (collider.transform.localScale.y /2);
local.z = 0f;//Random.Range(local.z, local.z + collider.transform.localScale.z) - (collider.transform.localScale.z /2);
return local;
}
IEnumerator SpawnWaves ()
{
float currentWait = 1f;//Random.Range (WaitMin, WaitMax);
//WaveWait = 2;//Random.Range (WaveWaitMin, WaveWaitMax);
//hazardCount = 3;// Random.Range (hazardCountMin, hazardCountMax);
yield return new WaitForSeconds (currentWait);
while (true)
{
for (int i = 0; i < hazardCount; i++)
{
Quaternion spawnRotation = Quaternion.identity;
GameObject gameObjectInstance = MakeRandomGameObject(MakeRandomSpawnPosition());
//Instantiate (enemyPrefab, spawnPosition, spawnRotation);
yield return new WaitForSeconds (spawnWait);
}
yield return new WaitForSeconds (WaveWait);
}
}
private GameObject MakeRandomGameObject(Vector3 position)
{
GameObject enemyPrefab = EnemyPrefabs[Random.Range(0, EnemyPrefabs.Length)];
Vector3 spawnPosition = MakeRandomSpawnPosition();
Quaternion spawnRotation = Quaternion.identity;
GameObject gameObjectInstance = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity) as GameObject;
return gameObjectInstance;
}
void OnTriggerExit (Collider other)
{
if (other.gameObject.tag == "Enemy")
{
Destroy (other.gameObject);
}
else if(other.gameObject.tag == "PickUp")
{
Destroy (other.gameObject);
}
}
}
Answer by RudyTheDev · Mar 28, 2014 at 10:33 AM
Instantiate(EnemyDroneArray[RandomIndex], transform.position, Quaternion.identity);
The syntax is array[index]
, the other two are parameters for the Instantiate
function and shouldn't have anything to do with the array.
Going to try this out now. That change in code gave me this warning:
Assets/$$anonymous$$ain Scene/Scripts/Enemy_Spawn_Script.js(69,32): BCW0028: WARNING: Implicit downcast from 'Object' to 'UnityEngine.Object'.
Be back in a moment with an update!
ArgumentException: The prefab you want to instantiate is null.
I half expected that. The drones are declared on line 20. The drones are included in the inspector. I have a feeling I am trying to go about this the wrong way. It would seem that I somehow need to assign '1' (int) to 'Enemy_Drone_1' (Transform) so it can be instantiated.