add: fully functional melee enemy
This commit is contained in:
@@ -3,7 +3,6 @@ using UnityEngine.AI;
|
||||
|
||||
public class MeleeEnemy : Enemy
|
||||
{
|
||||
public float speed = 1f;
|
||||
public float detectionRadius = 5f;
|
||||
public float patrollRadius = 3f;
|
||||
public float damage = 5f;
|
||||
@@ -14,6 +13,7 @@ public class MeleeEnemy : Enemy
|
||||
[SerializeField] MeleeEnemyState currentState = MeleeEnemyState.Patrolling;
|
||||
Vector3 patrollingTarget;
|
||||
NavMeshAgent navMeshAgent;
|
||||
float currentDelay = 0;
|
||||
|
||||
void Start() {
|
||||
target = FindFirstObjectByType<Player>();
|
||||
@@ -24,22 +24,52 @@ public class MeleeEnemy : Enemy
|
||||
void Update() {
|
||||
switch (currentState) {
|
||||
case MeleeEnemyState.Patrolling:
|
||||
Vector3 vectorToTarget = (target.transform.position - transform.position).normalized;
|
||||
bool canSee = false;
|
||||
if (Physics.Raycast(transform.position, vectorToTarget, out RaycastHit hit, detectionRadius)) {
|
||||
if (hit.transform.CompareTag("Player")) canSee = true;
|
||||
}
|
||||
if (canSee) currentState = MeleeEnemyState.Pursuing;
|
||||
if (CanSeeTarget()) currentState = MeleeEnemyState.Pursuing;
|
||||
else {
|
||||
if (Vector3.Distance(transform.position, patrollingTarget) <= 0.1f) patrollingTarget = GetPatrollingTarget();
|
||||
if (Vector3.Distance(transform.position - new Vector3(0, navMeshAgent.baseOffset * transform.localScale.y), navMeshAgent.destination) <= 0.1f) patrollingTarget = GetPatrollingTarget();
|
||||
navMeshAgent.destination = patrollingTarget;
|
||||
}
|
||||
break;
|
||||
case MeleeEnemyState.Pursuing:
|
||||
if (!CanSeeTarget()) currentState = MeleeEnemyState.Patrolling;
|
||||
navMeshAgent.destination = target.transform.position;
|
||||
if (Vector3.Distance(transform.position, target.transform.position) <= attackRadius) currentState = MeleeEnemyState.Attacking;
|
||||
break;
|
||||
case MeleeEnemyState.Attacking:
|
||||
navMeshAgent.ResetPath();
|
||||
if (Vector3.Distance(transform.position, target.transform.position) >= attackRadius) currentState = CanSeeTarget() ? MeleeEnemyState.Pursuing : MeleeEnemyState.Patrolling;
|
||||
else if (currentDelay >= 1 / attackRate) {
|
||||
target.DealDamage(damage);
|
||||
currentDelay = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (attackRate != 0) {
|
||||
if (currentState == MeleeEnemyState.Attacking) currentDelay = Mathf.Clamp(currentDelay += Time.deltaTime, 0, 1 / attackRate);
|
||||
else currentDelay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetPatrollingTarget() {
|
||||
return Vector3.zero;
|
||||
NavMeshPath path = new();
|
||||
while (true) {
|
||||
Vector2 circle = Random.insideUnitCircle * patrollRadius;
|
||||
Vector3 maybeDestination = transform.position + new Vector3(circle.x, 0, circle.y);
|
||||
NavMesh.CalculatePath(transform.position, maybeDestination, NavMesh.AllAreas, path);
|
||||
if (path.status == NavMeshPathStatus.PathComplete) return maybeDestination;
|
||||
if (path.status != NavMeshPathStatus.PathInvalid) break;
|
||||
}
|
||||
Vector3 destination = path.corners[^1];
|
||||
destination.y = transform.position.y;
|
||||
return destination;
|
||||
}
|
||||
|
||||
bool CanSeeTarget() {Vector3 vectorToTarget = (target.transform.position - transform.position).normalized;
|
||||
bool canSee = false;
|
||||
if (Physics.Raycast(transform.position, vectorToTarget, out RaycastHit hit, detectionRadius)) {
|
||||
if (hit.transform.CompareTag("Player")) canSee = true;
|
||||
}
|
||||
return canSee;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ public class GameController : MonoBehaviour
|
||||
public string deploySceneName;
|
||||
public List<LevelInfo> levels;
|
||||
public List<EnemyInfo> enemies;
|
||||
public int startEnemiesNumber = 1;
|
||||
public Dictionary<BulletType, int> inventory = new();
|
||||
|
||||
public void Awake() {
|
||||
@@ -23,7 +24,7 @@ public class GameController : MonoBehaviour
|
||||
return li;
|
||||
}).ToList();
|
||||
levels.ForEach(li => {
|
||||
AddEnemyInLevel(SelectEnemyWeighted().prefab, li.sceneName);
|
||||
for (int i = 0; i < startEnemiesNumber; ++i) AddEnemyInLevel(SelectEnemyWeighted().prefab, li.sceneName);
|
||||
});
|
||||
foreach (BulletType i in Enum.GetValues(typeof(BulletType))) {
|
||||
if (i == BulletType.None) continue;
|
||||
|
||||
Reference in New Issue
Block a user