187 lines
4.7 KiB
C#
187 lines
4.7 KiB
C#
using UnityEngine;
|
|
using Akila.FPSFramework;
|
|
|
|
public enum TargetType
|
|
{
|
|
None,
|
|
Enemy,
|
|
Player,
|
|
PatrolPoint
|
|
}
|
|
|
|
public abstract class BaseAIController : MonoBehaviour
|
|
{
|
|
[Header("Movement & Combat")]
|
|
public float moveSpeed = 5f;
|
|
public float chaseRange = 15f;
|
|
public float stopCloseRange = 4f;
|
|
public float strafeAmount;
|
|
public float pointWaitTimer = 3f;
|
|
public float currentHealth = 25f;
|
|
public float waitToDisappear = 4f;
|
|
public float damageAmount = 10f;
|
|
|
|
[Header("Components")]
|
|
public Rigidbody theRB;
|
|
public Animator anim;
|
|
|
|
[Header("Patrol")]
|
|
public Transform[] PatrolPoints;
|
|
protected int currentPatrolPoint;
|
|
public Transform pointsHolder;
|
|
protected float waitCounter;
|
|
|
|
protected bool isDead;
|
|
protected float attackCooldown = 1f;
|
|
protected float attackTimer = 0f;
|
|
|
|
protected FirstPersonController player;
|
|
protected Damageable playerDamageable;
|
|
|
|
protected virtual void Start()
|
|
{
|
|
player = FindFirstObjectByType<FirstPersonController>();
|
|
if (player != null)
|
|
{
|
|
playerDamageable = player.GetComponent<Damageable>();
|
|
}
|
|
|
|
strafeAmount = Random.Range(-0.75f, 0.75f);
|
|
if (pointsHolder != null)
|
|
{
|
|
pointsHolder.SetParent(null);
|
|
}
|
|
waitCounter = Random.Range(0.75f, 1.25f) * pointWaitTimer;
|
|
attackTimer = 0f;
|
|
}
|
|
|
|
protected void HandleDeath()
|
|
{
|
|
waitToDisappear -= Time.deltaTime;
|
|
if (waitToDisappear <= 0)
|
|
{
|
|
transform.localScale = Vector3.MoveTowards(transform.localScale, Vector3.zero, Time.deltaTime * 2f);
|
|
if (transform.localScale.magnitude < 0.1f)
|
|
{
|
|
Destroy(gameObject);
|
|
if (pointsHolder != null)
|
|
{
|
|
Destroy(pointsHolder.gameObject);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void UpdateTimers()
|
|
{
|
|
attackTimer -= Time.deltaTime;
|
|
}
|
|
|
|
protected bool ValidatePlayerReferences()
|
|
{
|
|
return player != null && playerDamageable != null;
|
|
}
|
|
|
|
protected void StopMovement()
|
|
{
|
|
theRB.linearVelocity = Vector3.zero;
|
|
anim.SetFloat("speed", 0f);
|
|
}
|
|
|
|
protected void LookAt(Transform target)
|
|
{
|
|
if (target != null)
|
|
{
|
|
transform.LookAt(new Vector3(target.position.x, transform.position.y, target.position.z));
|
|
}
|
|
}
|
|
|
|
protected void MoveTowardsTarget(Transform target, float speedMultiplier)
|
|
{
|
|
if (target != null)
|
|
{
|
|
LookAt(target);
|
|
theRB.linearVelocity = (transform.forward + transform.right * strafeAmount) * moveSpeed;
|
|
anim.SetFloat("speed", speedMultiplier);
|
|
}
|
|
}
|
|
|
|
protected void AttackTarget()
|
|
{
|
|
theRB.linearVelocity = Vector3.zero;
|
|
anim.SetFloat("speed", 0f);
|
|
|
|
if (attackTimer <= 0f)
|
|
{
|
|
anim.SetTrigger("attack");
|
|
attackTimer = attackCooldown;
|
|
}
|
|
}
|
|
|
|
protected void HandlePatrolling()
|
|
{
|
|
if (PatrolPoints.Length > 0)
|
|
{
|
|
float distanceToPatrolPoint = Vector3.Distance(transform.position,
|
|
new Vector3(PatrolPoints[currentPatrolPoint].position.x, transform.position.y, PatrolPoints[currentPatrolPoint].position.z));
|
|
|
|
if (distanceToPatrolPoint < 0.25f)
|
|
{
|
|
WaitAtPatrolPoint();
|
|
}
|
|
else
|
|
{
|
|
MoveToPatrolPoint();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StopMovement();
|
|
}
|
|
}
|
|
|
|
protected void WaitAtPatrolPoint()
|
|
{
|
|
waitCounter -= Time.deltaTime;
|
|
StopMovement();
|
|
|
|
if (waitCounter <= 0)
|
|
{
|
|
MoveToNextPatrolPoint();
|
|
}
|
|
}
|
|
|
|
protected void MoveToNextPatrolPoint()
|
|
{
|
|
currentPatrolPoint++;
|
|
if (currentPatrolPoint >= PatrolPoints.Length)
|
|
{
|
|
currentPatrolPoint = 0;
|
|
}
|
|
waitCounter = Random.Range(0.75f, 1.25f) * pointWaitTimer;
|
|
}
|
|
|
|
protected void MoveToPatrolPoint()
|
|
{
|
|
MoveTowardsTarget(PatrolPoints[currentPatrolPoint], 0.5f); // Walking speed
|
|
}
|
|
|
|
protected void PreserveVerticalVelocity(float yStore)
|
|
{
|
|
theRB.linearVelocity = new Vector3(theRB.linearVelocity.x, yStore, theRB.linearVelocity.z);
|
|
}
|
|
|
|
public virtual void TakeDamage(float damageToTake)
|
|
{
|
|
currentHealth -= damageToTake;
|
|
if (currentHealth <= 0)
|
|
{
|
|
anim.SetTrigger("dead");
|
|
isDead = true;
|
|
theRB.linearVelocity = Vector3.zero;
|
|
theRB.isKinematic = true;
|
|
GetComponent<Collider>().enabled = false;
|
|
}
|
|
}
|
|
}
|