Randomly chosen items or values are important in many games. This sections shows how you can use Unity's built-in random functions to implement some common game mechanics. 在很多游戲中,隨機(jī)選取數(shù)據(jù)或游戲元素是很重要的。本節(jié)說明如何使用Unity的內(nèi)置隨機(jī)函數(shù)執(zhí)行一些常見的游戲機(jī)制。 Choosing a Random Item from an Array
Picking an array element at random boils down to choosing a random integer between zero and the array's maximum index value (which is equal to the length of the array minus one). This is easily done using the built-in Random.Range function:- 要隨機(jī)獲取數(shù)組中零到索引上界(等于數(shù)組的長度減去一)之中的數(shù)組元素。使用內(nèi)置的Random.Range函數(shù)很容易做到: var element = myArray[Random.Range(0, myArray.Length)];
Note that Random.Range returns a value from a range that includes the first parameter but excludes the second, so using myArray.Length here gives the correct result. 請注意,Random.Range是在范圍中只返回第一個參數(shù)的值,但不包括第二個參數(shù),所以在這里直接使用myArray.Length給出正確的結(jié)果。 Choosing Items with Different Probabilities 用不同的概率選中數(shù)據(jù)Sometimes, you need to choose items at random but with some items more likely to be chosen than others. For example, an NPC may react in several different ways when it encounters a player:- 有時候,你需要隨機(jī)選中的選項(xiàng)概率比選擇其他項(xiàng)的概率更大。例如,NPC可能以下在幾種不同的方式做出反應(yīng),當(dāng)它遇到一個玩家: - - 50% chance of friendly greeting
50%的機(jī)會友好的問候 - 25% chance of running away
25%的幾率走開 - 20% chance of immediate attack
20%的機(jī)會立即攻擊 - 5% chance of offering money as a gift
5%的機(jī)會提供金錢作為禮物
You can visualise these different outcomes as a paper strip divided into sections each of which occupies a fraction of the strip's total length. The fraction occupied is equal to the probability of that outcome being chosen. Making the choice is equivalent to picking a random point along the strip's length (say by throwing a dart) and then seeing which section it is in. 你可以想象這些不同的結(jié)果分布在條形紙上,每個結(jié)果各占總長度的一部分。各個結(jié)果被選中的概率是相等的。做出的選擇等價于隨機(jī)拋出一個點(diǎn)沿紙帶飛行的長度(想想投擲飛鏢),看看它會落到哪個部分。 
In the script, the paper strip is actually an array of floats that contain the different probabilities for the items in order. The random point is obtained by multiplying Random.value by the total of all the floats in the array (they need not add up to 1; the significant thing is the relative size of the different values). To find which array element the point is "in", firstly check to see if it is less than the value in the first element. If so, then the first element is the one selected. Otherwise, subtract the first element's value from the point value and compare that to the second element and so on until the correct element is found. In code, this would look something like the following:- 在下面腳本中,條形紙實(shí)際上就像是一個數(shù)組,以便包含不同概率的元素。隨機(jī)點(diǎn)則是由float數(shù)組大小乘以Random.value值來獲得(它們累計(jì)加不一定要等于1,主要是不同的值獲得的相對大?。?。為了找出隨機(jī)點(diǎn)元素落在哪個點(diǎn)數(shù)組,首先檢查看它是否是小于第一個元素的值。如果是的話,那么第一個元素將被選擇。否則,從數(shù)組中減去第一個元素的值,比較第二個元素,直到找到正確的元素。類似于下面這個代碼: - function Choose(probs: float[]) {
var total = 0;
for (elem in probs) {
total += elem;
}
var randomPoint = Random.value * total;
for (i = 0; i < probs.Length; i++) {
if (randomPoint < probs[i])
return i;
else
randomPoint -= probs[i];
}
return probs.Length - 1;
}
Note that the final return statement is necessary because Random.value can return a result of 1. In this case, the search will not find the random point anywhere. Changing the line 需要注意的是最后一個return語句非常必要,因?yàn)镽andom.value可以返回1(注:有些地方random.value都是不能返回1,可以返回0)。在這種情況下,我們會無法獲得隨機(jī)點(diǎn),更改代碼行: if (randomPoint < probs[i])
...to a less-than-or-equal test would avoid the extra return statement but would also allow an item to be chosen occasionally even when its probability is zero. 一個小于或等于的if測試語句將避免額外的return語句。因?yàn)榧幢氵x中它的概率是零。它也有可能被選中。 Shuffling a List 隨機(jī)排序A common game mechanic is to choose from a known set of items but have them arrive in random order. For example, a deck of cards is typically shuffled so they are not drawn in a predictable sequence. You can shuffle the items in an array by visiting each element and swapping it with another element at a random index in the array:- 一個普遍的游戲機(jī)制是從一個已經(jīng)進(jìn)行隨機(jī)順序的數(shù)組中選擇一個需要的數(shù)據(jù)。例如,一副牌通常會被打亂,所以你不會預(yù)見到它們的排列順序。同樣這你可以通過隨機(jī)交換數(shù)組中的元素或改變它們的索引值來打亂它們之間的順序 function Shuffle(deck: int[]) {
for (i = 0; i < deck.Length; i++) {
var temp = deck[i];
var randomIndex = Random.Range(0, deck.Length);
deck[i] = deck[randomIndex];
deck[randomIndex] = temp;
}
}
Choosing from a Set of Items Without Repetition 不重復(fù)選取A common task is to pick a number of items randomly from a set without picking the same one more than once. For example, you may want to generate a number of NPCs at random spawn points but be sure that only one NPC gets generated at each point. This can be done by iterating through the items in sequence, making a random decision for each as to whether or not it gets added to the chosen set. As each item is visited, the probability of its being chosen is equal to the number of items still needed divided by the number still left to choose from. 一個簡單的要求是在選擇數(shù)組中,同一個元素最多只能被隨機(jī)選中一次。例如,您可能要在隨機(jī)點(diǎn)的位置生成NPC,但可以肯定,在每一個點(diǎn)只能有一個NPC產(chǎn)生。這可以通過遍歷序列中的項(xiàng)目,為每一個隨機(jī)點(diǎn)決定是否被添加到選擇集。剩下的元素被選中的概率等于需要選擇的元素?cái)?shù)量除以剩下的所有元素?cái)?shù)量。 As an example, suppose that ten spawn points are available but only five must be chosen. The probability of the first item being chosen will be 5 / 10 or 0.5. If it is chosen then the probability for the second item will be 4 / 9 or 0.44 (ie, four items still needed, nine left to choose from). However, if the first was not chosen then the probability for the second will be 5 / 9 or 0.56 (ie, five still needed, nine left to choose from). This continues until the set contains the five items required. You could accomplish this in code as follows:- 例如,假設(shè)有十個刷新復(fù)活點(diǎn)可以用,但是必須只能選擇五個。第一個物體被選擇的概率將是5/ 10或0.5。如果選中第一個之后,第二個的概率為4 /9或0.44(即,四個物體仍然需要從剩下的九個選擇)。然而,如果第一個沒有選中,第二個選中的概率為5/ 9(即5/ 9或0.56,仍然需要從剩下的九個中選擇)。這一直持續(xù)到要求的5個都被選上。完成的代碼如下: var spawnPoints: Transform[];
function ChooseSet(numRequired: int) {
var result = new Transform[numRequired];
var numToChoose = numRequired;
for (numLeft = spawnPoints.Length; numLeft > 0; numLeft--) {
// Adding 0.0 is simply to cast the integers to float for the division.
var prob = numToChoose + 0.0 / numLeft + 0.0;
if (Random.value <= prob) {
numToChoose--;
result[numToChoose] = spawnPoints[numLeft - 1];
if (numToChoose == 0)
break;
}
}
return result;
}
Note that although the selection is random, items in the chosen set will be in the same order they had in the original array. If the items are to be used one at a time in sequence then the ordering can make them partly predictable, so it may be necessary to shuffle the array before use. 請注意,雖然選擇是隨機(jī)的,在選擇集中的數(shù)據(jù)在原始數(shù)組的排列順序依然相同。如果數(shù)據(jù)排序是一次性的話,部分隨機(jī)的數(shù)據(jù)有可能是可預(yù)見到的,所以它有必要在使用前就打亂數(shù)組的順序。 Random Points in Space 空間中的隨機(jī)點(diǎn)A random point in a cubic volume can be chosen by setting each component of a Vector3 to a value returned by Random.value:- 一個三維空間中的點(diǎn),可以通過random.value函數(shù)中隨機(jī)返回一個為Vector3的xyz值 var randVec = Vector3(Random.value, Random.value, Random.value);
This gives a point inside a cube with sides one unit long. The cube can be scaled simply by multiplying the X, Y and Z components of the vector by the desired side lengths. If one of the axes is set to zero, the point will always lie within a single plane. For example, picking a random point on the "ground" is usually a matter of setting the X and Z components randomly and setting the Y component to zero. 上述函數(shù)所給的這個立方體中的點(diǎn)會分布在同一條邊上。而將所需的邊長乘以vector3的X,Y和Z分量就可以簡單的進(jìn)行比例縮放。另外,如果其中一個軸的值被設(shè)置為零,這一點(diǎn)始終分布在一個單獨(dú)的平面。例如,選擇"地面"上的一個隨機(jī)點(diǎn)通常是把Y分量設(shè)為零,然后隨機(jī)設(shè)置X和Z分量值。 When the volume is a sphere (ie, when you want a random point within a given radius from a point of origin), you can use Random.insideUnitSphere multiplied by the desired radius:- 當(dāng)它是一個球體時(即:當(dāng)你想從給定的半徑內(nèi)獲取一個隨機(jī)點(diǎn)),您可以使用所需的半徑大小乘以Random.insideUnitSphere: var randWithinRadius = Random.insideUnitSphere * radius;
Note that if you set one of the resulting vector's components to zero, you will *not* get a correct random point within a circle. Although the point is indeed random and lies within the right radius, the probability is heavily biased toward the edge of the circle and so points will be spread very unevenly. You should use Random.insideUnitCircle for this task instead:- 注意:如果你設(shè)定了Vector中的某個向量值為零,你獲得的隨機(jī)點(diǎn)將"不會"圍成一個圓。雖然這一點(diǎn)的獲取確實(shí)是隨機(jī)的且半徑也是正確的。這個點(diǎn)分布的概率在很大程度上偏向圓的邊緣且極不均勻。要讓它分布在圓上的話可以使用Random.insideUnitCircle做到。 var randWithinCircle = Random.insideUnitCircle * radius;
頁面最后更新:2011-09-12
|