- Home /
Using event system to respawn dead enemies will spawn live ones again too
using event system to respawn dead enemies will spawn live ones again too
I'm stuck on my respawn system. I've looked at countless answered questions on here and viewed so many youtube tutorials but I think I'm not grasping some fundamental c# instancing. I'm also new to the event system so that doesn't help, but the event system seemed to be the closest method to what I wanted.
When I run the OnEnemyKilled?.Invoke(); all four of my spawn points will spawn the enemy. I only want the one who died to respawn! My belief is that it's because public static event EnemyKilled OnEnemyKilled; is static and it shouldn't be static, but I can't figure out how to get it to work as a non-static.
I have two main scripts here that are part of the system. BeingAI.cs and Spawn.cs. The Spawn.cs file is attached to the empty gameobject that is the "spawn location". The BeingAI.cs is attached to the actual enemy and it's where the death occurs.
//BeingAI.cs
using Pathfinding;
using UnityEngine;
using Xanthe.AI;
using Xanthe.Movement;
//required components
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(CharacterController))]
public class BeingAI : BeingObject
{
//attach these to this script
public CharacterController controller;
Animator animator;
IAstarAI astar;
//scriptable Objects
public BehaviourSO behaviourSO;
//spawn vars
public delegate void EnemyKilled();
public static event EnemyKilled OnEnemyKilled;
//stats
[SerializeField] float attackSpeed;
[SerializeField] float resumeRoam;
void Start()
{
//get components that only need to be grabbed once
animator = GetComponent<Animator>();
//wander
behaviourSO.startingPosition = transform.position;
behaviourSO.roamingPosition = AI.GetRoamingPosition(behaviourSO.startingPosition, behaviourSO.minimumWander, behaviourSO.maximumWander);//delete
astar = GetComponent<IAstarAI>();
//gravity
groundCheck = GameObject.Find("groundCheck").transform;
//death stuff
dead = false;
despawnTimer = 0f;
constitution = raceSO.constitution + classSO.constitution; //get my own health
attackSpeed = 0f;
resumeRoam = behaviourSO.resumeRoam;
}
void Update()
{
despawnTimer = AI.Timer(despawnTimer, dead); //if im dead start a timer
dead = AI.Death(constitution, despawnTimer, gameObject);//i'm dead animate death and despawn
//attack speed counter
if (attackSpeed > 0f)
attackSpeed -= Time.deltaTime;
if (attackSpeed <= 0f)
attackSpeed = 0f;
HateList();
MoveLogic();
//gravity stuff
if (groundCheck != null)
{
gravity = Movement.Gravity(gravity, groundCheck, groundMask);
controller.Move(gravity * Time.deltaTime);
}
//if this being dies
if (dead)
{
OnEnemyKilled?.Invoke();
Movement.MoveSpeed(animator, "stop");
animator.SetBool("Dead", true); //death animation
astar.maxSpeed = 0f; //stop
}
}
void MoveLogic()
{
if (hateList.Count > 0 && target.GetComponent<BeingObject>().constitution > 0) //if sometihing is on the hate list and it has health
{
if (target != null)
{
float distanceToTarget = Vector3.Distance(target.position, transform.position); //distance to target
if (distanceToTarget <= raceSO.aggroRadius && distanceToTarget >= raceSO.attackDistance && !dead) //run toward targetdistanceToTarget > beingSO.tooClose &&
{
astar.destination = target.position;
astar.SearchPath();
Movement.MoveSpeed(animator, "run");
astar.maxSpeed = 4f;
}
if (distanceToTarget <= raceSO.aggroRadius && distanceToTarget <= raceSO.attackDistance && !dead) //stop and attack //distanceToTarget > beingSO.tooClose &&
{
AI.FaceTarget(target.position, transform);
astar.maxSpeed = 0f;
astar.destination = transform.position;
Attack();
}
}
}
else //roam if there's nothing else to do
{
if (!astar.pathPending && (astar.reachedEndOfPath || !astar.hasPath) && !dead) //at end of roaming path
{
if (resumeRoam <= 0)
{
astar.destination = AI.PickRandomPoint(behaviourSO.maximumWander, transform);
astar.SearchPath();
resumeRoam = behaviourSO.resumeRoam;
Movement.MoveSpeed(animator, "walk");
astar.maxSpeed = 1f;
}
else
{
resumeRoam -= Time.deltaTime;
Movement.MoveSpeed(animator, "stop");
astar.maxSpeed = 0f;
}
}
}
}
public void Attack()
{
//stop the being
Movement.MoveSpeed(animator, "stop");
attackSpeed -= Time.deltaTime;
if (attackSpeed <= 0f && target != null && target.GetComponent<BeingObject>().constitution > 0)
{
//do damage
target.GetComponent<BeingObject>().TakeDamage(Random.Range(0, strength)); //activate the takedamage function on my target's beingAI script
//do animation
animator.SetTrigger("Attack");
attackSpeed = raceSO.attackSpeed; //set my attack speed to my being default
//add me to target hatelist
if (!target.GetComponent<BeingObject>().hateList.Contains(transform)) //if the list doesn't already have the mob (ME), add it
target.GetComponent<BeingObject>().hateList.Add(transform);
}
}
}
//Spawn.cs
using UnityEngine;
public class Spawn : MonoBehaviour
{
public GameObject spawn;
void Start()
{
SpawnNPC();
}
void SpawnNPC()
{
Instantiate(spawn, transform.position, transform.rotation);
}
void OnEnable()
{
BeingAI.OnEnemyKilled += SpawnNPC;
}
}
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Multiple Cars not working 1 Answer
Instantiating unique Prefabs to unique child objects in C# 3 Answers
Instantiated object not keeping transform of the instantiator after instantiator is destroyed 2 Answers
Spawn enemies so they aren't spawned on top of each other (C#) 1 Answer