열거형(enum)
관련된 값들을 그룹화하여 의미 있는 이름으로 정의하는 데이터 타입으로, 개발자가 정의한 특정한 값들만 가질 수 있도록 제한한다.
동작 방식
public enum InfoType { Exp, Level, Kill, Time, Health }
InfoType type = InfoType.Exp;
- 변수 타입은 InfoType 타입이며, 오직 Exp, Level, Kill, Time, Health 중 하나만 가질 수 있다.
- 내부적으로는 정수값으로 저장된다.
Exp → 0
Level → 1
Kill → 2
Time → 3
Health → 4
- 열거형은 기본적으로 첫 번째 항목이 0, 그다음부터 1, 2, 3 순으로 자동 할당된다.
public enum InfoType { Exp = 10, Level = 20, Kill = 30, Time = 40, Health = 50 }
- 이런 식으로 직접 값을 할당할 수도 있다.
사용하는 이유
- 가독성이 좋아짐 : "Exp" 대신 InfoType.Exp를 사용하면 코드를 쉽게 이해할 수 있음
- 오타 방지 : 문자열 "Exp" 대신 InfoType.Exp를 사용하면 잘못된 값 입력을 방지할 수 있음
- 코드 자동완성 가능 : InfoType.을 입력하면 자동완성으로 선택 가능 -> 타이핑 실수 방지
월드 좌표(World Position)와 스크린 좌표(Screen Position)
Unity에서는 게임 오브젝트와 UI의 좌표 시스템이 다르다.
따라서, 월드 좌표를 UI의 스크린 좌표로 변환해야 체력 바를 올바르게 배치할 수 있다
.
월드 좌표
- Transform.position을 사용
- 3D/2D 공간에서 오브젝트가 실제로 위치한 좌표
- 예 : Vector3(5, 2, 0) (플레이어 위치)
스크린 좌표
- UI 요소는 따로 스크린 좌표를 사용
- 화면 픽셀 단위로 측정됨
- 예 : Vector2(450, 300) (HUD 체력 바 위치)
문제점
rect.position = GameManager.instance.player.transform.position;
- 체력 바가 월드 좌표 기준으로 이동하여 엉뚱한 곳에 배치됨
- 월드 좌표 -> 스크린 좌표로의 변환이 필요
해결 방법 : WorldToScreenPoint()
rect.position = Camera.main.WorldToScreenPoint(GameManager.instance.player.transform.position);
- 이 함수는 게임 내 플레이어의 위치를 실제 화면 상의 픽셀 위치로 변환
- 월드 좌표를 UI의 스크린 좌표로 변환하여 체력 바가 정확히 플레이어 위에 위치하도록 만듦
※ .ScreenToWorldPoint() = 반대의 상황에 사용
Follow.cs
플레이어의 체력 바가 항상 플레이어를 따라다니도록 하는 역할을 한다.
플레이어의 위치가 변할 때마다 체력 바 UI가 해당 위치를 반영하도록 설정한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Follow : MonoBehaviour
{
/* RectTransform = UI 요소의 위치, 크기, 회전을 관리하는 컴포넌트
* 일반적인 Transform과 다르게 UI 전용이며, Canvas 안의 UI 요소들의 위치를 조정할 때 사용
* 체력 바가 UI로 표시되기 때문에 Transform이 아니라 RectTransform을 사용 */
RectTransform rect;
void Awake()
{
rect = GetComponent<RectTransform>();
}
// 카메라 좌표 변환을 지속적으로 수행하기 위해 FixedUpdate 사용
// 체력 바 UI가 플레이어 위치를 따라 이동
void FixedUpdate()
{
// 변환된 스크린 좌표를 체력 바의 RectTransform에 적용하여 HUD가 플레이어를 따라가도록 설정
rect.position = Camera.main.WorldToScreenPoint(GameManager.instance.player.transform.position);
}
}
HUD.cs
플레이어의 상태(경험치, 레벨, 킬 수, 남은 시간, 체력)를 UI로 표시하는 역할을 한다.
게임 화면의 상단이나 하단에 표시되는 HUD(Head-Up Display)의 핵심적인 기능을 담당한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI 관련 Component 사용 시 UnityEngine.UI 네임 스페이스 사용
// Head Up Display
public class HUD : MonoBehaviour
{
public enum InfoType { Exp, Level, Kill, Time, Health } // HUD에서 표시할 정보의 종류를 미리 정해둠
public InfoType type; // 해당 HUD UI가 어떤 정보를 화면에 표시할지를 설정
Text myText; // UI의 텍스트 요소(Level, Kill, Time 표시용)
Slider mySlider; // UI의 슬라이더 요소(Exp, Health 표시용)
void Awake()
{
myText = GetComponent<Text>(); // UI의 텍스트 요소 가져오기
mySlider = GetComponent<Slider>(); // UI의 슬라이더 요소 가져오기
}
// 연산이 완료 될 때 쯤 갱신
void LateUpdate()
{
switch (type)
{
case InfoType.Exp:
float curExp = GameManager.instance.exp; // 현재 경험치
/* Mathf.Min() = 두 개의 숫자 중 더 작은 값을 반환하는 함수
* 해당 함수를 사용하여 배열 범위를 벗어나지 않도록 방지 */
float maxExp = GameManager.instance.nextExp[Mathf.Min(GameManager.instance.level, GameManager.instance.nextExp.Length - 1)]; // 최대 경험치
mySlider.value = curExp / maxExp; // 경험치 비율을 슬라이더 값(0~1)으로 설정
break;
case InfoType.Level: // 레벨
/* string.Format = 문자열을 특정 형식으로 변환하는 함수
* .Format("포맷의 type {데이터의 인덱스 순번:포맷)", 데이터)
* F0 = 소수점 없이 정수로 표시 */
myText.text = string.Format("Lv.{0:F0}", GameManager.instance.level); // level을 가져와 HUD에 표시
break;
case InfoType.Kill: // 적 처치 수
myText.text = string.Format("{0:F0}", GameManager.instance.kill); // kill 을 가져와 HUD에 표시
break;
case InfoType.Time: // 남은 시간
float remainTime = GameManager.instance.maxGameTime - GameManager.instance.gameTime; // 남은 시간 = 전체 게임 시간 - 현재 경과 시간
// 분과 초로 분리
// .Mathf.FloorToInt = 소수점을 버리는 함수
int min = Mathf.FloorToInt(remainTime / 60); // 남은 시간을 분 단위로 변환
// A % B = A를 B로 나누고 남은 나머지
int sec = Mathf.FloorToInt(remainTime % 60); // 남은 초 계산
/* D0, D1, D2... = 서식 지정자로 정수를 특정 자리수로 출력할 때 사용
* D는 Decimal(10진수) 형식 지정자를 의미
* D0 -> 최소 0자리 (즉, 원래 값 그대로)
* D1 -> 최소 1자리 (즉, 한 자리면 그대로, 두 자리 이상이면 그대로)
* D2 -> 최소 2자리 (한 자리면 앞에 0 추가) */
// {0:D2} -> 첫 번째 숫자(분, min)를 2자리 숫자로 표시
// {1:D2} -> 두 번째 숫자(초, sec)를 2자리 숫자로 표시
myText.text = string.Format("{0:D2}:{1:D2}", min, sec); // 남은 시간을 "분:초" 형식으로 HUD에 표시
break;
case InfoType.Health: // 체력
float curHealth = GameManager.instance.health; // 현재 체력
float maxHealth = GameManager.instance.maxHealth; // 최대 체력
mySlider.value = curHealth / maxHealth; // 체력 게이지를 현재 체력 비율에 맞게 설정
break;
}
}
}
'Unity > Undead Survivor' 카테고리의 다른 글
레벨업 시스템(LevelUp System) / 손과 무기 장착 표현(Hands) / 캐릭터 선택(Character Select) (0) | 2025.03.19 |
---|---|
스크립터블 오브젝트(Scriptable Object) / 능력 업그레이드(Ability Upgrade) (0) | 2025.03.18 |
범위 감지(Scanner) / 무기(Weapon)와 총알(Bullet) (0) | 2025.03.18 |
배열과 리스트의 차이 / 오브젝트 풀링(Object Pooling) (0) | 2025.03.17 |
코루틴(Corutine) / 적 생성(Enemy, Spawn) (0) | 2025.03.13 |