
메탈슬러그 3 우주 미션에 등장하는 특정한 적 UFO를 하나 구현해야 했는데 일단 조건부터 정리해보았다.
플레이어를 특정하지 않는다, 아래를 향한 단순한 수직 공격.
1회 공격 - 이동 - 1회 공격 - 이동... 이런 패턴으로 계속 반복해야 한다.
이동 시 랜덤한 범위 내로만 이동해야 한다, 수직형 공격이다 보니 플레이어와 너무 근접해서는 안된다 = 화면 반 위에서만 놀도록 해야겠다로 해석
게임의 시작과 동시에 나오는 적이다보니 임팩트가 중요했기에 위 조건을 토대로 cs를 새로 작성했고,
어떻게 구현을 할 까 고민을 해보다가 Coroutine 사용해보기로 했다.
Coroutine
using UnityEngine;
using System.Collections;
public class SmallUFOMovement : MonoBehaviour
{
public Vector2 movementBoundsMin; // 왼쪽 아래
public Vector2 movementBoundsMax; // 오른쪽 위, 몹 활동 범위
public float moveTime; // 무빙 시간
public float waitTime; // 대기 시간
public GameObject attackPoint; // Attack_Point 오브젝트
public RangedAttackData attackData; // 공격 데이터
private Vector2 targetPosition;
void Start()
{
StartCoroutine(MoveAndAttackRoutine());
}
IEnumerator MoveAndAttackRoutine()
{
while (true)
{
// 범위 내 랜덤 움직임
targetPosition = new Vector2(
Random.Range(movementBoundsMin.x, movementBoundsMax.x),
Random.Range(movementBoundsMin.y, movementBoundsMax.y)
);
StartCoroutine(MoveToPosition(targetPosition, moveTime));
// 움직임이 끝날 때까지 기다림
yield return new WaitForSeconds(moveTime);
// 공격 로직
yield return StartCoroutine(PerformAttack());
// 공격이 끝날 때까지 기다림
yield return new WaitForSeconds(waitTime);
}
}
IEnumerator MoveToPosition(Vector2 target, float timeToMove)
{
var currentPos = transform.position;
var t = 0f;
while (t < 1)
{
t += Time.deltaTime / timeToMove;
transform.position = Vector2.Lerp(currentPos, target, t);
yield return null;
}
}
private IEnumerator PerformAttack()
{
attackPoint.SetActive(true);
// 애니메이션 재생 시간 대기
yield return new WaitForSeconds(0.5f);
// 투사체 아래로 발사
Vector2 direction = Vector2.down;
ProjectileManager.instance.ShootBulletStraightDown(attackPoint.transform.position, attackData.bulletNameTag);
//Attack_Point 비활성화
attackPoint.SetActive(false);
// 쿨다운 시간 동안 대기
yield return new WaitForSeconds(attackData.delay);
}
}
Start() 메서드: 스크립트가 시작될 때 코루틴을 실행
MoveAndAttackRoutine() 코루틴
이동 : 랜덤한 위치(targetPosition)를 생성하여 그 위치로 이동하도록 MoveToPosition() 코루틴을 시작하고 움직임이 끝날 때까지 대기
공격 : 공격 동작을 수행하는 PerformAttack() 코루틴을 실행, 공격이 끝날 때까지 대기
위 과정을 While을 통해 무한 반복
MoveToPosition() 코루틴: 주어진 시간 동안 target 위치로 선형 보간lerp 을 사용하여 부드럽게 이동.
Lerp
"선형 보간(Linear Interpolation)"
두 개의 값을 사이에 있는 중간값으로 부드럽게 이동시킨다.
그래픽, 애니메이션, 게임 개발 등에서 사용되며, 값을 부드럽게 변화시키는 데 유용함.
attackPoint 오브젝트를 활성화 : UFO 자체에서 투사체가 날아가는게 아닌 살짝 아래의 특정 위치에서 나가야 했음 + 특정 애니메이션이 재생되었어야 했기에 자식 오브젝트로 만들어서 평상시엔 숨겨놓고 공격시에 발동하게 함.
애니메이션 재생 시간(0.5초)를 확보하기 위해 대기
투사체를 아래로 발사, ProjectileManager 클래스를 사용하여 구현했고 attackData.bulletNameTag를 통해 적 UFO 고유의 투사체를 발사
공격 발사가 끝났으니 attackPoint를 비활성화
attackData.delay만큼 대기

인스펙터 스크립트 창에서 볼 수 있는 적의 움직임 범위 설정과, 다음 위치로 이동 할 수 있는 Move time(이동 속도의 개념), 공격 딜레이를 구현하였고
Attack point 오브젝트를 담고 Attack SO를 부여하여 고유의 공격력 등을 반영 함.

최종적으로 완성된 몬스터의 무브 & 어택 패턴