OldBlueWater/BlueWater/Assets/02.Scripts/Ai/AiController.cs

111 lines
3.3 KiB
C#
Raw Normal View History

using System;
using UnityEngine;
2023-08-08 07:53:35 +00:00
using UnityEngine.AI;
using Random = UnityEngine.Random;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[Serializable]
public abstract class AiController : MonoBehaviour, IDamageable
{
#region Property and variable
2023-08-08 07:53:35 +00:00
protected bool isAttacking;
protected Animator aiAnimator;
2023-08-08 07:53:35 +00:00
protected AiMover aiMover;
protected FieldOfView fieldOfView;
2023-08-08 07:53:35 +00:00
protected NavMeshAgent navMeshAgent;
2023-08-08 07:53:35 +00:00
public static readonly int SpeedHash = Animator.StringToHash("Speed");
public static readonly int AttackHash = Animator.StringToHash("TakeDamage");
public static readonly int DamageHash = Animator.StringToHash("TakeDamage");
public static readonly int DeathTypeHash = Animator.StringToHash("DeathType");
public static readonly int DeathHash = Animator.StringToHash("Death");
#endregion
#region abstract function
protected abstract void Attack();
#endregion
#region Unity built-in function
protected virtual void Awake()
{
aiAnimator = Utils.GetComponentAndAssert<Animator>(transform);
2023-08-08 07:53:35 +00:00
aiMover = Utils.GetComponentAndAssert<AiMover>(transform);
fieldOfView = Utils.GetComponentAndAssert<FieldOfView>(transform);
2023-08-08 07:53:35 +00:00
navMeshAgent = Utils.GetComponentAndAssert<NavMeshAgent>(transform);
}
private void Start()
{
SetCurrentHp(AiStat.maxHp);
}
2023-08-08 07:53:35 +00:00
private void LateUpdate()
{
Attack();
}
#endregion
#region interface property and function
[field: SerializeField] public AiStat AiStat { get; set; } = new();
public void TakeDamage(AiStat attacker, AiStat defender)
{
// 회피 성공 체크
if (Random.Range(0, 100) < defender.avoidanceRate)
{
// TODO : 회피 처리
return;
}
var finalDamage = Utils.CalcDamage(attacker, defender);
// 방패 막기 체크
if (finalDamage == 0f)
{
// TODO : 방패로 막힘 처리(애니메이션 등)
return;
}
var changeHp = Mathf.Max(defender.currentHp - finalDamage, 0);
SetCurrentHp(changeHp);
// 죽었는지 체크
if (changeHp == 0f)
{
2023-08-08 07:53:35 +00:00
var randomValue = Random.Range(0, 2);
aiAnimator.SetInteger(DeathTypeHash, randomValue);
// TODO : 죽었을 때 처리(죽는 애니메이션 이후 사라지는 효과 등)
aiAnimator.SetTrigger(DeathHash);
2023-08-08 07:53:35 +00:00
Invoke(nameof(Destroy), 5f);
return;
}
aiAnimator.SetTrigger(DamageHash);
}
#endregion
#region Custom function
2023-08-08 07:53:35 +00:00
private void Destroy() => Destroy(gameObject);
public bool GetIsAttacking() => isAttacking;
public FieldOfView GetFieldOfView() => fieldOfView;
public NavMeshAgent GetNavMeshAgent() => navMeshAgent;
public Animator GetAnimator() => aiAnimator;
public void SetCurrentHp(float value) => AiStat.currentHp = value;
#endregion
}
}