使用Unity网络系统的服务器授权系统时,使用NetworkServer.Spawn()
必须由服务器“生成”具有NetworkIdentities
的网络对象。这会导致它们被分配一个NetworkInstanceId
并在连接到服务器的客户端上创建。
NetworkBehaviours具有以下所述的功能。
同步变量
NetworkBehaviours
的成员变量可以从服务器同步到客户端。由于服务器在该系统中是权威的,所以同步仅在服务器到客户端方向上进行。客户做事的请求由命令处理,而不是由客户端同步的变量处理。
所述SyncVar
属性用于标记成员变量为被同步。SyncVars
可以是任何基本类型,而不是类,列表或其他集合。
public class SpaceShip : NetworkBehaviour
{
[SyncVar]
public int health;
[SyncVar]
public string playerName;
}
在NetworkBehaviour
脚本上为各种网络事件调用回调函数。这些是基类中的虚函数,因此可以在使用代码时重写它们:
public class SpaceShip : NetworkBehaviour
{
public override void OnStartServer()
{
// disable client stuff
}
public override void OnStartClient()
{
// register client events, enable effects
}
}
OnStartServer
函数在服务器上产生对象时启动,或者在场景中的对象启动服务器时调用。OnStartClient
函数在客户端生成对象时,或客户端连接到服务器以获取场景中的对象时调用。这些功能对于执行特定于客户端或服务器的事情非常有用,例如抑制对服务器的影响或设置客户端事件。
请注意,当使用本地客户端时,这两个函数将在同一对象上调用。
其他回调包括:
服务器和客户端功能
NetworkBehaviours
中的成员函数可以使用自定义属性进行标记,以将它们指定为仅服务器或仅客户端函数。例如:
using UnityEngine;
using UnityEngine.Networking;
public class SimpleSpaceShip : NetworkBehaviour
{
int health;
[Server]
public void TakeDamage( int amount)
{
// will only work on server
health -= amount;
}
[Client]
void ShowExplosion()
{
// will only run on client
}
void Update()
{
}
}
命令是客户请求在服务器上执行某些操作的方式。由于HLAPI是一个服务器授权系统,客户端只能通过命令做事情。命令在与发送命令的客户端相对应的服务器上的玩家对象上运行。此路由自动发生,因此客户端不可能为其他玩家发送命令。
命令必须以前缀“Cmd”开头,并在其上具有[Command]
自定义属性,如下所示:
using UnityEngine;
using UnityEngine.Networking;
public class SpaceShip : NetworkBehaviour
{
bool alive;
float thrusting; // 推进力
int spin;
[Command]
public void CmdThrust(float thrusting, int spin)
{
if (!alive)
{
this.thrusting = 0;
this.spin = 0;
return;
}
this.thrusting = thrusting;
this.spin = spin;
}
[ClientCallback]
void Update()
{
int spin = 0;
if (Input.GetKey(KeyCode.LeftArrow))
{
spin += 1;
}
if (Input.GetKey(KeyCode.RightArrow))
{
spin -= 1;
}
// this will be called on the server
CmdThrust(Input.GetAxis("Vertical"), spin);
}
}
通过在客户端上正常调用函数来调用命令。但不是在客户端上运行的命令功能,而是在服务器上该客户端的玩家对象上调用它。所以,命令是类型安全的,具有内置的安全性和路由到玩家,并且使用高效的序列化机制来使参数快速调用。
客户端RPC调用
客户端RPC调用是服务器对象在客户端对象上发生事件的一种方式。这与命令如何发送消息的方向相反,但概念是相同的。然而,客户端RPC调用不仅可以在玩家对象上调用,还可以在任何NetworkIdentity
对象上调用。它们必须以前缀“Rpc”开头并具有[ClientRPC]
自定义属性,如下所示:
联网事件与客户端RPC调用相似,但不是仅调用客户端对象上的函数,而是触发客户端对象上的事件。然后调用为该事件注册的其他脚本 - 使用来自服务器的参数,以便在客户端上实现联网的脚本间交互。事件必须以前缀“Event”开始,并具有SyncEvent
自定义属性。
using UnityEngine;
using UnityEngine.Networking;
// Server script
public class MyCombat : NetworkBehaviour
{
public delegate void DieDelegate();
public delegate void RespawnDelegate();
bool alive;
int health;
[SyncEvent(channel=1)]
public event TakeDamageDelegate EventTakeDamage;
[SyncEvent]
public event DieDelegate EventDie;
[SyncEvent]
public event RespawnDelegate EventRespawn;
[Server]
void EventTakeDamage(int amount)
{
if (!alive)
return;
if (health > amount) {
health -= amount;
}
else
{
health = 0;
alive = false;
// send die event to all clients
EventDie();
deathTimer = Time.time + 5.0f;
}
}
[ServerCallback]
void Update()
{
if (!alive)
{
if (Time.time > deathTimer)
{
Respawn();
}
return;
}
}
[Server]
void Respawn()
{
alive = true;
// send respawn event to all clients
EventRespawn();
}
提示
?