OldBlueWater/BlueWater/Assets/02.Scripts/Ai/FieldOfView.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

158 lines
4.7 KiB
C#

using System;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[Serializable]
public class TargetInfo
{
public Transform transform;
public Collider collider;
public IAiStat iAiStat;
public TargetInfo()
{
transform = null;
collider = null;
iAiStat = null;
}
public TargetInfo(Transform transform, Collider collider, IAiStat iAiStat)
{
this.transform = transform;
this.collider = collider;
this.iAiStat = iAiStat;
}
public void SetTargetInfo(Transform targetTransform, Collider collider, IAiStat targetIAiStat)
{
transform = targetTransform;
this.collider = collider;
iAiStat = targetIAiStat;
}
public void DefaultSetting()
{
transform = null;
collider = null;
iAiStat = null;
}
}
public class FieldOfView : MonoBehaviour
{
#region Property and variable
[Header("타겟 및 시야 설정")]
[SerializeField] private bool drawGizmo = true;
[SerializeField] private LayerMask targetLayer;
[Tooltip("시야 각도\n상대를 감지하는 0~360도 사이의 시야각")]
[Range(0f, 360f)]
[SerializeField] private float viewAngle = 360f;
[Tooltip("시야 길이\n상대를 감지하는 최대 길이, 부채꼴 혹은 원의 반지름 길이")]
[Range(0f, 50f)]
[SerializeField] private float viewRadius;
[Header("시야 내 타겟 정보")]
[SerializeField] private Collider[] colliderWithinRange = new Collider[TARGET_MAX_SIZE];
[SerializeField] private TargetInfo targetInfo = new();
private Collider targetCollider;
private IAiStat iAiStat;
private const int TARGET_MAX_SIZE = 20;
#endregion
#region Unity built-in Function
#if UNITY_EDITOR
public void OnDrawGizmosSelected()
{
if (!drawGizmo) return;
var myPos = transform.position;
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(myPos, viewRadius);
if (targetInfo.transform == null) return;
Debug.DrawLine(myPos, targetInfo.transform.position, Color.red);
}
#endif
private void LateUpdate()
{
Array.Clear(colliderWithinRange, 0, TARGET_MAX_SIZE);
var myPos = transform.position;
var maxColliderCount = Physics.OverlapSphereNonAlloc(myPos, viewRadius, colliderWithinRange,
targetLayer, QueryTriggerInteraction.Collide);
if (maxColliderCount <= 0)
{
targetInfo.DefaultSetting();
return;
}
iAiStat = colliderWithinRange[0].GetComponent<IAiStat>();
float nearestDistance;
Transform nearestTargetTransform;
if (iAiStat.GetCurrentHp() <= 0)
{
nearestDistance = float.PositiveInfinity;
nearestTargetTransform = null;
}
else
{
nearestDistance = Vector3.Distance(colliderWithinRange[0].transform.position, myPos);
nearestTargetTransform = colliderWithinRange[0].transform;
}
for (var i = 1; i < maxColliderCount; i++)
{
var distance = Vector3.Distance(colliderWithinRange[i].transform.position, myPos);
if (nearestDistance < distance) continue;
iAiStat = colliderWithinRange[i].GetComponent<IAiStat>();
if (iAiStat.GetCurrentHp() <= 0) continue;
nearestDistance = distance;
nearestTargetTransform = colliderWithinRange[i].transform;
}
if (nearestTargetTransform)
{
targetCollider = nearestTargetTransform.GetComponent<Collider>();
iAiStat = nearestTargetTransform.GetComponent<IAiStat>();
targetInfo.SetTargetInfo(nearestTargetTransform, targetCollider, iAiStat);
var targetPos = targetInfo.transform.position;
targetPos.y = transform.position.y;
transform.LookAt(targetPos);
}
else
{
targetInfo.DefaultSetting();
}
}
#endregion
#region Custom Function
public int GetTargetLayer() => targetLayer;
public TargetInfo GetTargetInfo() => targetInfo;
#endregion
}
}