Bullet script:
private void OnTriggerEnter(Collider other)
{
if (other.transform.CompareTag("Enemy"))
{
other.transform.GetComponent<Enemy>().TakeDamage(damage);
Destroy(gameObject);
}
}
Enemy class:
public abstract class Enemy : MonoBehaviour
{
protected float health = 100f;
protected NavMeshAgent agent;
protected Transform targetTransform;
protected Vector3 target;
protected bool targetIsPlayer = false;
protected abstract float AttackRange { get; set; }
protected abstract float AttackArea { get; set; }
protected abstract float EnemyDamage { get; set; }
protected abstract int EnemyExperience { get; set; }
// Player Layer as of time writing this is 6
protected LayerMask playerLayer = 6;
private void Awake()
{
agent = GetComponent<NavMeshAgent>();
}
public virtual void TakeDamage(float damage)
{
health -= damage;
if (health <= 0)
{
LevelManager.Instance.AddExperience(EnemyExperience);
Destroy(this.gameObject);
}
}
protected abstract void Attack();
protected abstract void CheckAttack();
protected void UpdateTarget(Vector3 newTarget, bool isPlayer)
{
this.target = newTarget;
this.targetIsPlayer = isPlayer;
agent.SetDestination(newTarget);
}
protected void UpdateTargetWithTransform(Transform newTarget, bool isPlayer)
{
this.targetTransform = newTarget;
this.targetIsPlayer = isPlayer;
agent.SetDestination(newTarget.position);
}
}
BasicZombie class:
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using UnityEngine;
using UnityEngine.AI;
public class BasicZombie : Enemy
{
private bool isAttacking;
private float attackRange = 2f;
protected override float AttackRange {
get { return attackRange; }
set { attackRange = value; }
}
private float attackArea = 3f;
protected override float AttackArea { get { return attackArea; } set { attackArea = value; } }
private float enemyDamage = 10f;
protected override float EnemyDamage { get { return enemyDamage; } set { enemyDamage = value; } }
[SerializeField] int experience = 10;
protected override int EnemyExperience { get { return experience; } set { experience = value; } }
protected override void Attack()
{
if (isAttacking) return;
Debug.Log("Attacking...");
isAttacking = true;
// Play Animation
}
public override void TakeDamage(float damage)
{
base.TakeDamage(damage);
}
// Call this on animation frame
protected override void CheckAttack()
{
Collider[] colliders = Physics.OverlapSphere(transform.position + transform.forward, AttackArea, playerLayer);
foreach (Collider collider in colliders)
{
if (collider.name.Equals("Player"))
{
collider.GetComponent<PlayerController>().TakeDamage(EnemyDamage);
}
}
}
// Start is called before the first frame update
void Start()
{
SetRandomTarget();
}
// Update is called once per frame
void Update()
{
if (targetIsPlayer)
{
UpdateTarget(targetTransform.position, true);
if (Vector3.Distance(transform.position, target) < AttackRange)
{
Attack();
}
return;
}
if (Vector3.Distance(transform.position, target) < 3f)
{
SetRandomTarget();
}
}
void SetRandomTarget()
{
// Get a random point within the NavMesh bounds
Vector3 randomPoint = RandomNavMeshPoint();
// Set the agent's destination to the random point
UpdateTarget(randomPoint, false);
}
// This should be changed as if random point is not in navmesh than not position I think, but this needs to be player's location eventually anyway
Vector3 RandomNavMeshPoint()
{
// Get a random point within the NavMesh bounds
Vector3 randomDirection = Random.insideUnitSphere * 20f; // Change 10f to your desired radius
randomDirection += transform.position;
NavMeshHit hit;
NavMesh.SamplePosition(randomDirection, out hit, 20f, NavMesh.AllAreas); // Change 10f to your desired maximum distance
return hit.position;
}
private void OnTriggerEnter(Collider other)
{
if (other.transform.tag.Equals("Player"))
{
Debug.Log("Player noticed");
this.UpdateTargetWithTransform(other.transform, true);
}
}
private void OnTriggerExit(Collider other)
{
if (other.transform.tag.Equals("Player"))
{
Debug.Log("Lost player");
SetRandomTarget();
targetTransform = null;
}
}
}
All the enemies have the BasicZombie class attached to them which is derived from the abstract Enemy class.
Problem
When shooting an enemy all the enemies take damage when a bullet hits one enemy. This is not a collider issue as far away enemies are damaged as well. I think the problem could lie with the abstract class sort of being handled as a singleton maybe?
Does anyone know what the problem is, this would help me a lot.