- Home /
How to make random alien fire and not all of them at once..
Hi am making Space invaders following Derick Banas tutorial, however, how do i make a random alien shoot instead of all of them? this is what i have but itdoesnt work, it take obj[i] and it fires the count of i as aliens.
private void FixedUpdate()
{
if (Time.time > baseFireWaitTime)
{
objs = GameObject.FindGameObjectsWithTag("Alien");
int i = Random.Range(1,objs.Length);
//baseFireWaitTime = baseFireWaitTime + Random.Range(minFireRateTime, maxFireRateTime);
Instantiate(alienBullet, objs[i].transform.position,Quaternion.identity);
print(objs[i]);
baseFireWaitTime += 5;
}
}
Are there multiple instances of this script?? Also, I would think you would want Random.Range(0,objs.Length); because your array of objs starts at 0
I forgot to mention the script is shared with all aliens. After thinking about it, I think if I move the instantiate of the bullet to an individual script for each alien with a random wait time, this might work. But there has to be an easier way no? Thanks for your help
Hi I tried finding a solution and decide to instantiate my prefabs as an array and call a specific array to test it out to see if only that one alien fires but they all still fire? Do yall know what I'm doing wrong? @highpockets @Saiansh2525
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class TestAlien : $$anonymous$$onoBehaviour { public GameObject alienBullet; public GameObject[] Invader1; private Rigidbody2D[] rigibod; public float $$anonymous$$FireRateTime; public float maxFireRateTime; public float baseFireWaitTime;
private void Start() { for (int i = 0; i < Invader1.Length; i++) { rigibod = new Rigidbody2D[Invader1.Length]; rigibod[i] = Invader1[i].GetComponent(); rigibod[i].velocity = new Vector2(1, 0) * 10; }
}
public void CreateInvaders()
{
for (int i = 0; i < Invader1.Length; i++)
{
Instantiate(Invader1[i], new Vector2(-i * 5 - (3), -5), Quaternion.identity);
}
}
// Update is called once per frame
public void FixedUpdate()
{
if (Time.time > baseFireWaitTime)
{
Instantiate(alienBullet,Invader1[1].transform.position, Quaternion.identity);
baseFireWaitTime += 5;
}
}
}
First thing I see in your code is that you are instantiating the alien bullet at the same game objects transform always because Invader1[1] will just always give you the second item in the Invader1[] array
Answer by Saiansh2525 · May 13, 2020 at 10:52 PM
First, assign an integer to every alien as an ID. You can have an empty GameObject that chooses a random number for the alien every x frames that you want. After that, each alien will access that variable and check if it is their ID and if it is then the alien will fire.
Wow, sounds good too.. but I'm new to unity so I have homework to do..lol. I was able to accomplish this in visual studio making galaga which is harder than unity but not able to figure out here
If you want to learn Unity I suggest that you look at learn.unity.com. They have many courses going and a few months of Learn Premium because of COVID-19.
Hi I tried finding a solution and decide to instantiate my prefabs as an array and call a specific array to test it out to see if only that one alien fires but they all still fire? Do yall know what I'm doing wrong?
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class TestAlien : $$anonymous$$onoBehaviour { public GameObject alienBullet; public GameObject[] Invader1; private Rigidbody2D[] rigibod; public float $$anonymous$$FireRateTime; public float maxFireRateTime; public float baseFireWaitTime;
private void Start() { for (int i = 0; i < Invader1.Length; i++) { rigibod = new Rigidbody2D[Invader1.Length]; rigibod[i] = Invader1[i].GetComponent(); rigibod[i].velocity = new Vector2(1, 0) * 10; }
}
public void CreateInvaders()
{
for (int i = 0; i < Invader1.Length; i++)
{
Instantiate(Invader1[i], new Vector2(-i * 5 - (3), -5), Quaternion.identity);
}
}
// Update is called once per frame
public void FixedUpdate()
{
if (Time.time > baseFireWaitTime)
{
Instantiate(alienBullet,Invader1[1].transform.position, Quaternion.identity);
baseFireWaitTime += 5;
}
}
}
Answer by highpockets · May 12, 2020 at 09:46 PM
Ya, well that’s the issue. If this script is on all aliens, each bullet will spawn at the same time since this just waits 5 seconds between shots From the beginning of the game I assume. And some of the bullets will be surely spawning on top of each other with the way things are now. If you want to have the bullets instantiate on each alien at random intervals then that could work, but instead of using Random.Range on to decide your instantiation point, you would use it define the moment to instantiate and instantiate each bullet at Gun position of the alien ship it’s attached to.
Another option, like you mentioned in your previous comment is to manage all bullets from one script. A bullet factory/object pool script would be my choice and reuse the bullets instead of destroying and instantiating them. Give each alien ship a random timer, and when the timer is up, assign the first available bullet to that ships gun position.
Im new to unity, do you have a sample? Lol.. but it sounds like what I need!! Thanks, I will get to experiementing!
The way you have it now could be adjusted slightly to meet your needs, I’m not going into how to create an object pool/factory for reusing the objects ins$$anonymous$$d of destroying and instantiating, but I do suggest that you read into it.
Below is what I would do if instantiation was the way you were to end up going:
float $$anonymous$$ShotTimer = 3.0f
float maxShotTimer = 5.0f
private Start(){
StartCoroutine(AlienFire());
}
private IEnumerator AlienFire()
{
while(true){
yield return new WaitForSeconds(Random.Range($$anonymous$$ShotTimer, maxShotTimer));
Instantiate(alienBullet, transform.position,Quaternion.identity);
}
}
That code above is assu$$anonymous$$g that you have the script on each of the alien ships. The bullets will just be instantiated on their respective transforms. Ins$$anonymous$$d of running in fixed update, I placed it in a coroutine. Then the logic is inside a while loop for the existence of the game object or class. The yield statement is something that all coroutines need to have, that yield is set to wait for the amount of seconds passed in which in this case is a random range between 3 and 5 seconds. When the yield statement completes 3-5 seconds afterwards, the bullet will be instantiated and then the loop will start over and wait for an additional 3-5 seconds before instantiating again. This is likely the behaviour you are looking for, but you may have to adjust the $$anonymous$$ShotTimer/maxShotTimer. Cheers
Beautiful and is what im going with so far since im still learning.. I have the $$anonymous$$ and max set different for each aliean and works so far! Thanks !