I have a particle system for when the enemy is destroyed. I have multiple enemies coming from the same path (using the same prefab) and the particle system is only working on the first enemy. Can someone tell me why it is not working on the others as well? Thank you.
EnemyShooting scrip (this is where the piece of code is for the explosion):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyShooting : MonoBehaviour {
[SerializeField] float EnemyLaserSpeed = 10f;
[SerializeField] float EnemyLaserFireTime;
[SerializeField] GameObject LaserBulletEnemyPreFab;
[SerializeField] int MaxNumberOfHits = 1;
public Transform explosion;
int CurrentNumberOfHits = 0;
Coroutine FireCoroutine;
void OnTriggerEnter2D(Collider2D collider)
{
if(collider.gameObject.tag == "PlayerLaser")
{
if (CurrentNumberOfHits < MaxNumberOfHits)
{
CurrentNumberOfHits++;
Destroy(collider.gameObject);
Score.ScoreValue += 2;//The user will be rewarded 1 point
}
if (explosion)//EXPLOSION CODE
{
GameObject exploder = ((Transform)Instantiate(explosion, this.transform.position, this.transform.rotation)).gameObject;
Destroy(exploder, 2.0f);
}
}
}
void DestroyEnemy()
{
if(CurrentNumberOfHits >= MaxNumberOfHits)
{
Destroy(gameObject);
EnemySpawner.Instance.OnEnemyDeath(); // Tell the EnemySpawner that someone died
}
}
private void Fire()
{
FireCoroutine = StartCoroutine(ShootContinuously());
}
void BecomeVisible()
{
Fire();
}
IEnumerator ShootContinuously()
{
while (true)
{
GameObject LaserBulletEnemy = Instantiate(LaserBulletEnemyPreFab, this.transform.position, Quaternion.identity) as GameObject;
LaserBulletEnemy.GetComponent<Rigidbody2D>().velocity = new Vector2(0, EnemyLaserSpeed);
EnemyLaserFireTime = Random.Range(0.5f, 0.9f);
yield return new WaitForSeconds(EnemyLaserFireTime);
}
}
// Use this for initialization
void Start () {
BecomeVisible();
}
// Update is called once per frame
void Update () {
DestroyEnemy();
}
}
EnemySpawner : (I thought this script might help in a way so I attached it)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemySpawner : MonoBehaviour
{
[SerializeField] GameObject EnemyPreFab;
[SerializeField] int MaxEnemies = 30;
[SerializeField] float EnemySpawnTime = 1.00001f;
[SerializeField] GameObject FirstWaypoint;
int CurrentNumOfEnemies = 0;
public int EnemiesToNextLevel = 7;
public int KilledEnemies = 0;
public LevelManager myLevelManager;
public static EnemySpawner Instance = null;
int timesEnemyHit;
IEnumerator SpawningEnemies()
{
while (CurrentNumOfEnemies <= MaxEnemies)
{
GameObject Enemy = Instantiate(EnemyPreFab, this.transform.position, Quaternion.identity);
CurrentNumOfEnemies++;
yield return new WaitForSeconds(EnemySpawnTime);
}
}
void Start()
{
if (Instance == null)
Instance = this;
StartCoroutine(SpawningEnemies());
timesEnemyHit = 0;
if (this.gameObject.tag == "EnemyHit")
{
CurrentNumOfEnemies++;
}
}
public void OnEnemyDeath()
{
CurrentNumOfEnemies--;
/*
if (CurrentNumOfEnemies < 5)
{
// You killed everyone, change scene:
LaserLevelManager.LoadLevel("NextLevelMenu");
}
*/
KilledEnemies++;
if (KilledEnemies >= EnemiesToNextLevel)
{
LaserLevelManager.LoadLevel("NextLevelMenu");
}
}
}
Related
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've been trying to make my enemy fall when it's health reaches zero.
So I made a damage variable. The damage will subtract to the health and when it reaches zero or lower, he's supposed to turn into a ragdoll. But its seems as he's not dying in the first place..
In the gun script:
using UnityEngine;
public class gun : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera Cam;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Fire();
}
void Fire()
{
RaycastHit hit;
if(Physics.Raycast(Cam.transform.position, Cam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Enemy enemy = hit.transform.GetComponent<Enemy>();
if (enemy != null)
{
enemy.damage(damage);
}
}
}
}
}
Now in the enemy script:
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using UnityEngine;
public class Enemy : MonoBehaviour
{
Animator myAnim;
List<Rigidbody> ragdollRigids;
public float health = 100f;
public void damage (float amount)
{
health -= amount;
if(health <= 0)
{
Death();
}
}
void Death()
{
activateRagdoll();
}
//Update
void Start()
{
myAnim = GetComponent<Animator>();
ragdollRigids = new List<Rigidbody>(transform.GetComponentsInChildren<Rigidbody>());
ragdollRigids.Remove(GetComponent<Rigidbody>());
DeactivateRagdoll();
}
void Update()
{
}
//Ragdoll dependencies.
public void activateRagdoll()
{
myAnim.enabled = false;
for (int i = 0; i < ragdollRigids.Count; i++)
{
ragdollRigids[i].useGravity = true;
ragdollRigids[i].isKinematic = false;
}
}
public void DeactivateRagdoll()
{
myAnim.enabled = true;
for (int i = 0; i < ragdollRigids.Count; i++)
{
ragdollRigids[i].useGravity = false;
ragdollRigids[i].isKinematic = true;
}
}
}
Thank you in advance. :)
Solution
Your variables (damage and amount) are named differently but are used for the same purpose. I have edited your code. There should be no errors. If there are, contact me my commenting on my answer.
Code
Gun:
using UnityEngine;
public class gun : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera Cam;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Fire();
}
void Fire()
{
RaycastHit hit;
if(Physics.Raycast(Cam.transform.position, Cam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Enemy enemy = hit.transform.GetComponent<Enemy>();
if (enemy != null)
{
enemy.damage(damage);
}
}
}
}
}
Enemy:
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using UnityEngine;
public class Enemy : MonoBehaviour
{
Animator myAnim;
List<Rigidbody> ragdollRigids;
public float health = 100f;
public void damage (float damage)
{
health -= damage;
if(health <= 0)
{
Death();
}
}
void Death()
{
activateRagdoll();
}
//Update
void Start()
{
myAnim = GetComponent<Animator>();
ragdollRigids = new List<Rigidbody>(transform.GetComponentsInChildren<Rigidbody>());
ragdollRigids.Remove(GetComponent<Rigidbody>());
DeactivateRagdoll();
}
void Update()
{
}
//Ragdoll dependencies.
public void activateRagdoll()
{
myAnim.enabled = false;
for (int i = 0; i < ragdollRigids.Count; i++)
{
ragdollRigids[i].useGravity = true;
ragdollRigids[i].isKinematic = false;
}
}
public void DeactivateRagdoll()
{
myAnim.enabled = true;
for (int i = 0; i < ragdollRigids.Count; i++)
{
ragdollRigids[i].useGravity = false;
ragdollRigids[i].isKinematic = true;
}
}
}
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 am making a game like 2 cars. And I have written code to create a instantiater. It is a car game and there are 4 lanes. Let me show you a picture of my game and yeah this is solely for practise.
Player should avoid square objects and eat circle objects but sometimes 2 square objects get spawned in a same lane making impossible for player to win. I have written this script to control that but I failed. Please help me. At least have a check to my DetectSameLaneFunction(). And tell me what I am doing wrong.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour {
public GameObject[] objects;
public float delaytime = 2f; // this is separate for each prefab with which script is attaches
public float spawnrate = 1f; // this is separate for each prefab with which script is attaches
public static int lastgameobjectindex;
public static GameObject lastgameobject;
public static GameObject SecondLastGameObject;
private float loadingtime;
private GameObject go; // just a temporary variable
public static List<GameObject> spawnobjects = new List<GameObject>();
// Use this for initialization
void Start () {
loadingtime = delaytime;
}
// Update is called once per frame
void Update () {
if (Time.time > loadingtime)
{
float randomness = spawnrate * Time.deltaTime;
if ( randomness < Random.value)
{
Spawners();
}
NextLoadTime();
}
}
private void Spawners()
{
int spawnnumber = Random.Range(0, 2);
GameObject go = Instantiate(objects[spawnnumber]) as GameObject;
go.transform.position = this.transform.position;
spawnobjects.Add(go);
Debug.Log(spawnobjects[spawnobjects.Count-1]);
DetectSameLaneObjects();
/* if (spawnobjects.Count > 4)
{
spawnobjects.RemoveAt(0);
}*/
}
private void DetectSameLaneObjects()
{
if (spawnobjects.Count > 3)
{
lastgameobject = spawnobjects[spawnobjects.Count - 1];
SecondLastGameObject = spawnobjects[spawnobjects.Count - 2];
lastgameobjectindex = spawnobjects.Count - 1;
if (SecondLastGameObject.transform.position.x != lastgameobject.transform.position.x
)
{
if (Mathf.Abs(lastgameobject.transform.position.x- SecondLastGameObject.transform.position.x) < 2.3f)
{
Debug.Log("Destroy function getting called");
Destroy(spawnobjects[lastgameobjectindex]);
spawnobjects.RemoveAt(lastgameobjectindex);
}
}
}
}
void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, 0.6f);
}
void NextLoadTime()
{
loadingtime = Time.time + delaytime;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAttack : MonoBehaviour {
public float timeBetweenAttacks = 0.5f;
public int attackDamage = 10;
Animator anim;
GameObject Player;
PlayerHealth playerHealth;
//EnemyHeath enemyhealth;
bool playerInRange;
float timer;
private Animator animator = null;
void Awake() {
Player = GameObject.FindGameObjectWithTag ("Player");
playerHealth = Player.GetComponent<PlayerHealth> ();
//enemyHealth = GetComponent<EnemyHealth> ();
anim = GetComponent <Animator> ();
}
void Attack(Collider other) {
if (other.gameObject == Player) {
playerInRange = true;
animator.SetBool ("idle0ToAttack1", true);
}
}
void Attack1(Collider other) {
if (other.gameObject == Player) {
playerInRange = false;
}
}
void Update() {
timer +=Time.deltaTime;
if (timer >= timeBetweenAttacks /*&& enemyHealth.currentHealth > 0*/) {
AttackPlayer ();
}
if (playerHealth.currentHealth <= 0) {
Destroy (this.Player);
}
}
void AttackPlayer() {
timer = 0f;
if (PlayerHealth.currentHealth > 0) {
playerHealth.TakeDamage (attackDamage);
}
}
}
The error is giving on last method void AttackPlayer() if(PlayerHealth.currentHealth > 0).
I am making a first Person Shooter Game in Unity and if possible please tell give me some more suggestions for player dead animator code that I've written above.
void AttackPlayer()
{
timer = 0f;
if(playerHealth.currentHealth > 0)
{
playerHealth.TakeDamage(attackDamage);
}
}
I've corrected the code. It was a simple mistake of using PlayerHealth instead of what you meant which was playerHealth. Using the uppercase was referring to the class itself. The lowercase would refer to your current object defined earlier in this class.