난이도 조정
private Fruit RandomRequest()
{
// 기본적으로 요청할 수 있는 최소 과일 (토마토)
int baseRequestCount = 3;
// completeCount가 3번 증가할 때마다 요청할 수 있는 과일 인덱스 증가
int increaseCount = Mathf.FloorToInt(NPCManager.Instance.completeCount / 3);
// 요청 가능한 과일의 최대 인덱스 계산 (과일 목록 초과하지 않도록 제한)
int maxRequestIndex = Mathf.Min(FruitManager.Instance.FruitList.Count,
baseRequestCount + increaseCount);
// baseRequestcount부터 maxRequestIndex 사이에서 랜덤 과일 선택
return FruitManager.Instance.FruitList[Random.Range(baseRequestCount, maxRequestIndex + 1)];
}
기존에는 게임을 시작하자마자 가장 높은 등급의 과일(ex. 수박)이 NPC의 첫 번째 요청으로 등장할 수도 있었다.
하지만 난이도를 조절하기 위해, NPC가 요청하는 과일의 등급이 점진적으로 상승하도록 변경했다.
NPCManager에서 과일 요청을 완료할 때마다 completeCount를 증가시키고,
이를 기반으로 요청 가능한 과일의 최대 레벨을 결정하도록 했다.
이제 게임 초반에는 낮은 등급의 과일만 등장하고,
게임이 진행될수록 점점 더 높은 등급의 과일이 등장하도록 조정하였다.
또한 if 문을 사용하는 것보다 Mathf 함수를 사용하는 것이 메모리 측면에서 더 효율적이라고 하여,
Mathf.Min 함수를 사용하여 과일 목록을 초과하는 인덱스가 나오지 않도록 처리했다.
물리 엔진 수정
현재 과일의 낙하 속도와 무게감을 적절하게 설정되어 있지만,
과일끼리 붙어 있는 현상이나 충돌 시 과도한 떨림 현상이 발생했다.
Rigidbody 2D에서 Linear Drag(선형 저항)을 0.5로 설정하여 공기 저항을 적절히 적용하고,
Angular Drag(회전 저항)을 5로 증가시켜 회전 시 과도한 떨림을 방지했다.
또한 Interpolate 옵션을 활성화하여 물리 엔진이 오브젝트의 움직임을 부드럽게 처리하도록 설정했다.
로딩 화면
대부분의 게임들은 시작 전에 로딩 화면이 나온다.
로딩 화면이 없고 게임이 멈춘 것처럼 보이면 사용자에게 부정적인 경험을 줄 수 있기 때문이다.
SceneManager.LoadSceneAsync(string sceneName)을 사용하면, 비동기적으로 씬을 로드할 수 있다.
이 함수는 AsyncOperation 객체를 반환하며, 로딩 진행도를 확인할 수 있는 변수를 제공한다.
AsyncOperation 객체에 제공하는 변수의 목록은 아래과 같다.
변수 | 설명 |
bool allowSceneActivation | 씬이 100% 로드되는 즉시 장면을 활성화시킬 것인지 허용 여부 (기본값 true) |
bool isDone | 씬 로딩이 완료 되었는지 여부 |
float progress | 로딩 진행도를 0~1 사이의 값으로 제공 |
private IEnumerator LoadSceneAsync(string sceneName)
{
yield return new WaitForSeconds(1f); // 1초 대기
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
operation.allowSceneActivation = false; // 100% 전환될 때까지 씬 전환 방지
while (!operation.isDone)
{
if (operation.progress >= 0.9f)
{
yield return new WaitForSeconds(1f); // 1초 대기 후 씬 전환
operation.allowSceneActivation = true;
}
}
yield return null;
}
SceneManager.LoadScene(string sceneName)을 사용하여 동기적으로 씬을 로드할 수 있지만,
이 방식은 로딩이 완료될 때까지 게임이 멈춘 것처럼 보인다.
반면 LoadSceneAsync를 사용하면 로딩과 동시에 다른 작업도 수행할 수 있다.
현재 게임은 가볍기 때문에 로딩 시간이 거의 없지만, 일단 구현해보았다.
private string baseText = "과일 가게 오픈 준비중"; // 고정 텍스트
private int dotCount = 0; // 점 개수
private void Start()
{
// AnimateTyping 함수를 0초 후 시작하고, 이후 0.5초마다 반복 실행
InvokeRepeating(nameof(AnimateTyping), 0f, 0.5f);
}
private void AnimateTyping()
{
// dotCount를 0~3 사이에서 반복 (0, 1, 2, 3 -> 다시 0)
dotCount = (dotCount + 1) % 4;
// 점 개수에 따라 로딩 메세지를 변경하여 출력
loadingText.text = baseText + new string('.', dotCount);
}
InvokeRepeating 함수를 사용하여 AnimateTyping 함수가 0.5초마다 호출되도록 했다.
이렇게 하면 "과일 가게 오픈 준비중" 이라는 텍스트 뒤에 점(.)이 하나씩 추가되었다가 다시 초기화되는 효과가 나타난다.
애니메이션 효과를 주어 로딩 중이라는 느낌을 주었다.
메인 메뉴
메인 메뉴는 심플하게 구성했다.
현재 레벨과 보유 골드량 표시, 플레이 버튼, 업그레이드 버튼이다.
추후 설정 메뉴나 상점 버튼을 추가할 예정이다.
업그레이드 패널에서 리스트 형식의 UI를 구현하기 위해 Scroll Rect 컴포넌트를 활용했다.
1. 패널 이미지에 Scroll Rect 추가
- Horizontal 체크 해제 (세로 스크롤 전용)
- Scrollbar 이미지는 따로 추가하지 않음
2. Viewport에 Rect Mask 2D 추가
- 특정 영역까지만 리스트가 보이도록 설정
3. Content에 vertical Layout Group 추가
- 패딩 값을 조정하여 정렬
- Child Force Expand 옵션 해제하여 자식 오브젝트 크기 자동 조정 방지
'유니티' 카테고리의 다른 글
[유니티] #3 수박 게임 만들기 (사운드, 애니메이션, 이펙트) (0) | 2025.03.04 |
---|---|
[유니티] #2 수박 게임 만들기 (UI) (0) | 2025.02.26 |
[유니티] 게임 재화 저장하는 방법 : PlayerPrefs + XOR 연산, JSON + AES-256 (0) | 2025.02.25 |
[유니티] C#에서 여러 값을 반환하는 방법 : out, Tuple (0) | 2025.02.24 |
[유니티] #1 수박 게임 만들기 (최적화) (0) | 2025.02.15 |