[Unity/TIL] 2D TopDown Shooting 게임 제작
2D TopDown Shooting
2D TopDown뷰의 간단한 Shooting 게임을 제작했다. 새롭게 배운 것들을 위주로 기록해보았다.
코드 전체
https://github.com/yndoo/TopDownProject
타일맵
주요 구성 요소 : Tile, Tilemap, Grid
타일맵을 만들면서 Floor, BackDesign, ForeDesign, Collision 모두 따로 그려줬다. Layer에 차이가 있고, Collision은 콜리전 영역 자체가 되어야 하기 때문이다.
애니메이션 파라미터 가져오고 쓸 때 문자열로 비교하는 것보다 숫자로 비교하는 것이 좋으니까 StringToHash를 사용해서 숫자로 사용. 고유한 숫자로 변환해서 사용하는 것임. 아예 Animator에서 제공하는 기능이네!
private static readonly int IsMoving = Animator.StringToHash("IsMove");
private static readonly int IsDamage = Animator.StringToHash("IsDamage");
파티클
파티클!! 그 중에 플레이어 발먼지!!!
이때 Animator와 Particle 재생시키는 함수 있는 스크립트가 같은 곳에 있어야 한다.
public class DustParticleControl : MonoBehaviour
{
[SerializeField] private bool createDustOnWalk = true;
[SerializeField] private ParticleSystem dustParticleSystem;
public void CreateDustParticle()
{
if (createDustOnWalk)
{
dustParticleSystem.Stop();
dustParticleSystem.Play();
}
}
}
발사체 파티클에는 Collision도 설정해줬음. 그럼 다다닥 떨어지는 듯한 느낌이 추가 된다.
옵션이 엄청 많다. 여러 옵션들 건드려보며 원하는 느낌 내서 사용하면 될 것 같다!
코루틴
유니티의 차별점이자 장점이라고 들은 코루틴을 드디어 배웠다.
코루틴은 시간 기반 작업이나 비동기적 작업을 처리하기 위해 사용되는 메서드이다. 일반적인 함수와 달리, 코루틴은 실행을 중단하고 나중에 그부분부터 다시 실행을 재개할 수 있다.
특징
- 1. 비동기적 작업 : 프레임 단위로 나뉘어 실행되므로, 한 프레임에 모든 작업을 처리하지 않아도 됨. 게임이 멈추지 않고 연속적으로 작동할 수 있음.
- 2. yield 키워드를 사용 : yield return을 통해 특정 조건이나 시간을 기다렸다가 작업을 재개할 수 있음.
yield return 종류도 한 번 글로 정리해야 겠다..!
UI 기본 렌더링 규칙 :
- 유니티의 UI는 Canvas를 기준으로 렌더링 된다.
- Hierarchy 상위 요소 -> 하위 요소 순서로 그려진다. 동일 부모 아래에서는 위쪽에 있는 항목이 먼저 렌더링된다.
=> 밑에 있을수록 더 위에 덮어 그려지는 것. - UI의 렌더링 순서를 스크립트로 제어하려면 Transform.SetSiblingIndex를 사용.
- Canvas를 여러 개 두고 Canvas 간의 렌더링 순서를 제어할 수도 있다 : Sort Order를 설정.
입력을 Input System으로 업그레이드
InputAction 만들기
플레이어에 PlayerInput 컴포넌트 추가하고 컴포넌트에 Actions에 우리가 만든 인풋액션 넣어주기
void OnMove(InputValue inputValue)
{
movementDirection = inputValue.Get<Vector2>();
movementDirection = movementDirection.normalized;
}
void OnLook(InputValue inputValue)
{
Vector2 mousePosition = inputValue.Get<Vector2>();
Vector2 worldPos = camera.ScreenToWorldPoint(mousePosition); // 화면상 좌표를 우리가 원하는 월드좌표로 변환
lookDirection = (worldPos - (Vector2)transform.position);
if (lookDirection.magnitude/*벡터의 크기*/ < 0.9f)
{
lookDirection = Vector2.zero;
}
else
{
lookDirection = lookDirection.normalized;
}
}
void OnFire(InputValue inputValue)
{
if (EventSystem.current.IsPointerOverGameObject()) return; // UI에 마우스가 올라가있으면 공격체 쏘지 않게.
isAttacking = inputValue.isPressed;
}