[TIL] Unity - 랜덤 버프

MINO·2024년 6월 25일
0
post-thumbnail

2024-06-24


Random.Range

UnityEngine.Random 클래스의 Range 메서드로 다음과 같은 형태를 가진다.

int Random.Range(int minInclusive, int maxEclusive)
float Random.Range(float minInclusive, float MaxInclusive)

랜덤 버프 선택

Runner RPG 프로젝트를 진행하며,
플레이어는 6개의 스탯을 가지고 있고, 특정 조건마다 스탯을 업그레이드 해주고 싶다.

위의 이미지처럼, 두 가지 버프 중 하나를 선택하는 방식이다.


이 기능을 구현해준 팀원의 고민은 선택지 1, 2 가 같은 종류이어도 괜찮은지 였다.

항상 서로 다른 선택지가 나오려면 어떤 방법으로 코드를 짜야할까
팀원 모두 고민을 해봤다.

구현 (1)

Random.Range 함수를 통해 6개의 스탯 중, 두가지를 골랐다.

int leftBuff = Random.Range(0,6);
int rightBuff = Random.Range(0,6);

그러나, 고안한 기획은 두 가지 버프의 종류는 서로 달랐으면 좋겠다는 것이다.


구현 (2)

처음에는 while 문을 통해서, leftBuff 와 rightBuff 가 다를 때 까지 뽑아주면 된다고 생각하였다.

int leftBuff = Random.Range(0,6);
int rightBuff = Random.Range(0,6);

while(leftBuff != rightBuff)
	rightBuff = Random.Range(0,6);

그러나 스탯의 종류가 6개뿐이라서 최악의 경우,
while 문에서 한참동안 갇혀있을 수도 있다는 팀원의 의견에 다른 방법을 찾아보기로 하였다.


구현 (3)

하드코딩 방식으로, 별로 좋지 않다고 생각한 코드다.

leftBuff 와 rightBuff 를 각각 뽑은 다음,
같은 경우에 예외처리를 해주었다.

int leftBuff = Random.Range(0,6);
int rightBuff = Random.Range(0,6);

if(leftBuff == rightBuff)
{
	if(leftBuff == 0)
    	rightBuff = Random.Range(1,6);
    else if(leftBuff == 5)
    	rightBuff = Random.Range(0,5);
    else
    	rightBuff = leftBuff + 1;
}

그러나, 원래 취지와는 다르게, 모두 같은 확률을 가지고 있다고 할 수 없다.


구현 (4)

List 를 통해, 중복이 될 상황을 아예 없애주었다.

List<int> stats = new List<int> { 0, 1, 2, 3, 4, 5 };
int idx1 = Random.Range(0, stats.Count);
leftBuff = (EStat)stats[idx1];
stats.RemoveAt(idx1);
int idx2 = Random.Range(0, stats.Count);
rightBuff = (EStat)stats[idx2];

최종적으로 사용하게 된 코드이다.

스탯의 종류가 6개 뿐이라서 RemoveAt 을 하는 데 공간이나 시간이 많이 낭비되진 않는다.

그러나 스탯의 종류가 다양한 경우, RemoveAt 을 사용하면 그만큼 배열 복사가 일어나기 때문에 좋다고는 할 수 없겠다.


튜터님의 조언

구현(4) 를 통해, 프로젝트의 랜덤 버프를 띄우는 것에는 성공했지만,
이 방법이 좋은 방법인가 하는 생각이 맴돌아 튜터님을 찾아갔다.

스탯의 종류가 적어 List 를 활용한 구현(4) 방법은 좋은 선택인 것 같다고 말씀해주셨다.

RemoveAt 을 쓰고 싶다면, 시간 복잡도가 더 적게 소요되는
Linked List 를 사용하는 것도 추천해주셨다.


만약, 뽑아야하는 리스트의 크기가 큰 경우일 때는,
RemoveAt 이 성능에 영향을 줄 수 있으므로, 구현(2) 의 방식을 사용할 것을 추천해주셨다.
리스트의 크기가 크다는 것은, 그만큼 중복이 발생할 확률도 적어진다는 뜻이기도 하다.

int leftBuff = Random.Range(0,6);
int rightBuff = Random.Range(0,6);

while(leftBuff != rightBuff)
{
	rightBuff = Random.Range(0,6);
}

TIL 마무리

처음 팀원이 랜덤 뽑기를 어떻게 구현할 지 모르겠다고 하였을 때,
쉽게 해결할 수 있을 거라고 생각하였다.

생각보다 좋은 코드를 찾아내기는 어려웠고,
코드를 구현하고 난 뒤에도 계속 찜찜한 느낌이었다.

같은 기능을 구현하더라도, 더 빠르고 공간을 절약할 수 있는 좋은 코드를 작성하도록 노력하자.

profile
안녕하세요 게임 개발하는 MINO 입니다.

0개의 댓글