- Home /
Enemy Health Script Working On One Enemy Not Multiples
I am trying to get this Enemy Health Script working for multiple enemies but it isn't working with multiple enemies in the scene. Here are my scripts. These scripts are similar to Survival Shooter but I moved some stuff around to work for what I need it to.
Enemy Health Script:
public int startingHealth = 100;
public int currentHealth;
public float sinkSpeed = 2.5f;
public Slider prestigeSlider; //Reference to the Players Prestige Slider
CapsuleCollider capsuleCollider;
bool isDead;
bool isSinking;
void Awake() {
capsuleCollider = GetComponent<CapsuleCollider>();
currentHealth = startingHealth;
}
// Update is called once per frame
void Update()
{
if (isSinking) {
transform.Translate(-Vector3.up * sinkSpeed * Time.deltaTime);
}
}
public void TakeDamage(int amount) {
if (isDead) return;
currentHealth -= amount;
if (currentHealth <= 0) {
Death();
StartSinking();
}
}
void Death() {
isDead = true;
capsuleCollider.isTrigger = true;
}
public void StartSinking() {
GetComponent<UnityEngine.AI.NavMeshAgent>().enabled = false;
GetComponent<Rigidbody>().isKinematic = true;
isSinking = true;
prestigeSlider.value = 100;
Destroy(gameObject, 2f);
}
Player Attack Script:
public float timeBetweenAttacks = 0.5f;
public int attackDamage = 10;
GameObject enemy;
EnemyHealth enemyHealth;
PlayerHealth playerHealth;
bool enemyInRange;
bool isDead;
float timer;
void Awake() {
enemy = GameObject.FindGameObjectWithTag("Enemy");
enemyHealth = enemy.GetComponent<EnemyHealth>();
playerHealth = GetComponent<PlayerHealth>();
}
void OnTriggerEnter(Collider other) {
if (other.gameObject == enemy) {
enemyInRange = true;
}
}
void OnTriggerExit(Collider other) {
if (other.gameObject == enemy) {
enemyInRange = false;
}
}
void Update() {
timer += Time.deltaTime;
if (timer >= timeBetweenAttacks && enemyInRange && playerHealth.currentHealth > 0) {
Attack();
}
if (enemyHealth.currentHealth <= 0) {
Death();
}
}
void Death()
{
isDead = true;
Debug.Log("Enemy Is Dead");
}
void Attack() {
timer = 0f;
if (enemyHealth.currentHealth > 0)
{
enemyHealth.TakeDamage(attackDamage);
}
}
I have tried using FindGameObjectsWithTag and I guess I was using it incorrectly because it couldn't convert GameObject using that line of code. Currently using unity 2018.4.18f1. I am not the greatest at coding so please try and be specific and basic as possible.
Answer by bdubbert · Mar 05, 2020 at 11:41 PM
Yea, the issue is that you are only tracking one enemy object using FindGameObjectWithTag. You could restructure your code to use FindGameObjectsWithTag, but there is a much more efficient way to do this just by checking the tag of the colliding object directly.
Also I added a list that keeps track of all enemies in range and attacks the first one encountered, as this is for sure the next problem that you would have encountered.
I have not tested this code, and it certainly could be improved but I did not want to change to much. If you have any questions about what I'm doing or it doesn't work exactly like you intended that ask me and I can explain in more depth what I am doing
public float timeBetweenAttacks = 0.5f;
public int attackDamage = 10;
GameObject currentTargetEnemy;
PlayerHealth playerHealth;
bool isDead;
float timer;
private List<GameObject> enemiesInRange;
void Awake () {
playerHealth = GetComponent<PlayerHealth> ();
enemiesInRange = new List<GameObject> ();
}
void OnTriggerEnter (Collider other) {
//Get if its an enemy, add to our list
if (other.gameObject.tag == "Enemy") {
enemiesInRange.Add (other.gameObject);
}
}
void OnTriggerExit (Collider other) {
//Enemy is no longer in range
if (other.gameObject.tag == "Enemy") {
enemiesInRange.Remove (other.GameObject);
}
}
void Update () {
timer += Time.deltaTime;
if (timer >= timeBetweenAttacks && (enemiesInRange.Count > 0) && playerHealth.currentHealth > 0) {
currentTargetEnemy = enemiesInRange[0]; //First enemy in our list
Attack ();
if (currentTargetEnemy.GetComponent<EnemyHealth>().currentHealth <= 0) {
Death ();
}
} else {
currentTargetEnemy = null;
}
}
void Death () {
Debug.Log ("Enemy Is Dead");
enemiesInRange.Remove(currentTargetEnemy);
}
void Attack () {
timer = 0f;
if (currentTargetEnemy.GetComponent<EnemyHealth>().currentHealth > 0) {
currentTargetEnemy.GetComponent<EnemyHealth>().TakeDamage (attackDamage);
}
}
I will test this tomorrow to see if it works out. I am sure it will but if anything comes up I'll reply again. Thanks for your time it's greatly appreciated.
Ok first and fore most. IT EFFIN WOR$$anonymous$$S!!!!!!
Secondly... These are the Red Flags I am getting when I am playing the scene.
1st.) NullReferenceException: Object reference not set to an instance of an object PlayerAttack.Update() (at Assets/Scripts/PlayerAttack.cs:45)
I think i know what is going on but I don't know how to fix it. If you know how to explain it and tell me how we can fix it together that would be A$$anonymous$$AZING!
2nd.) $$anonymous$$issingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object.
Im pretty sure not destorying the game object Enemy would look weird in a game especially a mobile game if there are a buncha dead bodies lieng about draining the performance lol. Unless I am not understanding this error and if so then please lemme know how to fix this as well.
You have been such a great help I am glad you responded to my post. Lets work together and wrap this up so I can try and make a tutorial next lol.
Hi its me I just switched accounts -
So I think both of these errors are likely the same underlying issue, and I was expecting something like this to pop up, however to exactly solve the issue I'll need you to give me the line of code that each error is pointing to (for the first error it says line 45 but that does not line up to the same line 45 as the script I pasted and for the second error there is no line number). But in either case I believe what is happening is just the enemy object that we are trying to look at was either destroyed earlier in the same frame or that we are trying to mess with a pointer to an enemy object that doesn't exist. Both of these can likely be fixed just by checking if the enemy object exists before we try to mess with it. Just send me the exact line that is throwing the error for each case because I'm having trouble locating the issue just by looking at it
Hmm actually I see a potential issue, it looks like when the enemy dies you turn their collider into a trigger, which I believe will cause your OnTriggerEntered function to be called again for the same enemy. Its probably safe to add a check to the OnTriggerEntered to make sure the enemy we are triggering with is not dead -
void OnTriggerEnter (Collider other) {
//Get if its an enemy, add to our list
if (other.gameObject.tag == "Enemy") {
if(other.gameObject.GetComponent<EnemyHealth>().currentHealth > 0) {
enemiesInRange.Add (other.GameObject);
}
}
}
Sorry I wasnt thinking when it came to the lines of code not matching up. Here are the code lines in my editor.
Line 45:
$$anonymous$$issingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. UnityEngine.GameObject.GetComponent[T] () (at C:/buildslave/unity/build/Runtime/Export/GameObject.bindings.cs:28) PlayerAttack.Update () (at Assets/Scripts/PlayerAttack.cs:45)
This was the other Error. It says Line 28 but it starts at line 25. Line 28:
Go ahead and try implementing the line of code in my second reply it should at least fix one of those errors, maybe both
I will go ahead and do that tomorrow and see what happens. I have no doubt it will work but I'll let you know.
I have more scripts I need to create that I have found some information on but could use your help on if you are not busy and ok with that?
I think I know what is going on.
In the line of code we are trying to get a component of Enemy Health and I dont have a reference to it in the code.
I added a private reference to enemy health at the top of the script but now it is throwing an error at line 48.
NullReferenceException: Object reference not set to an instance of an object PlayerAttack.Update () (at Assets/Scripts/PlayerAttack.cs:48)
if (currentTargetEnemy.GetComponent<EnemyHealth>().currentHealth <= 0){ Death(); }
void Death()
{
Debug.Log("Enemy Is Dead");
enemiesInRange.Remove(currentTargetEnemy);
}
Is it because the object is removed and not destroyed? I am also getting the same error once the object is removed from the scene i.e. the enemie is dead.
Answer by bdoobie01 · Mar 07, 2020 at 03:43 AM
Yea for sure email me at bdoobie01@gmail.com so we don't clog up the comments here, I'm happy to help (sorry 3rd account)
Just sent you an email. Thanks for all the help. Talk with you soon.
Your answer
Follow this Question
Related Questions
(URGENT) I have a swinging axe I can get to rotate once in 1 direction but i need it to loop 3 Answers
Help me with this code proplem,,Almost finish my game please help this once 3 Answers
How do I make a crouch script unity 3d 1 Answer
Why when using get; set; in one script i'm getting null in other script that use it ? 1 Answer
[C#] Quaternion Rotations with Input.GetAxis problems. 1 Answer