blog.gamedev.tv -Unity의 AI 인식 예제 프로젝트
Unity의 기능 중 NavMesh로 인해서 길을 찾고 FSM을 이용한 상태 패턴으로 간단한 AI를 만드는 기본적인 예제의 코드와 구현 방식에 대한 코드 리뷰입니다.
원본 URL : [링크]
프로젝트 링크 주소 : [링크]
<플레이 영상>
------------------------------------
Enemy Object와 Player 2가지와 기본적인 환경 파일로 Scene은 구성되어있다.
Enemy 에는 NavMeshAgent와 AlController, Patrol , Chase, 의 스크립트의 컴포넌트가 있고
Eyes와 Ears를 통해서 Player를 감지하도록 구성되어 있다.
DrawGizmos를 통해서 Eyes의 영역과 Ears의 영역을 확인할 수 있도록 구성되어있다.
<Sense>
public class Sense : MonoBehaviour
{
public Detectable Detectable;
public float Distance;
protected bool IsSensing;
public bool IsDetectionContinuous = true;
public UnityAction<Detectable> OnDetect;
public UnityAction<Detectable> OnLost;
#if UNITY_EDITOR
public Color DebugDrawColor = Color.green;
#endif
private void Detect(Detectable detectable)
{
IsSensing = true;
OnDetect?.Invoke(detectable);
}
private void Lost(Detectable detectable)
{
IsSensing = false;
OnLost?.Invoke(detectable);
}
void Update()
{
if (IsSensing)
{
if (!HasDetected(Detectable))
{
Lost(Detectable);
return;
}
if(IsDetectionContinuous)
{
Detect(Detectable);
}
}
else
{
if (!HasDetected(Detectable))
return;
Detect(Detectable);
}
}
protected virtual bool HasDetected(Detectable detectable) => false;
}
<Ears>
public class Ears : Sense
{
protected override bool HasDetected(Detectable detectable)
{
return Vector3.Distance(detectable.transform.position, transform.position) <= Distance && detectable.CanBeHear;
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
Gizmos.color = DebugDrawColor;
Gizmos.DrawWireSphere(transform.position, Distance);
}
#endif
}
<AIController>
public class AIController : MonoBehaviour
{
private AIBehaviour currentBehavior;
public AIBehaviour CurrentBehavior
{
get => currentBehavior;
private set
{
currentBehavior?.Deactivate(this);
value.Activate(this);
currentBehavior = value;
}
}
private Patrol PatrolBehavior;
private Investigate InvestigateBehavior;
private Chase ChaseBehavior;
private NavMeshAgent agent;
public float RemainingDistance { get => agent.remainingDistance; }
public float StoppingDistance { get => agent.stoppingDistance; }
public void SetDestination(Vector3 destination) => agent.SetDestination(destination);
private float defaultAgentSpeed;
public void MultiplySpeed(float factor) => agent.speed = defaultAgentSpeed * factor;
public void SetDefaultSpeed() => agent.speed = defaultAgentSpeed;
private Eyes eyes;
private Ears ears;
public void IgnoreEars(bool ignore) => ears.gameObject.SetActive(!ignore);
void Start()
{
agent = GetComponent<NavMeshAgent>();
defaultAgentSpeed = agent.speed;
PatrolBehavior = GetComponent<Patrol>();
InvestigateBehavior = GetComponent<Investigate>();
ChaseBehavior = GetComponent<Chase>();
eyes = GetComponentInChildren<Eyes>();
eyes.OnDetect += Chase;
eyes.OnLost += Investigate;
ears = GetComponentInChildren<Ears>();
ears.OnDetect += Investigate;
Patrol();
}
void Update()
{
CurrentBehavior.UpdateStep(this);
}
public void Patrol()
{
CurrentBehavior = PatrolBehavior;
}
public void Investigate(Detectable detectable)
{
InvestigateBehavior.Destination = detectable.transform.position;
CurrentBehavior = InvestigateBehavior;
}
public void Chase(Detectable detectable)
{
ChaseBehavior.Target = detectable.transform;
CurrentBehavior = ChaseBehavior;
}
}
<Patrol Point>
<Patrol>
처음 시작할때 기본적으로 Patrol의 정해진 Point를 기준으로 이동을 반복합니다.
public class Patrol : AIBehaviour
{
public Transform[] PatrolPoints;
private int currentPPIndex;
public override void Activate(AIController controller)
{
controller.SetDefaultSpeed();
controller.SetDestination(PatrolPoints[currentPPIndex].position);
}
public override void UpdateStep(AIController controller)
{
if (controller.RemainingDistance <= controller.StoppingDistance) {
currentPPIndex = currentPPIndex < PatrolPoints.Length - 1 ? currentPPIndex + 1 : 0;
controller.SetDestination(PatrolPoints[currentPPIndex].position);
}
}
}
Sense를 통해서 탐지할 항목이 탐지되면 다음 행동으로 넘어갑니다.
Patrol -> Chase -> Investigate의 형태로 State가 변경된다.
-----------------------------------
총평
<귀 구성요소>
<눈 구성요소>
블로그에서도 말하는것처럼 단순하게 Rule Base System으로 구성되어서 기본적인 AI 구성에는 도움 될만한 코드라고 생각이 든다. NavMesh를 통한 길 찾기, FSM, 탐지 요소 등등이 포함되어있다.
[Unity -Top Paid Package]
[Unity -Top Free Package]
[Unity -New Asset Package]
★★☆☆☆
'개발 > Unity) 코드분석' 카테고리의 다른 글
Unity)코드분석) Boss Room (0) | 2022.05.22 |
---|---|
코드분석) Commandpattern-Tutorial 프로젝트 (0) | 2022.04.12 |
코드분석) Unity Open Project - Chop Chop (0) | 2021.11.21 |
코드분석) MegaMan-Unity-8Bit(메가멘 8비트) (0) | 2021.08.16 |
코드분석) 유전 알고리즘(카트) (0) | 2021.05.09 |
댓글