I am making a game in Unity2D i which you have to match the correct projectiles with the enemies but I can't randomly spawn them, it just spawns one... (btw this is my first game)
{
timeBTWSpawn = StartTimeBTWSpawn;
private void Update()
{
if(timeBTWSpawn <= 0 )
{
rand = Random.Range(0, enemies.Length);
Instantiate(enemies[0], SpawnPoint.transform.position, Quaternion.identity);```
timeBTWSpawn = StartTimeBTWSpawn;
}
else
{
timeBTWSpawn -= Time.deltaTime;
}
}
}
i expect 3 different enemies to be randomly spawned but it only spawns the first one in the array.
there is one minor mistake. You are not actually using "rand" variable inside the instantiate method. having 0 in the index will always spawn the first element inside enemies array.it should be like this:
Code:
Instantiate(enemies[rand], SpawnPoint.transform.position, Quaternion.identity);
this will fix :)
Related
I'm working on my first Unity project. It's a little game where you have to move your planet to dodge incoming asteroids.
I have set up a simple collision detection system but it's not working at this moment and I'm not entirely sure why.
These are the lines of codes, they're on the movement script for the planet, attached to my gameobject planet:
private void OnTriggeredEnter2D(Collider2D collision)
{
if (collision.tag == "Asteroid")
{
restartPanel.SetActive(true);
}
}
The asteroids are a prefab spawned dynamically in this manner in a script attached to an invisible gameobject:
void Update()
{
float interval = Time.deltaTime;
random = Random.Range(0f, 1f);
Debug.Log(interval);
Debug.Log(random);
if (interval > random) {
GameObject newAsteroid = Instantiate(asteroidPrefab, GetRandomPosition(), Quaternion.identity);
newAsteroid.GetComponent<Gravity>().planet = planet;
}
}
Nothing happens when planet collides with any asteroid, or when asteroids collide with each other, if that matters, and I'm not entirely sure why.
Thank you for your help.
The method name was not correct, I messed up, it should have been OnTriggerEnter2D, not OnTriggeredEnter2D.
Yikes.
So I'm making a game where you evade enemies and trigger certain powerups that has various effects on the enemies. One of them is a bomb that explodes 4 seconds after the player collides with it, destroying all enemies within its radius as it explodes.
I think I've got everything figured out except the actual destroying of the enemy. I feel like the solution is so obvious but I just never learned the method. At this point the bomb object is destroyed upon explosion instead of the enemies, which I expected to happen, because Destroy(other.gameObject) just doesn't work in this context! What do I do??
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Debug.Log("player");
StartCoroutine(BombCountdownRoutine());
}
}
IEnumerator BombCountdownRoutine()
{
bombAudio.PlayOneShot(bombSound, 0.8f);
yield return new WaitForSeconds(4);
Collider[] hitColliders = Physics.OverlapSphere(transform.position, 10);
for (int i = 0; i < hitColliders.Length; i++)
{
if (hitColliders[i].gameObject.tag == "Enemy")
{
Destroy(gameObject);
}
}
}
I'm writting a small 2D game in Unity with C#. I have built two obstaclespawner which spawn vertical lines. After the lines have been spawned, they move down. One of the spawner is located at the upper left edge and the other one at the upper right edge. Currently, new objects are spawned after a certain time. But my goal is, for example, to spawn a new object on the upper left edge when the object which is spawned on the top right has traveled a certain distance.
Could this possibly be done via the coordinates of the objects?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObstacleSpawner : MonoBehaviour
{
public GameObject[] obstacles;
public List<GameObject> obstaclesToSpawn = new List <GameObject>();
int index;
void Awake()
{
InitObstacles();
}
// Start is called before the first frame update
void Start()
{
StartCoroutine (SpawnRandomObstacle ());
}
// Initialize obstacles
void InitObstacles()
{
index=0;
for(int i =0; i<obstacles.Length*3;i++){
GameObject obj = Instantiate(obstacles[index], transform.position, Quaternion.identity);
obstaclesToSpawn.Add(obj);
obstaclesToSpawn [i].SetActive (false);
index++;
if (index == obstacles.Length)
{
index= 0;
}
}
}
IEnumerator SpawnRandomObstacle()
{
//Wait a certain time
yield return new WaitForSeconds(3f);
}
//I want something like this
(if gameObject.x == -0.99){
//activate obstacles
int index = Random.Range(0, obstaclesToSpawn.Count);
while(true){
if (!obstaclesToSpawn[index].activeInHierarchy){
obstaclesToSpawn[index].SetActive(true);
obstaclesToSpawn [index].transform.position = transform.position;
break;
}else{
index = Random.Range (0, obstaclesToSpawn.Count);
}
}
StartCoroutine (SpawnRandomObstacle ());
}
}
As far as I understand, you need to save in each spawner the reference to other spawner.
public class ObstacleSpawner : MonoBehaviour
{
public ObstacleSpawner otherSpawner;
...
Then in spawner check the position of obstacle in the second spawner. Something like this:
...
if (otherSpawner.obstaclesToSpawn[someIndex].transform.position.x <= -0.99)
{
// Spawn new obstacle in this spawner...
...
}
Comparing position of an object to a certain position in the world is something that might work for you right now but may cause problems in the future if you ever try to change anything in the way your scene is set up.
You're looking for distance travelled by an object and you have everything necessary to calculate said distance.
The starting point for all your obstacles spawned by an ObstacleSpawner is the position of the ObstacleSpawner object so you don't need to cache the spawn position which makes things a lot easier.
You need a variable defining the distance after which you want to spawn another obstacle something like public float distBeforeNextObstacle = 1f, then you can compare this distance against the obstacle's distance from its spawn position (use Vector3 or Vector2, both have a Distance method, you should choose whatever fits your game best):
if(Vector3.Distance(obstaclesToSpawn[index].transform.position, transform.position)>=distBeforeNextObstacle)
{
//Spawn next obstacle
}
So basically I have a spawning script (2D game) that spawns in a enemy after spawn delay. I've also adding an array of enemy prefabs so that the SpawnerScript will spawn in a random enemy. However I'm having some problems with spawning in the prefabs in a random position within a transform (a.k.a: a 3D cube). You see My spawner isn't spawning in anything when I play the game, I made sure that I have included the size of how many enemies I want to spawn in. and made sure I have attach my prefabs. I also made sure that my unity project file hasn't got a bug. Maybe my code is wrong, i'm not sure.
My SpawnerScript:
public float RateOfSpawn = 1;
public float spawnTime = 2;
public GameObject[] enemy;
void Start(){
InvokeRepeating ("addEnemy", spawnTime, spawnTime);
}
void Spawn () {
// Random position within this transform- 3Dcube
var x1 = transform.position.x - GetComponent<Renderer> ().bounds.size.x / 2;
var x2 = transform.position.x + GetComponent<Renderer> ().bounds.size.x / 2;
var spawnPoint = new Vector2 (Random.Range (x1, x2), transform.position.y);
int enemyIndex = enemy.Length;
Instantiate (enemy[enemyIndex],spawnPoint,Quaternion.identity);
}
}
Thank you :)
You have to call the proper function to make it work.
void Start()
{
InvokeRepeating ("Spawn", spawnTime, spawnTime);
}
You have to call "Spawn" instead of "addEnemy".
Also change Instanatiate for proper instantiation.
Instantiate (enemy[Random.Range (0, enemyIndex)], spawnPoint, Quaternion.identity);
enemy[Random.Range (0, enemyIndex)] helps you choose random enemy from array of enemies' index 0 to enemyIndex-1.
The cause of exception is putting the length of array as index. Max Index limit is always length-1.
I'm working at an enemy spawn system. This is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EnemyManager : MonoBehaviour
{
public GameObject shark; // prefab von Shark
public GameObject instanceShark; // globale Instanzvariable von Shark
public Transform[] spawnPoints; // An array of the spawn points this enemy can spawn from.
public float spawnTime = 3f; // How long between each spawn.
public int maximumSharks = 2;
private int currentSharks;
public int healthShark; // current Health von Shark
public int startinghealthShark = 200;
public float sinkSpeed = 2.5f;
bool isDead;
void Start ()
{
healthShark = startinghealthShark;
currentSharks = 0;
}
void Update ()
{
if (currentSharks <= maximumSharks) {
InvokeRepeating ("Spawn", spawnTime, spawnTime);
}
Debug.Log (currentSharks);
}
void Spawn ()
{
// Find a random index between zero and one less than the number of spawn points.
int spawnPointIndex = Random.Range (0, spawnPoints.Length);
// Create an instance of the enemy prefab at the randomly selected spawn point's position and rotation.
instanceShark = Instantiate (shark, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation) as GameObject;
currentSharks++;
if (currentSharks >= maximumSharks) {
CancelInvoke("Spawn");
}
}
public void AddDamageToShark (int neuDamageWert) // Addiere zu damage. Public function, können andre scripts auch aufrufen
{
// If the enemy is dead...
if(isDead)
// ... no need to take damage so exit the function.
return;
healthShark -= neuDamageWert;
if (healthShark <= 0) { //tot
Death ();
}
Debug.Log (healthShark);
}
void Death ()
{
// The enemy is dead.
isDead = true;
currentSharks--;
Destroy (instanceShark);
Debug.Log ("dead?");
return;
}
What I want: Spawn enemies as long as maximum amount isn't reached (this part works so far) and destroy the enemy that has been shot and respawn another one (doesn't work).
This codes creates 2 sharks as enemies at the moment. The problem is when I damage one, only the last created instance gets destroyed even though I shot at the first shark. Also the health of the other instance and new spawning instance isn't affected at all.
I'd appreciate any advices, I spent ages with this code and it seems like I need some help regarding the instances - health logic.
Thank you very much
Split your spawn manager behaviour and your enemy behaviour and use interfaces to organize your code in a more SOLID approach. Turn your objects responsible for just one scope (Now your SpawnManager is current responsible for Enemy behaviours/responsabilities)
SpawnManager should be a singleton object with just one responsibility "to manage enemy spawn" with a maximunEnemyCount and a currentEnemyCount. You can spawn always when your currentEnemyCount < maximunEnemyCount.
OnTakeDamage() and OnDeath() should be interfaces of your enemy behaviour (in a separated script from SpawnManager, lets assume EnemyBehaviour script) and your destroy should target just the instance of itself Destroy(this.gameObject)
Remember to notify your SpawnManager when an enemy is dead on your OnDeath method to adjust enemyCurrentCount.
I think this is a more elegant way to do this task and less susceptible to bugs on managing enemy instances.
edited:
linked singleton references that I forgot before
you'll need a unique gameObject for manager that should know how much enemies can live and how many are living, nothing more about the enemies (enemy's health is a responsibility of enemy object in this case).
each enemy need to know when he/she dies and so notify the manager to decrement its counter.