Handling Non-Player objects
处理非玩家角色对象
Our current example has been focused primarily on the player GameObjects.
我们当前的例子主要集中在玩家的游戏对象上。
Most games, however, have many non-player GameObjects that exist in the game world.
然而,大多数游戏都有许多在游戏世界中存在的非玩家游戏对象。
For this example we will ignore environmental GameObjects but concentrate on non-player GameObjects such as enemies
在这个例子中,我们将忽略环境的游戏对象,而将注意力集中在非玩家的游戏对象上,比如敌人。
While player GameObjects are spawned when a Client connects to the Host, enemy GameObjects need to be controlled by the Server.
当一个客户端连接到主机时,玩家的游戏对象就会产生,而敌人的游戏对象需要被服务器控制。
In this section we will add an Enemy Spawner that creates non-player, enemy GameObjects that can be shot and killed by any of the players.
在这一节中,我们将添加一个敌人的产卵器,它可以创造非玩家,敌人的游戏对象,可以被任何玩家射杀。
Create a new empty GameObject.
创建一个新的空的GameObject。
Rename the new GameObject “Enemy Spawner”
重命名新游戏对象“敌人的产卵器”
With the Enemy Spawner GameObject selected,
选择了敌人的产卵器,
...
…
find and add the component: Network > NetworkIdentity
查找并添加组件:Network > NetworkIdentity。
...
…
on the NetworkIdentity component, set the Server Only checkbox to true.
在NetworkIdentity组件上,将服务器复选框设置为true。
By setting Server Only to true, this prevents the Enemy Spawner from being sent to the Clients.
通过将服务器设置为true,这可以防止敌人的产卵器被发送到客户端。
With the Enemy Spawner GameObject selected
选择了敌人的产卵器。
...
…
create and add a new script called “EnemySpawner”
创建并添加一个名为“EnemySpawner”的新脚本
Open the script EnemySpawner for editing.
打开脚本灌肠器进行编辑。
Replace all of the code in the script with the following simple EnemySpawner class:
将脚本中的所有代码替换为以下简单的灌肠类:
EnemySpawner
C#
using UnityEngine;
using UnityEngine.Networking;
public class EnemySpawner : NetworkBehaviour {
public GameObject enemyPrefab;
public int numberOfEnemies;
public override void OnStartServer()
{
for (int i=0; i < numberOfEnemies; i++)
{
var spawnPosition = new Vector3(
Random.Range(-8.0f, 8.0f),
0.0f,
Random.Range(-8.0f, 8.0f));
var spawnRotation = Quaternion.Euler(
0.0f,
Random.Range(0,180),
0.0f);
var enemy = (GameObject)Instantiate(enemyPrefab, spawnPosition, spawnRotation);
NetworkServer.Spawn(enemy);
}
}
}
It is worth noting a few key elements in this script.
值得注意的是这个脚本中的几个关键元素。
The namespace UnityEngine.
名称空间UnityEngine。
Networking is required.
网络是必需的。
The class needs to derive from NetworkBehaviour.
这个类需要从网络行为派生。
The class uses an implementation of the virtual function OnStartServer.
这个类使用了一个虚拟函数OnStartServer的实现。
When the server starts, a number of enemies are generated at a random position and rotation and then these are spawned using NetworkServer.Spawn(enemy).
当服务器启动时,会在随机位置和旋转中生成一些敌人,然后使用NetworkServer.Spawn(敌人)生成这些敌人。
OnStartServer is very similar to OnStartLocalPlayer, used earlier in this lesson to change the player GameObject’s color.
OnStartServer非常类似于OnStartLocalPlayer,在本课的早期使用它来改变播放器的颜色。
In this case, OnStartServer is called on the Server when the Server starts listening to the Network.
在这种情况下,当服务器开始监听网络时,服务器将调用OnStartServer。
For more information on the virtual functions available from the NetworkBehaviour base class, please see the manual pages on NetworkBehaviour and Spawning or the Scripting Reference page on NetworkBehaviour.
有关网络行为基类中可用的虚拟函数的更多信息,请参阅有关网络行为的手册页,以及关于网络行为的脚本参考页面。
Save the script.
保存脚本。
Return to Unity.
回到Unity。
Now that the Enemy Spawner has been created, we need enemy GameObjects to spawn.
现在敌人的产卵器已经被创造出来了,我们需要敌人的游戏对象来产卵。
For ease, we will use the player prefab as a base for the enemy.
为了方便起见,我们将使用玩家预制板作为敌人的基地。
The enemy will need the NetworkIdentity and NetworkTransform components already attached to the Player prefab, as well the Health script and the Healthbar setup.
敌人将需要已经连接到玩家预置的NetworkIdentity和NetworkTransform组件,以及健康脚本和Healthbar设置。
We will customize the enemy GameObject a little to identify the enemy as different from the player prefab.
我们将对敌人的游戏对象进行一些自定义,以识别不同于玩家预制的敌人。
Drag the Player prefab into the Hierarchy to create an instance of the Player GameObject in the scene.
将播放器预置到层次结构中,以创建场景中播放器游戏对象的实例。
Change the name of the Player GameObject to “Enemy”.
将玩家游戏对象的名字改为“敌人”。
Drag this Enemy GameObject back into the Project Window to create a new Enemy prefab.
将这个敌人的游戏对象拖回项目窗口,创建一个新的敌人预置。
We create the new Enemy prefab at this point in the process to prevent any chance of saving our changes to the linked Player prefab.
在此过程中,我们创建了新的敌人预置,以防止任何可能将我们的更改保存到链接的播放器预置。
By creating a new prefab from the instance of the Player prefab in the scene, we link the prefab instance in the scene to the new prefab asset in the Project Window.
通过在场景中创建一个新的预置程序,我们将场景中的预置实例链接到项目窗口中的新预置资产。
With the Enemy GameObject selected in the Hierarchy Window,
通过在层次结构窗口中选择的敌人GameObject,
...
…
delete the child GameObject called Gun.
删除名为Gun的子游戏对象。
Unity will warn us that we will break the Prefab instance.
团结将警告我们,我们将打破预制的实例。
Click Continue.
单击Continue。
With the Enemy GameObject selected,
选择了敌人的游戏对象,
...
…
delete the child GameObject called Bullet Spawn.
删除子游戏对象,即“子弹卵”。
...
…
remove the PlayerController script from the root GameObject.
从根游戏对象中删除PlayerController脚本。
At this point, the enemy it technically ready to go, but it will look identical to the player GameObjects.
在这一点上,敌人在技术上已经准备好了,但是它看起来和玩家的游戏对象是一样的。
Let’s add a few details to make the enemies different from the players.
让我们添加一些细节,使敌人与玩家不同。
First, we will simply reverse the color scheme.
首先,我们将简单地改变配色方案。
Apply the Black Material to the Enemy GameObject.
将黑色材料应用于敌人的游戏对象。
Set the Material on the Visor GameObject to Default-Material.
将遮阳板上的材料设置为默认材料。
Next, optionally, you can create a headpiece.
接下来,您可以选择创建一个headpiece。
With the Enemy GameObject selected,
选择了敌人的游戏对象,
...
…
create a new Cube as a child GameObject.
创建一个新的立方体作为子游戏对象。
Rename this new child GameObject "Mohawk”.
重命名这个新的子游戏对象“莫霍克”。
Set the Mohawk’s Transform Position to (0.0.
将莫霍克变换位置设置为(0.0)。
0.55, -0.15).
Set the Mohawk’s Transform Scale to (0.2, 1.0, 1.0).
将Mohawk的转换级别设置为(0.2,1.0,1.0).
Remove the Mohawk’s BoxCollider component.
拆下莫霍克的波箱碰撞组件。
The Enemy should look something like this:
敌人应该是这样的:
Apply changes to the Enemy Prefab.
将更改应用于敌人的预制。
Delete the Enemy GameObject from the scene.
从场景中删除敌人的游戏对象。
Save the scene.
保存场景。
Now that the Enemy prefab set up we need to finish this section by registering the Enemy prefab and adding the Enemyprefab to the Enemy Spawner.
现在,敌人的预警机已经设置好了,我们需要通过注册敌人的预制板,并将敌人的预制板添加到敌人的产卵器来完成这个部分。
Select the NetworkManager in the Hierarchy Window.
在层次结构窗口中选择NetworkManager。
With the NetworkManager selected,
使其选择,
...
…
open the Spawn Info foldout.
打开生成的信息foldout。
...
…
in the list Registered Spawnable Prefabs, add a new row with the + button.
在列表注册的可生成的Prefabs中,添加一个带有+按钮的新行。
...
…
add the Enemy prefab to the new row in the Registered Spawnable Prefabs list.
在已注册的可生成的Prefabs列表中添加敌人的预置到新行。
Select the Enemy Spawner in the Hierarchy Window.
在层次结构窗口中选择敌人的产卵器。
With the Enemy Spawner selected,
随着敌人的产卵,
...
…
set the Enemy Prefab field to the Enemy prefab asset from the Project Window.
从项目窗口向敌人预制资产设置敌人预制区。
...
…
set the Number Of Enemies to a value of 4.
将敌人的数量设置为4。
Save the Project.
保存项目。
Because the Enemy prefab has a Health script, just like the Player, the Bullet script should detect the enemy’s Health script in the same way it does on the Player, so no changes are needed here.
因为敌人的预制板有一个健康脚本,就像玩家一样,子弹脚本应该像玩家一样检测敌人的健康脚本,所以这里不需要改变。
Build and Run this scene as a standalone application.
构建并运行这个场景作为一个独立的应用程序。
Click the Host button from the in-game UI to start this game as a Host.
单击游戏内UI中的主机按钮以作为主机启动此游戏。
At this point, the first player and the four enemies should be created.
此时,应该创建第一个玩家和四个敌人。
Move the Player GameObject.
玩家GameObject移动。
Return to Unity.
回到Unity。
Enter Play Mode.
进入播放模式。
Click the LAN Client button from the in-game UI to connect to the Host as a Client.
单击游戏内UI中的LAN客户端按钮以连接到主机作为客户端。
The second player should now be created, and the first player and all of the enemies should have been added to this instance of the game.
第二个玩家现在应该被创建,并且第一个玩家和所有的敌人应该被添加到这个游戏的实例中。
Shooting the enemies will cause them to lose health, but when their health reaches zero they are not respawned as none of the enemies will meet the isLocalPlayer check in RpcRespawn.
射击敌人会使他们失去健康,但是当他们的健康达到零的时候,他们就不会受到伤害,因为没有敌人会在RpcRespawn中遇到isLocalPlayer检查。
Their current health will, however, be set back to maximum, as that is controlled by the Server.
但是,它们当前的健康状况将被设置为最大,因为这是由服务器控制的。
Close the standalone player.
关闭独立的球员。
Return to Unity.
回到Unity。
Exit Play Mode.
退出播放模式。