-
내일배움캠프 20일차 TIL - 스파르타타운 게임 제작TIL/Unity 2024. 5. 13. 20:04
[학습목표]
유니티를 이용하여 ZEP과 유사한 시점의 탑뷰 게임을 제작하고 주차 개인 과제를 제출한다.
[학습내용]
이번 과제에서 구현해야 할 요구사항들은 다음과 같다.
필수
- 캐릭터 만들기
- 캐릭터 이동
- 방 만들기 (맵)
- 카메라 따라가기
- 캐릭터 애니메이션 추가
- 이름 입력 시스템
- 캐릭터 선택 시스템
선택
- 시간 표시
- 인게임에서 이름 변경
- 참석 인원 UI
- 인게임에서 캐릭터 변경
- NPC 대화
캐릭터 만들기
플레이어 캐릭터를 생성해주었다. 에셋 링크
Player 오브젝트 아래에 CharacterSprite 오브젝트를 만들어서 스프라이트를 배치해주었다.
캐릭터 이동
캐릭터를 이동시키기 위해서 먼저 패키지 매니저에서 Input System을 설치해주었다.
그 다음 Input Action을 하나 생성하여 작성해주었다.
마우스 위치에 따라서 캐릭터를 뒤집어야 하기 때문에 마우스도 입력으로 잡아주었다.
그 다음 입력과 이동 관련 스크립트를 작성해주었다.
using System; using UnityEngine; public class InputController : MonoBehaviour { public event Action<Vector2> OnMoveEvent; // 키보드 입력 시 이동 public event Action<Vector2> OnLookEvent; // 마우스 위치로 캐릭터 시점 public void CallMoveEvent(Vector2 direction) { OnMoveEvent?.Invoke(direction); } public void CallLookEvent(Vector2 direction) { OnLookEvent?.Invoke(direction); } }
InputController.cs
using UnityEngine; using UnityEngine.InputSystem; public class PlayerInputController : InputController { private Camera camera; private void Awake() { camera = Camera.main; } // 캐릭터 이동 public void OnMove(InputValue inputValue) { CallMoveEvent(inputValue.Get<Vector2>().normalized); } // 캐릭터 시점 public void OnLook(InputValue inputValue) { Vector2 mouseWorldPosition = camera.ScreenToWorldPoint(inputValue.Get<Vector2>()); Vector2 playerLookPosition = (mouseWorldPosition - (Vector2)transform.position).normalized; if(playerLookPosition.magnitude > .9f) { CallLookEvent(playerLookPosition); } } }
PlayerInputController.cs
using UnityEngine; public class MoveObject : MonoBehaviour { private InputController inputController; private Rigidbody2D rigidbody; private Vector2 moveDirection = Vector2.zero; private void Awake() { inputController = GetComponent<InputController>(); rigidbody = GetComponent<Rigidbody2D>(); } private void Start() { inputController.OnMoveEvent += SetMoveDirection; } private void FixedUpdate() { Move(moveDirection); } private void SetMoveDirection(Vector2 direction) { moveDirection = direction; } private void Move(Vector2 direction) { direction *= 5; rigidbody.velocity = direction; } }
MoveObejct.cs
using UnityEngine; public class FilpObject : MonoBehaviour { private InputController inputController; private SpriteRenderer spriteRenderer; private void Awake() { inputController = GetComponentInParent<InputController>(); spriteRenderer = GetComponent<SpriteRenderer>(); } private void Start() { inputController.OnLookEvent += Flip; } private void Flip(Vector2 direction) { spriteRenderer.flipX = Mathf.Abs(Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg) > 90f; } }
FlipObject.cs
그리고 Player 컴포넌트와 하위 스프라이트에 스크립트를 배치해주었다.
방 만들기 (맵)
타일맵을 구성된 맵을 제작해 주었다. 에셋 링크
먼저 타일맵을 제작해준다.
그러면 하이어라키에 그리드가 자동 생성된다. 하위에 바닥과 벽 타일맵을 나누어 따로 그려준다.
벽 타일맵은 따로 Order In Layer를 올려주고, 타일맵 콜라이더 2d 컴포넌트를 붙여준다. 캐릭터가 통과하지 못하게 하기 위해서다.
캐릭터가 충돌하려면 캐릭터에게도 물리 컴포넌트를 달아줘야 한다.
카메라 따라가기
이건 따로 강의에서 배운 내용이 아니기 때문에, 직감적으로 했다. 카메라를 새로 추가해줄까 고민했으나, 게임 구성 상 카메라가 여러 개일 이유가 없을 거 같아서 그냥 메인 카메라를 플레이어 캐릭터에 부착해주었다.
캐릭터 애니메이션 추가
플레이어 캐릭터 오브젝트 하위 스프라이트 오브젝트에 애니메이터 컴포넌트와 애니메이션 스크립트를 넣어주었다.
그리고 애니메이터를 구성해주었는데, 요구하는 사항이 걸을 때 애니메이션이었기 때문에 Bool값 IsWalking을 만들어주고, 캐릭터가 일정 속도 이상일 때 true가 되도록 코드를 짜주었다.
using UnityEngine; public class AnimationController : MonoBehaviour { protected Animator animator; protected InputController inputController; protected virtual void Awake() { animator = GetComponent<Animator>(); inputController = GetComponentInParent<InputController>(); } }
AnimationController.cs
using UnityEngine; public class CharacterAnimationController : AnimationController { private static readonly int IsWalking = Animator.StringToHash("IsWalking"); private readonly float magnitudeThreshold = 0.5f; protected override void Awake() { base.Awake(); } private void Start() { inputController.OnMoveEvent += MoveAnimation; } private void MoveAnimation(Vector2 direction) { animator.SetBool(IsWalking, direction.magnitude > magnitudeThreshold); } }
CharacterAnimationController.cs
이름 입력 시스템
이름을 입력받고 캐릭터 머리 위에 띄워야 한다. 처음에 새로운 씬을 만들어서 구현할까 고민하였으나, 씬을 만들 정도의 기능은 아닌 거 같아서 기존 화면에서 UI만 띄우는 방식으로 했다.
그래서 UI를 먼저 구성해줬다.
그 다음 캐릭터 머리 위에 이름 UI를 달아주었다.
UI를 많이 다뤄보지 않아서 캐릭터 오브젝트에 다는 법을 찾아야 했다. 구글에 검색해보니 캔버스의 Render Mode를 World Space로 바꿔야 한다고 한다.
이름도 만들었으니, UI에 있는 Join 버튼에 기능을 달아줬다. 클릭 시 InputField의 값을 받아서 캐릭터 이름을 변경해주는 스크립트를 작성하였다.
// UI 버튼으로 호출 public void Join() { if (nameInputField == null) { return; } string name = nameInputField.text; if (2 <= name.Length && name.Length <= 10) { CharacterNameText.text = name; // 이름 설정 gameObject.SetActive(false); // UI 종료 PlayerInput.enabled = true; // 캐릭터 입력 활성화 } }
UIManager.cs 중 Join()
입력 글자는 2~10 글자 사이라는 조건이 있어서 if문의 조건으로 넣었다.
플레이어 인풋은 글자 입력 도중에 캐릭터가 움직이는 것을 방지하기 위해서 비활성화 시켜놓았고, 입력이 끝나면 다시 활성화 시켜주는 식으로 구현했다.
캐릭터 선택 시스템
캐릭터를 선택하면 플레이어 캐릭터가 바뀌어야 한다.
플레이어 캐릭터를 변경하는 방법이 어려워서 일단 스프라이트만 바꾸는 식으로 진행하기로 했다. 스프라이트를 펭귄과 마법사 두 가지로 만들고 각각 애니메이터를 붙여서 서로 다른 애니메이션을 구현해줬다.
일단 하나는 비활성화 시켜놓고 플레이어가 고른 캐릭터만 활성화 시키는 방법을 사용했다.
// UI 버튼으로 호출 public void SelectCharacter(int characterSort) { this.characterSort = (CharacterSort)characterSort; SetSelectedCharacter(); // 고른 캐릭터로 변경 CharacterSelectUI.SetActive(false); // 캐릭터 선택 UI 종료 } public void SetSelectedCharacter() { switch(characterSort) { case CharacterSort.Penguin: // UI 버튼 변경 UIPenguinImage.SetActive(true); UIWizardImage.SetActive(false); // 캐릭터 스프라이트 변경 PenguinSprite.SetActive(true); WizardSprite.SetActive(false); break; case CharacterSort.Wizard: UIPenguinImage.SetActive(false); UIWizardImage.SetActive(true); PenguinSprite.SetActive(false); WizardSprite.SetActive(true); break; } }
UIManager.cs 중
지금 당장에는 구현되었으나, 후에 스킬 등을 서로 다르게 구현하기 위해서는 아예 둘을 구별해야할 거 같다. 그 방법이 마땅히 떠오르지 않아 일단은 이렇게 구현하였으나, 내일 다시 생각해서 남은 과제 제출 기한 동안 수정을 거쳐야 할 거 같다.
[결과물]
https://github.com/JNUSYJ/SpartaTown
[회고]
유니티 강의를 듣고 나니 생각보다 더 개인 과제 시간이 모자라다. 필수 요구사항은 다 구현했으나, 선택 요구사항에 도전하지 못한 게 아쉽다. 일단 오늘 구현했던 캐릭터 구현 방식을 좀 더 고민해 본 뒤, 시간이 난다면 선택 하나 쯤은 도전해볼 수 있으면 좋겠다.
'TIL > Unity' 카테고리의 다른 글
내일배움캠프 22일차 TIL - 유니티 입문 팀 프로젝트 (1) 2024.05.16 내일배움캠프 21일차 TIL - 스파르타타운 제작 마무리 (0) 2024.05.14 내일배움캠프 19일차 TIL - 2D게임 기초 개발 입문 2 (0) 2024.05.10 내일배움캠프 18일차 TIL - 2D게임 기초 개발 입문 1 (0) 2024.05.09 내일배움캠프 17일차 TIL - Pong 게임 구현 (0) 2024.05.08