I found a good re-spawner for my game and I respawn 50 spheres. I want them to disappear when I walk into them but they do nothing.
Here is my script:
using UnityEngine;
using System.Collections;
public class BoxDestroy : MonoBehaviour
{
void OntriggerEnter(Collider collider)
{
if (collider.gameObject.tag == "Player")
{
Destroy(gameObject);
}
}
}
Here is my re-spawner:
using UnityEngine;
using System.Collections;
public class spawner : MonoBehaviour
{
public GameObject objectToSpawn;
public int numberOfEnemies;
private float spawnRadius = 5;
private Vector3 spawnPosition;
// Use this for initialization
void Start ()
{
SpawnObject ();
}
void Update ()
{
}
void SpawnObject()
{
for (int i= 0; i < numberOfEnemies; i++)
{
spawnPosition = transform.position + Random.insideUnitSphere * spawnRadius;
Instantiate(objectToSpawn, spawnPosition, Quaternion.identity);
}
}
}
Any ideas?
OntriggerEnter should be OnTriggerEnter! Case sensitive :)
Did you actually tag your player-gameobject with a "player" tag?
Did you mark the colliders as triggers? OnTriggerEnter vs OnCollisionEnter
Do you have a rigidbody component on your player object?
Related
I have a couple of problems with object pooling in Unity with my 2D game, cannon balls don't want to stop when there is a collision with the wall, and 1 of them bursts shoot and the other 9 shoot together connected with each other, my cannon is static object on scene. Can someone help or give me some hint about it.
Here is my code, 3 scripts:
ObjectPooling.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPooling : MonoBehaviour
{
public static ObjectPooling instance;
[SerializeField] public GameObject objectToPool;
private List<GameObject> cannonBalls = new List<GameObject>();
private int numberOfObjects = 20;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
for (int i = 0; i < numberOfObjects; i++)
{
GameObject gameObject = Instantiate(objectToPool);
gameObject.SetActive(false);
cannonBalls.Add(gameObject);
}
}
// Update is called once per frame
void Update()
{
}
public GameObject GetCannonBallObject()
{
for (int i = 0; i < cannonBalls.Count; i++)
{
if (!cannonBalls[i].activeInHierarchy)
{
return cannonBalls[i];
}
}
return null;
}
}
Cannon.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cannon : MonoBehaviour
{
[SerializeField] private Rigidbody2D rb;
[SerializeField] private GameObject cannonBall;
[SerializeField] private Transform cannonBallPosition;
void Start()
{
}
private void Update()
{
Fire();
}
private void Fire()
{
cannonBall = ObjectPooling.instance.GetCannonBallObject();
if(cannonBall != null)
{
cannonBall.transform.position = cannonBallPosition.position;
cannonBall.SetActive(true);
}
}
}
CannonBall.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CannonBall : MonoBehaviour
{
private float speed = 10f;
[SerializeField] private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
rb.velocity = Vector2.left * speed;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("FloorAndWall"))
{
// Destroy(this.gameObject);
gameObject.SetActive(false);
}
}
}
Why is you cannonball static? Have your tried not having it marked as static? Also, this problem has nothing to do with object pooling. Make sure that when your objects are enabled, all the components are active. Finally, when working with rigidbodies, you should handle them inside FixedUpdate(), and not inside Update().
I am new to unity. Recently, I have started making a survival fps game, there, I have 1 enemy, when I kill him, it will spawn more enemies. However, the spawned only move, but not shoot. Although, I have attached a script to it. here are all my code.
prefab_shooting-
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class prefab_shooting : MonoBehaviour
{
public float damage = 1f;
public float range = 100f;
public GameObject player;
public GameObject enemy;
private void Start()
{
player = GameObject.FindWithTag("Player");
enemy = GameObject.FindWithTag("PBR");
}
private void Update()
{
if (Vector3.Distance(transform.position, player.transform.position) < 25.0f)
{
Debug.Log(damage);
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(enemy.transform.position, enemy.transform.forward, out hit, range))
{
if (hit.transform.tag == "Player")
{
swat_death swat = hit.transform.GetComponent<swat_death>();
// Debug.Log(damage);
}
}
}
}
PBR_shooting (the enemy shooting)-
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PBR_shooting : MonoBehaviour
{
public float damage = 1f;
public float range = 100f;
public GameObject player;
public GameObject enemy;
private void Start()
{
player = GameObject.FindWithTag("Player");
enemy = GameObject.FindWithTag("PBR");
}
private void Update()
{
if (Vector3.Distance(transform.position, player.transform.position) < 25.0f)
{
Shoot();
}
}
void Shoot()
{
RaycastHit hit;
if(Physics.Raycast(enemy.transform.position, enemy.transform.forward, out hit, range))
{
if(hit.transform.tag == "Player")
{
swat_death swat = hit.transform.GetComponent<swat_death>();
// Debug.Log(swat.health);
swat.TakeDamage(damage);
}
}
}
Swat_death (player_death) -
using UnityEngine;
using UnityEngine.SceneManagement;
public class swat_death : MonoBehaviour
{
static float health = 250f;
public GameObject player;
public void TakeDamage(float amount)
{
health -= amount;
Debug.Log(health);
if (health <= 0f)
{
Debug.Log("STOP");
SceneManager.LoadScene("death_scene");
}
}
void Die()
{
}
private void OnCollisionEnter(Collision collision)
{
if(collision.transform.tag == "enemy_bullet")
{
//SceneManager.LoadScene("death_scene");
}
}
}
And the PBR_Death (from where the spawning starts) -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PBR_death : MonoBehaviour
{
public GameObject player;
Animator anim;
public int XPos;
public int ZPos;
public GameObject TheEnemy;
public int enemyCount = 0;
public int points = 1;
public GameObject enemyGameObject;
void Start()
{
anim = GetComponent<Animator>();
enemyGameObject = GameObject.FindWithTag("PBR");
}
// Update is called once per frame
void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag == "bullet")
{
anim.SetTrigger("isDying");
enemy_movement enemy = GetComponent<enemy_movement>();
enemy.enabled = false;
PBR_shooting shoot = GetComponent<PBR_shooting>();
shoot.enabled = false;
scoreManager.score += points;
GameObject go = Instantiate(enemyGameObject, new Vector3(Random.Range(34, 0), Random.Range(34, 0), 0), Quaternion.identity) as GameObject;
go.AddComponent<prefab_movement>();
go.AddComponent<prefab_death>();
go.AddComponent<prefab_shooting>();
// StartCoroutine(EnemySpawner());
Destroy(collision.gameObject);
}
}
Pls help me, I am stuck in this for almost 3 days..
You didn't call the function
In your first script (prefab_shooting-) You didn't call the Shoot() function.
I'm using this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionPlayer : MonoBehaviour
{
public bool alreadyDied = false;
public GameObject player;
public float timeDeath;
public ParticleSystem particles;
public GameObject explosionGO;
private SpriteRenderer sr;
private BoxCollider2D bc;
private PlayerController walkScript;
void Start()
{
sr = GetComponent<SpriteRenderer>();
bc = GetComponent<BoxCollider2D>();
walkScript = GetComponent<PlayerController>();
}
void OnCollisionEnter2D (Collision2D collide)
{
if (collide.gameObject.CompareTag("Dead"))
{
Instantiate(particles, player.transform.position, Quaternion.identity);
Instantiate(explosionGO, player.transform.position, Quaternion.identity);
CinemachineShake.Instance.ShakeCamera(30f, .1f);
alreadyDied = true;
}
}
void Update()
{
if(alreadyDied == true)
{
timeDeath -= Time.deltaTime;
sr.enabled = false;
bc.enabled = false;
walkScript.enabled = false;
}
if(timeDeath <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
This is the bullet's code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeftBulletScript : MonoBehaviour
{
// Start is called before the first frame update
public float speed;
public float destructionLeftTime;
public ParticleSystem particles;
private GameObject thisGameObject;
void Start()
{
thisGameObject = this.gameObject;
Destroy(gameObject, destructionLeftTime);
}
void Update()
{
transform.Translate(Vector2.left * speed * Time.deltaTime);
if(destructionLeftTime > 0.05f)
{
destructionLeftTime -= Time.deltaTime;
}
else
{
Instantiate(particles, thisGameObject.transform.position, Quaternion.identity);
}
}
}
This code should spawn some particles and a sound effect when the player gets hit by something with tag "Dead". But that does not happen. I have a box collider 2D on both the bullet (that should kill me) and the player. My Rigidbody2D is dynamic on the player with z freezed. The bullet does not have a rigidbody. I made sure that the bullet actually has the tag "Dead", spelled the exact same way as the way I wrote on the script. The weirdest thing is that I used this code on another game and nothing changed (just the name of a script). Both the player and the bullet are on the same layer. Anyone could tell me what could have happened?
I'm trying to have health points to the instantiated enemies of my game.
At first the enemies were just destroyed as soon as a single shot hit them.
I thought adding a new class just holding the HP of the instantiated prefab would work, but I don't know how to write that correctly. Either it's "static" and then I know how to call it from the bullet controller class, but it's not instantiated and the same int value is kept for all instantiated enemies, or it is not "static" and then I don't know how to call it from the other classes.
Here is the code currently, for the bullet controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletController : MonoBehaviour
{
private Transform bullet;
public float speed;
// Start is called before the first frame update
void Start()
{
bullet = GetComponent<Transform>();
}
void FixedUpdate()
{
bullet.position += transform.up * speed;
if (bullet.position.y >= 10)
Destroy(gameObject);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Enemy")
{
Enemy4HP.health--;
Destroy(gameObject);
if (Enemy4HP.health < 1)
{
Destroy(other.gameObject);
PlayerScore.playerScore++;
}
}
if (other.tag == "Enemy2")
{
Enemy10HP.health--;
Destroy(gameObject);
if (Enemy10HP.health <1)
{
Destroy(other.gameObject);
PlayerScore.playerScore++;
}
}
}
}
and for the two health classes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy4HP : MonoBehaviour
{
public int health = 4;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy10HP : MonoBehaviour
{
public int health = 10;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
And this is how the enemies get instantiated:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyController : MonoBehaviour
{
private Transform enemyHolder;
public float speed;
public GameObject shot;
public GameObject enemy;
public GameObject enemy2;
public Text winText;
int secCount;
float timer = 0;
public float fireRate = 0.997f;
public int enemyCount;
// Start is called before the first frame update
void Start()
{
enemyCount = 0;
secCount = 0;
enemyHolder = GetComponent<Transform>();
winText.enabled = false;
InvokeRepeating("MoveEnemy", 0f, 0.016f);
}
private List<GameObject> allSpawns = new List<GameObject>();
void MoveEnemy()
{
float xPosition = Random.Range(-11f, 11f);
int enemyType = Random.Range(0, 8);
secCount = Random.Range(2, 4);
timer += Time.deltaTime;
if (timer >= secCount && enemyCount < 25)
{
if (enemyType > 0)
{
GameObject spawned = Instantiate(enemy, new Vector3(xPosition, 6, 0), Quaternion.identity);
allSpawns.Add(spawned);
}
else
{
GameObject spawned = Instantiate(enemy2, new Vector3(xPosition, 6, 0), Quaternion.identity);
allSpawns.Add(spawned);
}
enemyCount++;
timer = timer - secCount;
}
foreach (GameObject thisEnemy in allSpawns)
{
if (thisEnemy !=null)
{
thisEnemy.transform.position += new Vector3(0, -1 * speed * Time.deltaTime, 0);
}
}
if (PlayerScore.playerScore == 25)
{
timer = 0;
CancelInvoke();
InvokeRepeating("MoveEnemy2", 0f, 0.016f);
}
}
...
That returns "An object reference is required for the non_static field...". What can I do?
Thanks.
Simplest quickest. Instead of 2 classes with 2 different number make 1 called EnemyHP. Add the component to the enemy prefabs and on the prefab in the inspector set the component's health to 4 for enemy 1 and 10 for enemy 2. Then :
void OnTriggerEnter2D(Collider2D other)
{
//you can probably just make both enemy the same tag.
if (other.tag == "Enemy" || other.tag == "Enemy2")
{
//get the Hp component of the specific enemy.
EnemyHP hpComponent = other.gameObject.GetComponent<EnemyHP>();
hpComponent.health--;
Destroy(gameObject);
if (hpComponent.health < 1)
{
Destroy(other.gameObject);
PlayerScore.playerScore++;
}
}
}
I writing simple game on Unity (C#)
I have player and want to make the destroyer, that will destroy player.
I create prefab of destroyer. And next, I create Quad.
I have spawn script:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 2f;
// Use this for initialization
void Start () {
Spawn();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
Also I write DestroyerScript:
using UnityEngine;
using System.Collections;
public class DestroyerScript : MonoBehaviour {
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Application.LoadLevel(1);
return;
}
if (other.gameObject.transform.parent)
{
Destroy(other.gameObject.transform.parent.gameObject);
}
else
{
Destroy(other.gameObject);
}
}
}
My destroyer spawning, but when player get it, I don't have Game Over screen.
Add rigid body to both player and "player destroyer" and then set onTriggerEnter on your player destroyer like so:
void OnTriggerEnter(Collider other) {
Destroy(other.gameObject);
}
For some fine tuning, you can do some checks if the other object is in fact the Destroyer (you can compare the tag or something, I won't go into too much detail now).
EDIT: Uncheck "isTrigger" on your BoxColliders and try this:
void OnCollisionEnter (Collision col)
{
Destroy(col.gameObject);
}