打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Adding Random Gameplay Elements 添加随机的游戏元素

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.

在很多游戏中,随机选取数据或游戏元素是很重要的。本节说明如何使用Unity的内置随机函数执行一些常见的游戏机制。

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:-

要随机获取数组中零到索引上界(等于数组的长度减去一)之中的数组元素。使用内置的Random.Range函数很容易做到:

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是在范围中只返回第一个参数的值,但不包括第二个参数,所以在这里直接使用myArray.Length给出正确的结果。

Choosing Items with Different Probabilities
用不同的概率选中数据

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:-

有时候,你需要随机选中的选项概率比选择其他项的概率更大。例如,NPC可能以下在几种不同的方式做出反应,当它遇到一个玩家: -

  • 50% chance of friendly greeting
    50%的机会友好的问候
  • 25% chance of running away
    25%的几率走开
  • 20% chance of immediate attack
    20%的机会立即攻击
  • 5% chance of offering money as a gift
    5%的机会提供金钱作为礼物

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.

你可以想象这些不同的结果分布在条形纸上,每个结果各占总长度的一部分。各个结果被选中的概率是相等的。做出的选择等价于随机抛出一个点沿纸带飞行的长度(想想投掷飞镖),看看它会落到哪个部分。

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:-

在下面脚本中,条形纸实际上就像是一个数组,以便包含不同概率的元素。随机点则是由float数组大小乘以Random.value值来获得(它们累计加不一定要等于1,主要是不同的值获得的相对大小)。为了找出随机点元素落在哪个点数组,首先检查看它是否是小于第一个元素的值。如果是的话,那么第一个元素将被选择。否则,从数组中减去第一个元素的值,比较第二个元素,直到找到正确的元素。类似于下面这个代码: -

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语句非常必要,因为Random.value可以返回1(注:有些地方random.value都是不能返回1,可以返回0)。在这种情况下,我们会无法获得随机点,更改代码行:

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语句。因为即便选中它的概率是零。它也有可能被选中。

Shuffling a List 随机排序

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:-

一个普遍的游戏机制是从一个已经进行随机顺序的数组中选择一个需要的数据。例如,一副牌通常会被打乱,所以你不会预见到它们的排列顺序。同样这你可以通过随机交换数组中的元素或改变它们的索引值来打乱它们之间的顺序

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
不重复选取

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.

一个简单的要求是在选择数组中,同一个元素最多只能被随机选中一次。例如,您可能要在随机点的位置生成NPC,但可以肯定,在每一个点只能有一个NPC产生。这可以通过遍历序列中的项目,为每一个随机点决定是否被添加到选择集。剩下的元素被选中的概率等于需要选择的元素数量除以剩下的所有元素数量。

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:-

例如,假设有十个刷新复活点可以用,但是必须只能选择五个。第一个物体被选择的概率将是5/ 10或0.5。如果选中第一个之后,第二个的概率为4 /9或0.44(即,四个物体仍然需要从剩下的九个选择)。然而,如果第一个没有选中,第二个选中的概率为5/ 9(即5/ 9或0.56,仍然需要从剩下的九个中选择)。这一直持续到要求的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.

请注意,虽然选择是随机的,在选择集中的数据在原始数组的排列顺序依然相同。如果数据排序是一次性的话,部分随机的数据有可能是可预见到的,所以它有必要在使用前就打乱数组的顺序。

Random Points in Space 空间中的随机点

A random point in a cubic volume can be chosen by setting each component of a Vector3 to a value returned by Random.value:-

一个三维空间中的点,可以通过random.value函数中随机返回一个为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.

上述函数所给的这个立方体中的点会分布在同一条边上。而将所需的边长乘以vector3的X,Y和Z分量就可以简单的进行比例缩放。另外,如果其中一个轴的值被设置为零,这一点始终分布在一个单独的平面。例如,选择"地面"上的一个随机点通常是把Y分量设为零,然后随机设置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:-

当它是一个球体时(即:当你想从给定的半径内获取一个随机点),您可以使用所需的半径大小乘以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:-

注意:如果你设定了Vector中的某个向量值为零,你获得的随机点将"不会"围成一个圆。虽然这一点的获取确实是随机的且半径也是正确的。这个点分布的概率在很大程度上偏向圆的边缘且极不均匀。要让它分布在圆上的话可以使用Random.insideUnitCircle做到。

var randWithinCircle = Random.insideUnitCircle * radius;

页面最后更新:2011-09-12

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Javascript数组及其操作
JavaScript入门基础教程(4)js内建对象
前端教程:JavascriptArray.pop()方法
js和jquery的数组过滤grep()和filter()数组去重去nullundefind
JavaScript学习笔记:内置API
一篇文章带你了解JavaScript 数组迭代方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服