이제 게임의 코어 매커니즘은 모두 작업이 완료되었다. 하지만 여기서 마무리하기 보다는, 게임의 완성도를 위해 약간의 작업을 더 진행해 본다.
FinishLine에 사용했던 particle system을 이용해 보드가 지면에 맞닿아있을 때 눈이 휘날리는 듯한 이펙트를 설정하여 시각적인 피드백을 강화하고, 공중에서 회전 중 캐릭터의 머리가 바닥과 충돌할 경우 게임이 종료되는 처리를 추가하여 약간의 난이도를 설정할 예정이다.
우선, 이펙트부터 작업해준다. Slide Effect라는 이름으로 particle system을 생성하여 캐릭터 오브젝트의 자식 오브젝트로 추가했다. 해당 이펙트는 도착지점에 사용했던 이펙트와 기본적으로 비슷하지만, 원뿔형으로 설정하고 이펙트 색상도 배경과 조화롭게 바꿔서 만들어 보았다.
이렇게만 둘 경우 캐릭터가 공중에 떠 있을 때도 이펙트가 계속해서 출력되어 다소 부자연스럽기 때문에, 땅에 닿아있을 때만 이펙트가 출력되도록 코드 작업을 진행해 준다.
DustTrail이라는 이름으로 스크립트를 생성해주고, 플레이어 오브젝트의 컴포넌트로 추가해 준 뒤 아래와 같이 코드를 작성했다.
// 이펙트 변수 직렬화하여 선언
[SerializeField] ParticleSystem particleSys;
// 지면과 충돌 시 동작해야하므로 OnCollision 메소드 사용
void OnCollisionEnter2D(Collision2D other)
{
// 충돌한 오브젝트의 태그가 "Ground"일 경우 이펙트 출력
if (other.gameObject.tag == "Ground")
particleSys.Play();
}
// 충돌 상태에서 벗어날 경우 동작을 멈추므로 OnCollisionExit 메소드 사용
void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.tag == "Ground")
particleSys.Stop();
}
이제, 플레이어 머리가 지면과 충돌할 경우 효과음을 재생하고 레벨을 재시작하는 코드 작업을 추가한다.
CrashDetector라는 이름의 스크립트를 생성해주고, 마찬가지로 플레이어 오브젝트의 컴포넌트로 추가해 준다.
이 스크립트의 경우 앞서 작성했던 FinishLine 스크립트와 작동 방식이 거의 동일하다.
// 씬 리로드를 해야하므로 SceneManagement 사용
using UnityEngine.SceneManagement;
// 씬 리로드에 걸리는 딜레이 변수 선언 및 초기화
[SerializeField] float LoadTime = 0.5f;
// 효과음 변수 설정을 위해 직렬화하여 선언
[SerializeField] AudioClip crashSFX;
// 충돌 여부 확인을 위한 boolean값 선언 및 초기화
bool hasCrashed = false;
void OnTriggerEnter2D(Collider2D other)
{
// 플레이어가 충돌 상태가 아닐 때 지면과 충돌 시
if (other.tag == "Ground" && !hasCrashed)
{
// 충돌 상태로 변경
hasCrashed = true;
// 플레이어 동작 중지(PlayerController 스크립트 비활성화)
FindObjectOfType<PlayerController>().DisableControls();
// 효과음 재생
GetComponent<AudioSource>().PlayOneShot(crashSFX);
// 딜레이 후 씬 리로드
Invoke("ReloadScene", LoadTime);
}
}
void ReloadScene()
{
SceneManager.LoadScene(0);
}
이렇게 모든 코드작업을 마쳤고, 게임이 아래와 같이 잘 완성되었다.