OldBlueWater/BlueWater/Assets/02.Scripts/Ai/AiController.cs
NTG_Lenovo 86065e52a9 #10 Testing long range ai (arrow attack system)
Additional commit content
1. Modified ObjectPool Function(OnReleaseArrow and naming).
2. Modified hitBox tag in aiPrefab.
3. Modified Physics layer.
4. Modified TargetInfo variable from TargetTransform variable in FieldOfView script.
5. Added GetCurrentHp() in IAiStat script.
2023-08-09 16:44:09 +09:00

134 lines
4.0 KiB
C#

using System;
using UnityEngine;
using UnityEngine.AI;
using Random = UnityEngine.Random;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public enum AttackerType
{
NONE,
PLAYER,
PIRATE,
ENEMY
}
[Serializable]
public abstract class AiController : MonoBehaviour, IDamageable
{
#region Property and variable
protected bool isAttacking;
protected AttackerType attackerType;
protected Animator aiAnimator;
protected AiMover aiMover;
protected FieldOfView fieldOfView;
protected NavMeshAgent navMeshAgent;
public static readonly int SpeedHash = Animator.StringToHash("Speed");
public static readonly int AttackHash = Animator.StringToHash("Attack");
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);
aiMover = Utils.GetComponentAndAssert<AiMover>(transform);
fieldOfView = Utils.GetComponentAndAssert<FieldOfView>(transform);
navMeshAgent = Utils.GetComponentAndAssert<NavMeshAgent>(transform);
if (gameObject.layer == LayerMask.NameToLayer("Player"))
{
attackerType = AttackerType.PLAYER;
}
else if (gameObject.layer == LayerMask.NameToLayer("Pirate"))
{
attackerType = AttackerType.PIRATE;
}
else if (gameObject.layer == LayerMask.NameToLayer("Enemy"))
{
attackerType = AttackerType.ENEMY;
}
}
private void Start()
{
SetCurrentHp(AiStat.maxHp);
}
private void LateUpdate()
{
Attack();
}
#endregion
#region interface property and function
[field: SerializeField] public AiStat AiStat { get; set; } = new();
public float GetCurrentHp() => AiStat.currentHp;
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)
{
var randomValue = Random.Range(0, 2);
aiAnimator.SetInteger(DeathTypeHash, randomValue);
// TODO : 죽었을 때 처리(죽는 애니메이션 이후 사라지는 효과 등)
aiAnimator.SetTrigger(DeathHash);
Invoke(nameof(Destroy), 5f);
return;
}
aiAnimator.SetTrigger(DamageHash);
}
#endregion
#region Custom function
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
}
}