아이템을 랜덤하게 선택해야 하지만, 어떤 아이템은 다른 것보다 가능성이 높은 경우가 있습니다. 예를 들어, NPC 캐릭터는 플레이어와 조우했을 때 몇 가지 반응을 나타낼 수 있습니다 : -
- 50%의 확률로 반겨주기
- 25% 확률로 도주
- 20% 확률로 갑작스러운 공격
- 5% 확률로 돈을 선물
이러한 서로 다른 결과를 분할한 페이퍼 스트립(Paper strip)으로 표현할 수 있고, 각각의 부분은 스트립의 길이의 일부를 차지합니다. 그 차지하는 길이가 선택되는 결과의 확률에 해당합니다. 선택하는 것은 스트립의 길이상에서 임의의 점을 선택하여(예를 들면 다트를 던지도록), 어떤 부분에 해당하는지 확인하는 것에 해당합니다.
스크립트 안에서 페이퍼 스트립은 실제로 float의 배열에서 각 항목에 다른 확률을 순서대로 포함하고 있습니다. 임의의 점은 Random.value을 모든 float의 총에 곱셈하여 얻을 수 있습니다 (더해서 1이 될 필요는 없고, 중요한 것은 다른 값의 상대적인 길이). 점이 어느 배열 요소에 “들어 있는지” 알아 내기 위하여 점의 값이 첫 번째 요소의 값보다 작은 지 비교합니다. 그 경우 선택되는 것은 첫 번째 요소입니다. 그렇지 않으면 첫 번째 요소의 값을 점 값에서 차감하고, 그것을 두 번째 요소의 값보다 작은 지 비교하는 등을 반복하여 최종적으로 올바른 요소를 찾습니다. 코드는 다음과 같이 될 것입니다 : -
float Choose (float[] probs) {
float total = 0;
foreach (float elem in probs) {
total += elem;
}
float randomPoint = Random.value * total;
for (int i= 0; i < probs.Length; i++) {
if (randomPoint < probs[i]) {
return i;
}
else {
randomPoint -= probs[i];
}
}
return probs.Length - 1;
}
마지막 return 문이 필요한 이유는 Random.value는 1의 값을 반환할 수 있기 때문이라는 것을 명심하십시오. 이 경우, 검색은 어디서나 임의의 지점을 찾을 수 없습니다. 다음 행을 변경하여,
if (randomPoint < probs[i])
… 값을 < = 기호로 변경하여 여분의 return 명령을 피할 수 있지만, 확률이 0인 경우에도 아이템을 선택할 수 있도록 허용해버립니다.
int[] prob = { 10, 60, 10, 10, 10 };
int total = 0;
foreach(int p in prob)
{
total += p;
}
int rand = Random.Range(0, total);
for(int i = 0; i < prob.Length; i++)
{
if(rand < prob[i])
{
Debug.Log(string.Format("{0} : {1}", prob[i], i));
break;
}
else
{
rand -= prob[i];
}
}
'유니티 > Note' 카테고리의 다른 글
| UGUI Text 글자 간격 조정하기 (0) | 2015.07.16 |
|---|---|
| 다른 확률을 가진 아이템을 선택 (0) | 2015.07.15 |
| 유니티 서버 관련. (0) | 2015.07.14 |
| 유니티 5.x 애니메이션 atomic (0) | 2015.06.30 |
| 유니티 svn 사용 시 해야될 것 (0) | 2015.06.22 |
| 유니티 기본 생성 스크립트 변경 방법 (0) | 2015.04.27 |


