목차
※ 오브젝트 풀링을 정리해주신 다른 수강생님
https://yukihirahole.tistory.com/186
[Unity] 오브젝트 풀링 (Object Pooling)
오브젝트 풀링이란?오브젝트 풀링은 객체를 반복해서 생성하고 삭제하는 대신, 미리 만들어 놓고 재사용하는 디자인 패턴이다.“필요할 때 꺼내 쓰고, 쓰지 않을 때는 돌려주는 대여 서비스라
blog.ysizuku.com
레이싱 게임 제작
25.01.23
아이디어 구상
: Figma로 구상
- 하이퍼 캐주얼 레이싱 게임
- 모바일 플랫폼
- 업적
- 리더보드
- 광고 추가
- 상점 : 광고 제거, 아이템 판매
- 세로 화면으로 제작 --> 모바일 특화, 한 손 플레이가 가능하다는 장점
Class 구분
- GameManager --> 게임 상태 처리
- Road Controller(도로 컨트롤) --> 도로 생성 및 관리(무한 맵), Gas Item 생성
- Car Controller(자동차 컨트롤) --> 이동 컨트롤, Gas
- UI Controller --> Gas 표시, 좌/우 이동 버튼
Jira와 Confluence로 일감 계획
: Jira에 'Hyper Racer' 프로젝트 생성
- 에픽 생성 : 프로토타입 개발, 안드로이드용 개발, iOS용 개발
- 스토리 생성 : 기획, 메인화면 개발, 게임 화면 개발, 게임오버 화면 개발
- 스프린트 생성
※ 스프린트는 월요일 기준으로 만드는 게 좋다
게임 흐름 구상
--> Scene 단위도 구상 (A+B로 묶어서 Scene을 제작하기로 구상)
※ Scene에 너무 많은 것을 담고 있으면 로딩하는 데에 시간이 많이 걸린다.
Unity 프로젝트 제작 후 Github와 연동
1. Unity 프로젝트 제작
2. Github에서 New repository 생성
3. Github Desktop에서 Clone repository
4. Unity Project 파일들을 복사하여 Clone한 폴더에 붙여넣기
5. Github Desktop에서 Commit & Push (커밋명 : 프로젝트 시작)
6. Push한 파일들 로컬에서 전부 삭제 후 새로 Clone (생략 가능)
7. Unity Project 원본 삭제
8. Unity Hub에서 원본 프로젝트 삭제 및 Github와 연동한 프로젝트 추가
Jira의 일감에 브랜치 연결
레이싱 게임 제작
>> Scene 생성
※ Ctrl + N, Ctrl + S
>> 빌드 세팅을 안드로이드로 변경
└ 기본 맵 생성
: Road, Car, Gas를 만들고 Prefab
1. Road
- Floor
- Wall
--> Right는 Position.x = 2
>> 추가 설정
- Road Prefab의 양 쪽 Wall에서 Box Collider를 삭제
- 부모 Object인 Road에 BoxCollider 추가 및 크기 조정
- IsTrigger 체크
- Road Controller.cs 추가
--> 원래 Center.Z가 0, Size.Z가 10이었는데, 차가 감지될 때 맵이 어색하게 사라져서 Collider의 범위를 넓힘
2. Car
>> 추가 설정
- Car model에서 BoxCollider를 삭제
- 부모 Object인 Car에 BoxCollider와 Rigidbody 추가
- 'Player' 태그 추가
- Collider 크기 조정
- 중력의 영향을 안 받도록 Is Kinematic 체크
- Car Controller.cs 추가
3. Gas
>> 부모 Object인 Gas에 'Gas' 태그 생성하여 추가
└ UI 생성
: Canvas, Gas량 표시할 Text, Button 2개 추가
1. Canvas
: 게임 해상도 조정
※ 먼저 Build Settings에서 Android로 Build
--> 기준이 되는 해상도 설정 (이후 작아진 글씨 크기 수정)
2. Text
--> 사진은 글씨 크기 수정 완료한 것
3. Button
: 원래는 투명도를 0으로 둬서 완전히 안 보이게 하는데, 지금은 보이도록 색과 투명도 설정해둠
>> 화면 비율과 상관없이 좌/우로 나뉘도록 설정
>> 추가 설정
- 버튼의 Button Component를 삭제하고 Event Trigger 추가 --> Pointer Down, Pointer Up 추가
- MoveButton.cs 추가
- 좌/우 각각 버튼에 맞게 Button 바인딩 및 함수 설정 --> Pointer Down과 Up 각각 맞게 설정
└ 코드 작성
- GameManager.cs
- CarController.cs
- RoadController.cs
- MoveButton.cs
>> GameManager.cs
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class GameManager : MonoBehaviour
{
[SerializeField] private GameObject carPrefab;
[SerializeField] private GameObject roadPrefab;
// UI 관련 코드
[SerializeField] private MoveButton leftMoveButton;
[SerializeField] private MoveButton rightMoveButton;
[SerializeField] private TMP_Text gasText;
// 자동차
private CarController _carController;
// 도로 오브젝트 풀
private Queue<GameObject> _roadPool = new();
private int _roadPoolSize = 3; // 도로가 생기는 개수 제한
// 도로 이동
private List<GameObject> _activeRoads = new();
// 상태
public enum State { Start, Play, End }
public State GameState { get; private set; } = State.Start;
// Singleton
private static GameManager _instance;
public static GameManager Instance
{
get
{
if (_instance == null)
_instance = FindObjectOfType<GameManager>();
return _instance;
}
}
private void Awake()
{
if (_instance != null && _instance != this)
Destroy(this.gameObject);
else
{
_instance = this;
}
}
private void Start()
{
// Road Object Pool 초기화
InitializeRoadPool();
// 게임 시작
StartGame();
}
private void Update()
{
// 활성화 된 도로를 아래로 서서히 이동
foreach (var activeRoad in _activeRoads)
{
activeRoad.transform.Translate(-Vector3.forward * Time.deltaTime);
}
// Gas 정보 출력
if (_carController != null)
gasText.text = _carController.Gas.ToString();
}
private void StartGame() // 게임 재시작 시, 다시 생성할 수 있게끔 따로 빼둠
{
// 도로 생성
SpawnRoad(Vector3.zero);
// 자동차 생성
_carController = Instantiate(carPrefab, new Vector3(0, 0, -3f), Quaternion.identity).GetComponent<CarController>();
// Left, Right move button에 자동차 컨트롤 기능 적용
leftMoveButton.OnMoveButtonDown += () => _carController.Move(-1f);
rightMoveButton.OnMoveButtonDown += () => _carController.Move(1f);
}
#region 도로 생성 및 관리
// 도로 오브젝트 풀 초기화
private void InitializeRoadPool()
{
for (int i = 0; i < _roadPoolSize; i++)
{
GameObject road = Instantiate(roadPrefab);
road.SetActive(false);
_roadPool.Enqueue(road);
}
}
// 도로 오브젝트 풀에서 불러와 배치하는 함수 --> 계속 새로 생성되지 않게 Object Pool 활용
public void SpawnRoad(Vector3 position)
{
if (_roadPool.Count > 0)
{
GameObject road = _roadPool.Dequeue();
road.transform.position = position;
road.SetActive(true);
// 활성화 된 길을 움직이기 위해 List에 저장
_activeRoads.Add(road);
}
else
{
GameObject road = Instantiate(roadPrefab, position, Quaternion.identity);
_activeRoads.Add(road);
}
}
public void DestroyRoad(GameObject road)
{
road.SetActive(false);
_activeRoads.Remove(road);
_roadPool.Enqueue(road); // 다시 road를 사용하기 위해 Enqueue
}
#endregion
}
--> 빈 GameObject로 GameManager 만들고 GameManager.cs 할당 및 각각 바인딩
>> CarController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarController : MonoBehaviour
{
[SerializeField] private int gas = 100;
[SerializeField] private float moveSpeed = 1f;
public int Gas { get => gas; } // Gas 정보
private void Start()
{
StartCoroutine(GasCoroutine());
}
IEnumerator GasCoroutine()
{
while (true)
{
gas -= 10;
if (gas <= 0) break;
yield return new WaitForSeconds(1f);
}
// TODO: 게임 종료
}
// 자동차 이동 Method
public void Move(float direction)
{
transform.Translate(Vector3.right * (direction * moveSpeed * Time.deltaTime));
transform.position = new Vector3(Mathf.Clamp(transform.position.x, -2f, 2f), 0, transform.position.z);
}
// Gas Item 확득 시, 호출되는 Method
public void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Gas"))
{
gas += 30;
// TODO: 가스 아이템 제거
}
}
}
>> MoveButton.cs
: 버튼을 누르고 있는 동안 움직이고, 버튼을 뗐을 때 멈추는 방식으로 구현하기 위해 생성
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveButton : MonoBehaviour
{
public delegate void MoveButtonDelegate();
public event MoveButtonDelegate OnMoveButtonDown; // 외부 객체에서 전달받으면 실행
private bool _isDown;
private void Update()
{
if (_isDown)
{
OnMoveButtonDown?.Invoke();
}
}
public void ButtonDown()
{
_isDown = true;
}
public void ButtonUp()
{
_isDown = false;
}
}
>> RoadController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoadController : MonoBehaviour
{
// 플레이어 차량이 도로에 진입하면 다음 도로를 생성
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
GameManager.Instance.SpawnRoad(transform.position + new Vector3(0, 0, 10));
}
}
// 플레이어 차량이 도로를 벗어나면 해당 도로를 풀에서 제거
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Player"))
{
GameManager.Instance.DestroyRoad(gameObject);
}
}
}
WinMerge
: 코드 비교 프로그램
--> 1번을 눌러 새 문서를 추가하고, 비교할 코드를 작성한 뒤 2번을 누르면 사진과 같이 다른 부분을 비교해준다.
'Development > C#' 카테고리의 다른 글
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 46일차 (0) | 2025.02.03 |
---|---|
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 45일차 (0) | 2025.01.24 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 43일차 (0) | 2025.01.22 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 42일차 (0) | 2025.01.21 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 41일차 (0) | 2025.01.20 |