호우동의 개발일지

Today :

article thumbnail

구현 목표

비숍 보스에 텔레포트 패턴을 추가하려고 한다.
텔레포트 패턴은 뿅 하고 사라진 후
플레이어의 머리 위에서 나타나는 패턴이다.

구현할 그림
그림은 아무리 그려도 늘지가 않는다..

구현을 2가지 항목으로 세분화하였다.

1. 텔레포트 액션 애니메이팅

보스의 텔레포트 애니메이션을 제작하고,
이펙트를 추가하여 이동할 때 텔레포트 하는 느낌이 나도록 할 것이다.

2. 텔레포트 스크립트 구현

만든 애니메이션을 토대로 코드를 작성하여
실제로 보스에게 패턴을 적용시킨다.

 

 


구현 과정


1. 텔레포트 애니메이션 만들기

애니메이션 스크린샷

우선 Bishop 프리팹을 이동해서 Create New Clip으로 Bishop_Teleport라는
이름으로 새로운 애니메이션을 만들어준다.

간단하게 스케일 조정으로 텔레포트 효과를 만들었다.

애니메이터 스크린샷

Animation에서 녹화버튼을 누르고
원하는 시간대에 모델의 동작이나 변형을 넣으면

유니티 내부에서 그 사이 시간대에 자연스러운 프레임을 넣어준다.

Add Property를 누르고,
Transfrom -> Scale을 눌러 크기를 조정한다.

조정

0초에는 기존의 크기인 (4,4,4)로 초기화해 준다.

애니메이터 조정

0.15초에는 스케일을 (0,6,0)으로
납작해지면서 위로 늘어지는 효과를 주도록 하였다.

이런 식으로 구성하면
0 ~ 0.15초 사이에는 유니티 자체에서 자연스럽게 애니메이션 채워준다.

조정

마무리로 다시 처음의 상태로 돌리는데,
여기서 충돌이 되지 않고, 보이지 않는 상태로 만들어둔다.

애니메이션에서 다른 컴포넌트 또한 제어가 가능하다.
Add Property를 통해 Mesh Collider와 Mesh Renderer을 가지고 온다.

그리고 사라지는 순간에는 충돌과 형체가 사라지게 만든다.

위와 같은 작업을 해주는 이유는
충돌과 transform의 물리작용으로 생기는 에러 때문이다.

이 작업 없이 코드를 짜니까 자꾸만 에러가 떠서
콜라이더를 꺼주는 애니메이션 작업을 만들었다.

loop Time 체크

그리고 이 애니메이션은 한 번만 동작되면 되니까 Loop Time 체크를 해제한다.
완성된 애니메이션 이렇게 된다.

완성

나름대로 순간이동하는 느낌이 난다.
이제 애니메이터를 연결해야 한다.

애니메이션 연결

Bool형인 파라미터 Teleport를 만들어준다.
이후 Bishop_Idle과 Bishop_Teleport 애니메이션을 연결해 준다.

인스펙터 창

Bishop_Teleport로 갈 때는 Teleport가 true로 바뀌어야 한다.
반대는 당연히 Teleport가 false여야 한다.

 


2. 텔레포트 스크립트 작성

Boss_Bishop.cs

private const float TELEPORT_SPEED = 0.2f;

// 텔레포트 위치 체크 및 코루틴 호출
private void Teleport()
{
    Vector3Int point = ConvertCellPos(target.position);
    if (!CheckCanMove(point) && target != null) return;

    StartCoroutine(TeleportAction(point));
}

// 실질적인 텔레포트 액션
private IEnumerator TeleportAction(Vector3Int point)
{
    bossState = BossState.attack;
    MeshCollider colli = mesh.GetComponent<MeshCollider>();

    anim.SetBool("Teleport", true);
    yield return new WaitForSeconds(TELEPORT_SPEED);

    // 애니메이션으로 꺼져있던 충돌과 mesh를 다시 true
    colli.enabled = true;
    mesh.enabled = true;
    anim.SetBool("Teleport", false);

    // 플레이어 위로 이동
    transform.position = point + Vector3.up * 5;

    // 액션 종료 상태 변환
    bossState = BossState.idle;
    Invoke("OnAction", actionDelay);
}

스크립트는 Teleport 함수와 TeleportAction이라는 코루틴 두 개로 나눴다.

Teleport는 이동할 위치를 체크하는데 해당 위치가 이동이 가능한 위치인지를 체크한다.
타깃이 없거나, 이동이 불가능한 곳이라면 코루틴을 호출하지 않는다.

TeleportAction은 Teleport에서 건네준 위치를 이용한다.

먼저 패턴을 시작했으므로 공격상태로 만들고
위에서 만들어둔 Teleport 애니메이션을 True로 하여 애니메이션을 작동시키게 한다.


Teleport 애니메이션의 loop를 꺼놨기 때문에 한 번만 동작한다.

yield return new WaitForseconds(TELEPORT_SPEED);
를 통해 설정한 시간만큼 기다린 후 사라졌다가 나타난다.

Teleport 애니메이션이 끝나면 충돌과 Mesh가 꺼진 상태이기 때문에
다시 true로 바꿔주고 애니메이션을 꺼준다.


그리고 위치이동을 해주는데 당연히 플레이어의 위치보다 조금 높은 곳으로 설정해 둔다.
이러면 패턴 종료.

상태를 평상시로 돌려주고 다시 OnAction을 호출하여 다른 패턴을 호출하도록 한다.

 


3. 이펙트(파티클) 추가

아무래도 그냥 이동하는 거는 그래도 좀 심심해서 이펙트 효과를 추가해야 할 것 같다.
무료 에셋 중에 어울리는 것을 찾아보던 중 적당하는 거를 찾았다.
이를 이용해서 텔레포트를 좀 더 있어 보이게 하겠다.

하위 오브젝트 설정

파티클을 보스의 하위 오브젝트로 만들어준다.
그리고 아까 Boss_Bishop.cs에

[SerializeField] ParticleSystem teleportEffect; // 파티클 시스템 추가
private const float TELEPORT_SPEED = 0.2f;

// 텔레포트 위치 체크 및 코루틴 호출
private void Teleport()
{
    Vector3Int point = ConvertCellPos(target.position);
    if (!CheckCanMove(point) && target != null) return;

    StartCoroutine(TeleportAction(point));
}

// 실질적인 텔레포트 액션
private IEnumerator TeleportAction(Vector3Int point)
{
    bossState = BossState.attack;
    MeshCollider colli = mesh.GetComponent<MeshCollider>();

    anim.SetBool("Teleport", true);
    yield return new WaitForSeconds(TELEPORT_SPEED);

    // 애니메이션으로 꺼져있던 충돌과 mesh를 다시 true
    colli.enabled = true;
    mesh.enabled = true;
    anim.SetBool("Teleport", false);

    // 플레이어 위로 이동
    transform.position = point + Vector3.up * 5;
    teleportEffect.Play(); // 이펙트 효과 플레이

    // 액션 종료 상태 변환
    bossState = BossState.idle;
    Invoke("OnAction", actionDelay);
}

기존 코드에 파티클 코드를 추가하여
보스가 나타날 때 이펙트 효과가 나오도록 하였다.

 

 


구현 결과

구현 결과

음 나름 이펙트도 잘 나오고 만족스럽게 뽑힌 것 같다.