Unity
[Unity 2D] 장애물과 겹치지 않게 랜덤하게 움직이기
(ꐦ •᷄ࡇ•᷅)
2025. 3. 5. 22:53
기능 설명
NPC가 배경에서 랜덤하게 움직이는 기능을 필요로 하였다.
이때, NPC가 움직일 때, 장애물과 겹치면 안 된다.
구현 알고리즘
- 랜덤한 위치를 선정한다.
- 그 위치에서 Physics2D.OverlapCircle을 사용하여 장애물의 반경에 속해 있는지 확인한다. (이때 장애물 레이어를 따로 설정해 준다.)
- 만약, 그 위치가 장애물 위면 다시 랜덤한 위치를 선택한다.
- 만약, 그 위치가 정상 위치라면 목표 경로에 장애물이 있는지 한 번 더 체크한다.
- 그래도 정상 위치라면 그 좌표로 이동하고, 장애물이 있는 경로라면 다시 랜덤한 위치를 선택한다.
AnimalController.cs
더보기
using System.Collections;
using UnityEngine;
public class AnimalController : MonoBehaviour
{
public int id;
public float moveSpeed = 2f;
public float waitTime = 2f;
public float checkRadius = 0.1f;
private bool isWaiting = false;
private LayerMask obstacleLayer;
private Vector2 targetPos;
private Vector2 minPos;
private Vector2 maxPos;
private void Start()
{
minPos = Managers.Game.Confiner.bounds.min;
maxPos = Managers.Game.Confiner.bounds.max;
obstacleLayer = LayerMask.GetMask("Obstacle");
ChooseNewPos();
}
private void Update()
{
if (isWaiting)
return;
Vector2 currentPos = transform.position;
float distance = Vector2.Distance(currentPos, targetPos);
if(distance < 0.1f)
{
StartCoroutine(WaitAndChooseNewTarget());
}
else
{
// 목표 경로에 장애물이 있는지 체크
// 동적으로 확인하여 움직이는 장애물도 피하게끔 함. (NPC끼리의 충돌)
Vector2 direction = (targetPos - currentPos).normalized;
RaycastHit2D hit = Physics2D.Raycast(currentPos, direction, distance, obstacleLayer);
#region 디버깅
//if (hit.collider != null)
// Debug.Log(hit.collider.gameObject.name);
//Debug.DrawRay(currentPos, direction * distance, Color.red);
#endregion
if (hit.collider == null)
{
transform.position = Vector2.MoveTowards(currentPos, targetPos, moveSpeed * Time.deltaTime);
}
else
{
ChooseNewPos();
}
}
}
void ChooseNewPos()
{
float x = Random.Range(minPos.x, maxPos.x);
float y = Random.Range(minPos.y, maxPos.y);
targetPos = new Vector2(x, y);
// 만약 새로 선택한 위치가 장애물 위면 다시 선택
if(Physics2D.OverlapCircle(targetPos, checkRadius, obstacleLayer))
{
ChooseNewPos();
}
}
IEnumerator WaitAndChooseNewTarget()
{
isWaiting = true;
yield return new WaitForSeconds(waitTime);
ChooseNewPos();
isWaiting = false;
}
}
결과
경로에 장애물이 있어 다시 경로를 설정하여 이동하는 모습이다.