- Home /
How to fix a combat issue with my game
I have recently been trying to implement a combat system to my game. When I finished making the scripts, I tried to test it out. I set the attack damage to 20 and the enemy's max health to 100. When i attacked the enemy, the health went to -20. I tried changing the damage to -20 but now it goes to 20. I also cannot attack the enemy twice.
edit: the version of unity i am using is 2020.3.0f1
Here are the scripts I used:
Script 1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ENEMY : MonoBehaviour
{
public int maxHealth = 100;
int currenthealth;
// Start is called before the first frame update
void Start()
{
currenthealth = maxHealth;
}
public void TakeDamage(int damage)
{
currenthealth -= damage;
//Play a hurt animation
if(currenthealth <= 0)
{
Die();
}
void Die()
{
Debug.Log("enemy died");
// play die animation
// disable the enemy
}
}
}
Script 2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PLAYER_COMBAT : MonoBehaviour
{
public Animator animator;
public Transform attackPoint;
public LayerMask enemyLayers;
public float attackRange = 0.5f;
public int attackDamage = 20;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
Attack();
}
}
void Attack()
{
// play attack animation
animator.SetTrigger("Attack");
// detect enemies in range of the attack
Collider[] hitEnemies = Physics.OverlapSphere(attackPoint.position, attackRange, enemyLayers);
// damage the enemy
foreach (Collider enemy in hitEnemies)
{
enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
}
}
void OnDrawGizmosSelected()
{
if (attackPoint == null)
return;
{
Gizmos.DrawWireSphere(attackPoint.position, attackRange);
}
}
}
As you may be able to tell, I haven't set up a dying animation or disabled the enemy after it died yet
also you declare Die() in take damage, it should not be.
is each enemy just one hitbox? if it is more then you can hit each enemy more than once with each attack with your current code.
Is there a way other than that to fix this because I feel like if I want to make a really op enemy I would have to add way too many hitboxes and it would just cause problems or mild annoyance
other way than what way? best thing you can do is to go up in the hierarchy until you find your enemy script for each collider. Then you save each enemy and compare if you already dealt damage to that specific enemy with this specific hit.
Answer by logicandchaos · Jun 26, 2021 at 01:58 PM
The answer is you did not set your health to 100 it is 0 because that is what it is set as in your inspector. Your max health is a public variable so it is serialized in the inspector so that whatever value is in your inspector will overwrite what is in your code. To fix this you either must set it in your inspector, or make the variable private and if you need to access it than make a method or property to do so.
I have set the max health in the inspector to 100 and made the integer variable private but i still have this issue, is there anything else I could do to help fix the issue? @logicandchaos
If you make it public you have to set it in the inspector unless you use HideInspector, if you make it private you have to set it in the code unless you use SerializeField. I could suggest some more things that may help, but last time I just got down voted, and hardly anyone ever upvotes any answers here.. so don't want to lose more reputation points..
Answer by Devster2020 · Jun 29, 2021 at 05:55 PM
Hi @ReferenceWolf, Probably, as @Captain_Pineapple says, you have more than one hitbox on the "ENEMY" object, so the getDamage () method is executed multiple times with a single attack.
To work around this, change your piece of code regarding the foreach loop to this:
// damage the enemy
List<Enemy> hittedEnemies = new List<Enemy>();
foreach (Collider enemyCollider in hitEnemies)
{
Enemy enemy = enemyCollider.GetComponent<Enemy>(); //Take the enemy
if(!hittedEnemies.Contains(enemy)){ //If not previous hitted,
enemy.TakeDamage(attackDamage); //Hit
hittedEnemies.Add(enemy); //Add to "previous hitted" list
}
}
Hi there @Devster2020, I don't have multiple hitboxes on my enemy but thank you for the code. Also thank you for helping on my other question I asked about loading screens :) Do you have any idea on why he instantly dies and does more damage than i set it to? If so any help would be greatly appreciated :)
You're welcome..
To better understand what is happening, I suggest you add logs to your code to better analyze the trend and understand if the same code is run several times.
Add these logs just before doing the damage:
public void TakeDamage(int damage) {
Debug.Log(string.Format("Current Health: {0} - Damage: {1}", currenthealth, damage));
currenthealth -= damage;
Debug.Log("Current Health: " + currenthealth);
//Play a hurt animation
if(currenthealth <= 0){
Die();
}
}