모각코 4회차

alvin·4일 전

오늘은 랜덤인카운터, 플레이어 이동 애니메이션을 구현해보겠습니다!!

1. 랜덤인카운터
'포켓몬스터'라는 게임 아시나요?? 이 게임에서 풀숲을 돌아다니다 보면 무작위로 야생 포켓몬을 만날 수 있는데요~

이러한 방식을 이용해서 제 게임에서 적과의 전투를 발생시킬 것입니다!
제가 생각한 인카운터 로직은 플레이어가 이동을 해서 밟고 있는 타일이 달라지면 어떤 메소드를 호출하고, 그 메소드에서 난수를 만들어 기준 이상이면 인카운터가 발생하는 방식입니다.

기존 PlayerController 스크립트에서 변경된 부분을 보겠습니다!

private float criticalPoint = 80;
private Vector3Int previousPosition;
.
.
.
private void Move(Vector2 direction)
    {

        if (CanMove(direction))
        {   
            transform.position += (Vector3)direction;


            Vector3Int afterPosition = groundTilemap.WorldToCell(transform.position);
            if(previousPosition != afterPosition)
            {
                OnSteppedOnNewTile(afterPosition);
                
                previousPosition = afterPosition;
            }
        }

       
    }
.
.
.
.
private void OnSteppedOnNewTile(Vector3Int newPosition)
    {
        int P = Random.Range(1,100);

        if(P >= criticalPoint)
        {
            Debug.Log("Encounter!!");
        }
    }

먼저 인카운터 발생 기준점을 80으로 잡아주었습니다. 또한 다른 타일을 밟았는지 확인하기 위해서 이전위치를 기억하는 변수를 만들었습니다.

(생략되었지만 Start메소드에서는
previousPosition = currentCell;로 현재 위치를 넣어주었습니다.)

Move메소드에서는 afterPosition 메소드에 이동후의 위치를 저장해주었고, 이전 위치와 이후 위치가 다르다면 메소드를 호출해주고 이전위치를 이후위치로 바꿔주었습니다.

OnSteppedOnNewTile메소드에서는 1~99까지의 정수 난수를 받는 변수 P가 임계점 이상이면 "Encounter!!"을 콘솔창에 출력하게 했습니다.

2. 이동 애니메이션
저번에 말했듯이 스프라이트에 캐릭터 모습하나 딸랑 있기 때문에 이동할 때 심심할 수 있습니다. 그래서 이동할 때 캐릭터가 흔들리는 애니메이션을 추가해주었습니다.

흔들리는 효과를 주는데는 3가지의 방법이 있는데

  1. 캐릭터만 비추는 카메라 흔들기

  2. 애니메이터로 애니메이션 만들기

  3. 스크립트에 코루틴 만들기

이렇게 있습니다. 저는 코루틴을 사용했습니다.
스크립트 변경점입니다!!

SpriteRenderer spriteRenderer;
private Coroutine shakeCoroutine;
.
.
.
private void Move(Vector2 direction)
    {
        if(direction.x != 0)
        {
            spriteRenderer.flipX = (direction.x == 1);
        }

        if (CanMove(direction))
        {   
            transform.position += (Vector3)direction;

            if (shakeCoroutine != null)
            {
                StopCoroutine(shakeCoroutine);
            }
            shakeCoroutine = StartCoroutine(ShakeSpriteRoutine(direction));

            Vector3Int afterPosition = groundTilemap.WorldToCell(transform.position);
            if(previousPosition != afterPosition)
            {
                OnSteppedOnNewTile(afterPosition);
                
                previousPosition = afterPosition;
            }
        }

       
    }
.
.
.
private IEnumerator ShakeSpriteRoutine(Vector2 direction)
    {
        Transform spriteTransform = spriteRenderer.transform;

        float targetRotationZ = 0f;
        if(direction.x > 0)
        {
            targetRotationZ = -5f;
        }
        else if(direction.x < 0)
        {
            targetRotationZ = 5f;
        }
        else
        {
            targetRotationZ = 5f;
        }

        spriteTransform.localPosition = new Vector3(0,0.12f,0);
        spriteTransform.localRotation = Quaternion.Euler(0,0,targetRotationZ);
        yield return new WaitForSeconds(0.06f);

        spriteTransform.localPosition = Vector3.zero;
        spriteTransform.localRotation = Quaternion.identity;
        yield return new WaitForSeconds(0.1f);
    }
}

1)플레이어 방향 바꾸기
direction.x != 0: 위아래로만 움직일 때는 이미지를 뒤집을 필요가 없으므로, 오직 좌우 입력(direction.x가 0이 아닐 때)이 있을 때만 내부 로직을 실행합니다.

spriteRenderer.flipX = (direction.x == 1);:

만약 플레이어가 오른쪽 키를 누르면 direction.x 값은 1이 됩니다. 이때 (direction.x == 1)이라는 조건식은 참(true)이 되므로 flipX가 켜집니다.

반대로 왼쪽 키를 누르면 direction.x 값은 -1이 됩니다. 이때 조건식은 거짓(false)이 되므로 flipX가 꺼집니다.

즉, 원본 스프라이트가 왼쪽을 바라보고 있을 때 오른쪽을 누르면 이미지를 뒤집고(true), 왼쪽을 누르면 원래 이미지대로 보여주어(false) 자연스럽게 이동 방향을 쳐다보게 만듭니다.

2)코루틴
캐릭터가 타일맵 위를 한 칸 이동하는 순간, 스프라이트 이미지를 물리적으로 튕겨주어 통통 튀는 듯한 생동감을 주는 핵심 연출입니다. 시간차를 두고 빠르게 일어나는 3단계 과정으로 진행됩니다.

준비 단계: 플레이어 본체의 실제 좌표 이동에 방해를 주지 않기 위해서, 이동은 본체가 조용히 처리하게 두고 오직 겉껍데기 이미지(자식 오브젝트)의 위치와 회전 정보만 따로 가져와서 만집니다.

1단계 (기울기 각도 정하기): 움직이는 방향에 맞춰 몸을 자연스럽게 눕히기 위한 회전값을 미리 정합니다. 오른쪽으로 갈 때는 시계 방향으로 살짝 몸을 눕히고, 왼쪽으로 갈 때는 반시계 방향으로 몸을 기울입니다. 위아래로 이동할 때도 심심하지 않도록 기본적으로 몸이 갸우뚱하도록 설정해 둡니다.

2단계 (공중 부양과 회전): 이동이 시작되는 순간, 캐릭터 이미지를 위쪽 방향으로 가볍게 들어 올림과 동시에 1단계에서 계산해 둔 각도로 몸을 기울입니다. 이 자세를 약 0.06초라는 아주 찰나의 시간 동안 유지하여 유저에게 "점프하는 느낌"을 즉각적으로 전달합니다.

3단계 (착지와 원위치): 짧은 공중 동작이 끝나면, 들어 올렸던 이미지를 다시 정중앙 제자리로 뚝 떨어트리고 갸우뚱했던 몸도 똑바로 세운 뒤 약 0.1초 동안 대기합니다.

이렇게 오늘은 랜덤 인카운터와 이동 애니메이션을 만들어보았습니다!
다음에는 인카운터가 발생해서 전투로 들어가는 부분을 만들어보겠습니다.

profile
cnu_cse

0개의 댓글