지우너
[Unity 3D Run] 게임 오버 UI(1) 본문
3.14는 게임 오버, 게임 클리어 등을 이미지 에셋으로 넣으려고 했다. 그런데 찾는 데에도 시간이 좀 걸리는 것 같았고, 시간은 계속 쓰는데 진도는 안 나가니까 조금 지쳤던 거 같다.
3.15와 3.16은 UI를 만들었는데, 점점 게임다워지는 모습이 뿌듯하면서도 난이도가 점점 올라가는 것 같아서 재미있음과 재미없음을 동시에 느꼈다... UI가 오브젝트 뒤에 보이는 현상만 해결하더라도 좀 나을 것 같은데 어떻게 해결해야할지 감이 안 잡힌다...
03.14
유니티 2D 게임제작, STUDIO SHIN 지음, 제이펍(2022)
p125. 이미지 UI 추가하기
계층 뷰의 + → UI → Image를 선택
계층 뷰에서 canvas 컴포넌트의 Render Mode 값을 ‘Screen Space-Camera’로 변경
Render Camera에 설정된 카메라의 범위 안에 Canvas를 담는다는 의미
‘Screen Space-Camera’로 설정하면 Order in Layer를 설정할 수 있게 된다.
UI가 반드시 맨 위에 올 수 있도록 가능한 큰 숫자를 설정한다.
계층 뷰의 Canvas를 선택한 상태에서 인스펙터 뷰에서 Render Camera의 입력 필드에 Main Camera를 드래그 앤 드롭 한다.
Canvas의 크기가 카메라의 영역 안에 들어온다.
03.15-03.16
전에 썼던 GameOver 스프라이트를 찾기 귀찮아서 그냥 텍스트로 넣었다.
나쁘지 않은 것 같기도 하고, UI가 들어가니까 이제야 뭔가 좀 게임같아진 느낌이다.
스테이지를 클리어 못했으면 재시작(RESTART)/단계 설정 씬(QUIT)으로 이동하는 버튼이 필요하다
계층 뷰의 + → UI → Legacy → Button 선택
패널로 UI를 묶어준다.
Canvas를 선택한 상태에서 +→UI→ Panel
Panel의 크기를 조정한 후 두 개의 버튼을 Panel의 자식으로 만든다.
Panel의 Color에 들어가 불투명도 a를 0으로 설정해준다(투명하게 만들기)
Canvas의 Order In Layer를 20으로 설정했는데 왜 다른 오브젝트 뒤에 표시 되는지 모르겠다.
Unity) 유니티에서 배경 뒤로 빼기, 오브젝트가 배경에 묻혀서 안 보일 때!
Canvas의 Layer는 UI이고, 다른 Player, Plane, Cube 오브젝트의 Layer는 Default이다. 아마 그래서 UI가 뒤에 배치되는 것 같다.Sorting Layer에 UI를 만들어 Default위에 표시되도록 만들고, 설정해줬는데도 문제가 해결되지 않았다.
GameManager 스크립트 만들기
GameManager를 Canvas에 어태치하기
Text를 안 보이게 만들었다가, GameOver 혹은 Game Clear했을 때 해당 문자로 표시되게 만들고 싶었다.
맨 처음 Text로 GameOver를 만들었다. 컴포넌트를 보니까 뭔가 .text로 접근할 수 있을 것 같다는 생각이 들었다. 그래서 그것을 이용하여 GameOver라는 텍스트를 Game Clear로 바꿀 수 있을 것 같다고 생각했다. 그런데 Text로 변수를 선언하니까 SetActive()를 사용할 수 없었다.
Text를 SetActive하는 방법을 생각해보다가 유니티 공식 문서에서 정답을 찾았다.
Scripting API: UI.Text.text - Unity - Manual
GameObject로 GameState를 선언해서 Hierarchy에 텍스트 오브젝트를 넣어준다.
그리고 private Text text를 선언해서 GetComponent<Text>()로 GameState의 Text에 접근한다.
그러면 GameState.SetActive(false);도 사용할 수 있고, 내가 원하던 text.text = "Game Clear!";를 이용하여 text 내용을 상황에 따라 바꾸는 것도 가능해진다.
// GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI를 사용할 때 필p
public class GameManager : MonoBehaviour
{
public GameObject GameState;// 게임 상태를 표시하는 오브젝트
private Text text; // GameOver!/GameClear!를 표시
public GameObject panel; // 패널
public GameObject RestartButton;
public GameObject QuitButton;
// Start is called before the first frame update
void Start()
{
text = GameState.GetComponent<Text>();
panel.SetActive(false); // 패널숨기기
GameState.SetActive(false); // 텍스트 숨기ㅑ
}
// Update is called once per frame
void Update()
{
// 게임 클리어시 텍스트 바꾸고 패널, 텍스트 보이기
// text.text = "Game Clear!";
// panel.SetActive(true);
// GameState.SetActive(true);
// 게임 오버시 패널, 텍스트 보이기
// panel.SetActive(true);
// GameState.SetActive(true);
}
}
근데 게임 클리어, 게임 오버를 어떻게 GameManager에게 알릴 수 있을지 고민이다.
일단 게임 중, 게임 클리어, 게임 오버 상태를 저장하기 위해 Player 스크립트의 코드를 살짝 수정했다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// GetComponent<PlayerController>()는 PlayerController와 Player 스크립트가 같은 오브젝트에 붙어 있는걸 전제로 한다.
// [RequireComponent(typeof(PlayerController))] 코드를 적어줘서 이 부분이 에러를 내지 않게 됨.
[RequireComponent(typeof(PlayerController))]
public class Player : MonoBehaviour
{
public enum State { playing, gameclear, gameover };
State currentState;
public float moveSpeed = 3.0f;
protected bool dead;
// moveVelocity를 다른 스크립트인 PlayerController로 전달해서 물리적인 부분들을 처리할 수 있도록 할 것
// 그래서 PlayerController에 대한 레퍼런스를 가져와야합니다.
PlayerController controller;
void Start()
{
currentState = State.playing;
}
void Awake()
{
controller = GetComponent<PlayerController>();
}
void Update()
{
if (currentState==State.playing)
{
// Movement input 플레이어의 움직임을 입력 받는 것
// 수평(Horizontal) 과 수직(Vertical) 방향에 대한 입력을 받고 싶으니
// Input. 을 적고 GetAxis()를 호출해서 "Horizontal"을 넣습니다.
// y값은 내버려 둬도 되며(0), 일정한 속도로 앞으로 가도록 moveSpeed를 넣어줬다.
Vector3 moveInput = new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed, 0, moveSpeed);
// 입력 받은 값을 방향으로 변환하고 움직임 속도를 곱할 겁니다.
// 입력의 방향을 얻기 위해 moveInput를 정규화(nomalized)하여 가져옵니다 (nomarlized는 방향을 가리키는 단위벡터로 만드는 연산)
// 거기에 moveSpeed를 곱해줍니다
Vector3 moveVelocity = moveInput.normalized * moveSpeed;
// controller에게 velocity값을 넘겨줌
controller.Move(moveVelocity);
}
}
public void Die()
{
dead = true;
currentState = State.gameover;
GameObject.Destroy(gameObject);
}
}
게임 클리어는 도착지점 게임 오브젝트를 만들어 거기에 닿으면 게임 클리어가 되도록 만들면 될 것 같기는 한데, 뭔가 스크립트들을 연결하는 작업이 어려울 것 같다...ㅠㅠ
'Project' 카테고리의 다른 글
[Unity 3D Run] 게임오버/클리어 UI (3) (1) | 2023.03.25 |
---|---|
[Unity 3D Run] 게임오버 UI (2) 공부+약간 수정 (0) | 2023.03.21 |
[Unity 3D Run] 장애물 충돌 설정 (0) | 2023.03.13 |
[Unity 3D Run] 캐릭터 이동 코드 수정, 카메라 추적 (0) | 2023.03.12 |
[Unity 3D Run] 03.05-03.09 계획, 캐릭터 이동 구현 (0) | 2023.03.09 |