WayPoint를 이용한 적 움직임 패턴 구현
WayPoint
-
웨이포인트는
Vector[]
값을 지정하고 오브젝트가 해당 위치를 배열 순으로 이동하여 움직임 패턴을 만드는 방법입니다. -
미리 좌표값을 넣어둘수도 있으며, 메서드 내부에서 좌표를 만드는 방법도 있습니다.
웨이포인트 생성기
- 먼저 내부에서 웨이포인트좌표를 생성하는 로직입니다.
public static Vector2[] CalculateWaypoints(Enemy enemy, int wayPointCount)
{
int direction = Random.Range(0, 2) == 0 ? -1 : 1;
Vector2[] wayPoints = new Vector2[wayPointCount];
Vector2 startPosition = enemy.transform.position;
for (int i = 0; i < wayPoints.Length; i++)
{
float nextX = Mathf.Clamp(startPosition.x + direction * WayPointWidthValue, -3.5f, 3.5f);
float nextY = Mathf.Clamp(startPosition.y - 2 * (i + 1), -5f, 5f);
wayPoints[i] = new Vector2(nextX, nextY);
direction *= -1;
startPosition = wayPoints[i];
}
return wayPoints;
}
-
메소드 선언
public static Vector2[] CalculateWaypoints(Enemy enemy, int wayPointCount)
- 이는 정적 메서드입니다. 즉, 클래스의 인스턴스가 아닌 클래스 자체에 속합니다.
- 웨이포인트를 나타내는
Vector2
객체의 배열을 반환합니다. - 두 개의 매개변수, 즉
Enemy
객체와 생성할 경유지 수를 나타내는int
를 사용합니다.
- 웨이포인트를 나타내는
-
임의 방향 초기화
int 방향 = Random.Range(0, 2) == 0 ? -1 : 1;
- 이 선은 첫 번째 웨이포인트의 초기 이동 방향(왼쪽 또는 오른쪽)을 결정합니다.
- Unity의
Random.Range
를 사용하여 0과 1 사이에서 선택합니다. 0이면 방향이 -1(왼쪽)으로 설정되고, 1이면 방향이 1(오른쪽)으로 설정됩니다.
- Unity의
-
웨이포인트 배열 초기화
Vector2[] wayPoints = new Vector2[wayPointCount];
- 이 줄은 길이가
wayPointCount
매개변수로 설정된Vector2
구조의 배열을 초기화합니다.- 이 배열의 각 ‘Vector2’는 웨이포인트의 x 및 y 좌표를 보유합니다.
-
시작 위치
-
Vector2 startPosition = 적.변환.위치;
- 이 줄은
Enemy
객체의 시작 위치를 가져와startPosition
에 저장합니다. - 첫 번째 웨이포인트를 계산하기 위한 기준점으로 사용됩니다.
- 이 줄은
-
-
웨이포인트 계산 루프:
-
for (int i = 0; i < wayPoints.Length; i++)
- 이 for 루프는 waypoints 배열을 반복하여 각 waypoint를 계산합니다.
-
- 루프 내에서
-
float nextX = Mathf.Clamp(startPosition.x + 방향 * WayPointWidthValue, -3.5f, 3.5f);
: 다음 웨이포인트의 x 좌표를 계산합니다. -
Mathf.Clamp
를 사용하여 x 좌표가 지정된 범위(이 경우 -3.5 ~ 3.5) 내에 유지되도록 합니다. -
WayPointWidthValue
는 각 웨이포인트가 이전 웨이포인트로부터 수평으로 얼마나 떨어져 있는지를 결정하는 상수 또는 변수(제공된 코드에 정의되지 않음)입니다. -
float nextY = Mathf.Clamp(startPosition.y - 2 * (i + 1), -5f, 5f);
: 다음 웨이포인트의 y좌표를 계산합니다. -
nextX
와 유사하게 y 좌표가 범위(-5 ~ 5) 내에 유지되고 매번 아래로 이동합니다(- 2 * (i + 1)
). -
wayPoints[i] = new Vector2(nextX, nextY);
: 계산된 x 및 y 좌표를 waypoints 배열의i
번째 요소에 할당합니다. -
방향 *= -1;
: 다음 웨이포인트 계산을 위해 방향을 반대로 합니다. -
startPosition = wayPoints[i];
: 다음 반복을 위해startPosition
을 현재 경유지 위치로 업데이트합니다.
-
반환:
-
return wayPoints;
: 루프가 완료된 후 메서드는 계산된 웨이포인트 배열을 반환합니다.
-
지그재그 형태의 웨이포인트
public void Zigzag()
{
CoroutineInit();
Vector2[] wayPoints = CalculateWaypoints(this, 3);
_moveCoroutine = StartCoroutine(MoveZigzag(this, wayPoints));
}
MoveZigzag()
public static IEnumerator MoveZigzag(Enemy enemy, Vector2[] wayPoints)
{
int currentWaypointIndex = 0;
while (currentWaypointIndex < wayPoints.Length)
{
Vector2 currentWaypoint = wayPoints[currentWaypointIndex];
while (Vector2.Distance(enemy.transform.position, currentWaypoint) > 0.01f)
{
enemy.transform.position = Vector2.MoveTowards(
enemy.transform.position,
currentWaypoint,
enemy.speed * Time.deltaTime * SpeedOffset);
yield return null;
}
currentWaypointIndex++;
}
enemy.EndToEnemyCoroutine(enemy);
}
-
메서드 선언:
-
public static IEnumerator MoveZigzag(Enemy enemy, Vector2[] wayPoints)
: 이것은 Unity에서 정적 코루틴 메서드입니다. -
Enemy
객체와 웨이포인트를 나타내는Vector2
객체 배열을 매개변수로 받습니다.
-
-
현재 웨이포인트 인덱스 초기화:
-
int currentWaypointIndex = 0;
: 이 줄은 적이 현재 향하고 있는 웨이포인트를 추적하기 위한 인덱스를 초기화합니다.
-
-
웨이포인트 탐색을 위한 외부 While 루프:
-
while (currentWaypointIndex < wayPoints.Length)
: 이 루프는 적이 마지막 웨이포인트에 도달할 때까지 계속됩니다. - 적이 배열의 각 웨이포인트를 거치도록 합니다.
-
-
현재 웨이포인트 접근:
-
Vector2 currentWaypoint = wayPoints[currentWaypointIndex];
: 이 줄은 현재 웨이포인트 인덱스를 사용하여 배열에서 현재 웨이포인트를 검색합니다.
-
-
현재 웨이포인트로 이동을 위한 내부 While 루프:
-
while (Vector2.Distance(enemy.transform.position, currentWaypoint) > 0.01f)
: 이 내부 루프는 적이 현재 웨이포인트와 매우 가까워질 때까지 계속됩니다 (0.01 유닛 미만). -
Vector2.Distance
를 사용하여 적의 현재 위치와 웨이포인트 사이의 거리를 계산합니다.
-
-
적 이동:
-
enemy.transform.position = Vector2.MoveTowards(enemy.transform.position, currentWaypoint, enemy.speed * Time.deltaTime * SpeedOffset);
: 이 줄은 적을 현재 웨이포인트 쪽으로 이동시킵니다. - 부드럽게 이동시키기 위해
Vector2.MoveTowards
를 사용합니다. -
enemy.speed * Time.deltaTime * SpeedOffset
는 이동 속도를 결정합니다.SpeedOffset
은 적의 속도를 수정하는 상수나 변수로 추정됩니다. -
Time.deltaTime
은 움직임이 프레임 속도에 독립적이도록 보장합니다.
-
-
Yield Return:
-
yield return null;
: 이 줄은 각 프레임에서 Unity 엔진으로 제어를 반환하여 부드러운 움직임과 다른 게임 프로세스가 계속될 수 있도록 합니다.
-
-
웨이포인트 인덱스 증가:
-
currentWaypointIndex++;
: 웨이포인트에 도달한 후에는 인덱스를 증가시켜 다음 웨이포인트로 이동합니다.
-
-
루틴 종료 처리:
-
enemy.EndToEnemyCoroutine(enemy);
: 모든 웨이포인트에 도달하면 이 메서드가 호출됩니다. 해당 메서드 호출 시 코루틴을 종료하고, 초기화 하여 코루틴으로 인해 발생할 수 있는 문제를 예방합니다.
-
정해진 좌표를 이동하는 웨이포인트 메서드
public static IEnumerator BossInfinityPattern(Enemy enemy)
{
Vector3[] waypoints =
{
new(0f,3.5f,0f),
new(-1.5f,2.5f,0f),
new(-3f,3.5f,0f),
new(-1.5f,4.5f,0f),
new(1.5f,2.5f,0f),
new(3f,3.5f,0f),
new(1.5f,4.5f,0f),
new Vector3(0f,3.5f,0f)
};
foreach (Vector3 wayPoint in waypoints)
{
while (Vector3.Distance(enemy.transform.position, wayPoint) > 0.01f)
{
enemy.transform.position = Vector3.MoveTowards(
enemy.transform.position,
wayPoint,
enemy.speed * Time.deltaTime * SpeedOffset);
yield return null;
}
}
BossNextPattern(enemy);
}
- 해당 메서드의 웨이포인트의 경우 옆으로 누운 8자 형태로 움직이는 메서드 입니다.
- 만약 좌표를 알 수 있고 고정된 행위를 하는 오브젝트의 경우 이러한 방법이 더 직관적이고 도움이 될 수 있습니다.