使用Unity网络系统的服务器授权系统时,使用NetworkServer.Spawn()必须由服务器“生成”具有NetworkIdentities的网络对象。这会导致它们被分配一个NetworkInstanceId并在连接到服务器的客户端上创建。

    NetworkBehaviours具有以下所述的功能。

    同步变量

    NetworkBehaviours的成员变量可以从服务器同步到客户端。由于服务器在该系统中是权威的,所以同步仅在服务器到客户端方向上进行。客户做事的请求由命令处理,而不是由客户端同步的变量处理。

    所述SyncVar属性用于标记成员变量为被同步。SyncVars可以是任何基本类型,而不是类,列表或其他集合。

    1. public class SpaceShip : NetworkBehaviour
    2. {
    3. [SyncVar]
    4. public int health;
    5. [SyncVar]
    6. public string playerName;
    7. }

    NetworkBehaviour脚本上为各种网络事件调用回调函数。这些是基类中的虚函数,因此可以在使用代码时重写它们:

    1. public class SpaceShip : NetworkBehaviour
    2. {
    3. public override void OnStartServer()
    4. {
    5. // disable client stuff
    6. }
    7. public override void OnStartClient()
    8. {
    9. // register client events, enable effects
    10. }
    11. }

    OnStartServer函数在服务器上产生对象时启动,或者在场景中的对象启动服务器时调用。OnStartClient函数在客户端生成对象时,或客户端连接到服务器以获取场景中的对象时调用。这些功能对于执行特定于客户端或服务器的事情非常有用,例如抑制对服务器的影响或设置客户端事件。

    请注意,当使用本地客户端时,这两个函数将在同一对象上调用。

    其他回调包括:

    服务器和客户端功能

    NetworkBehaviours中的成员函数可以使用自定义属性进行标记,以将它们指定为仅服务器或仅客户端函数。例如:

    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. public class SimpleSpaceShip : NetworkBehaviour
    4. {
    5. int health;
    6. [Server]
    7. public void TakeDamage( int amount)
    8. {
    9. // will only work on server
    10. health -= amount;
    11. }
    12. [Client]
    13. void ShowExplosion()
    14. {
    15. // will only run on client
    16. }
    17. void Update()
    18. {
    19. }
    20. }

    命令是客户请求在服务器上执行某些操作的方式。由于HLAPI是一个服务器授权系统,客户端只能通过命令做事情。命令在与发送命令的客户端相对应的服务器上的玩家对象上运行。此路由自动发生,因此客户端不可能为其他玩家发送命令。

    命令必须以前缀“Cmd”开头,并在其上具有[Command]自定义属性,如下所示:

    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. public class SpaceShip : NetworkBehaviour
    4. {
    5. bool alive;
    6. float thrusting; // 推进力
    7. int spin;
    8. [Command]
    9. public void CmdThrust(float thrusting, int spin)
    10. {
    11. if (!alive)
    12. {
    13. this.thrusting = 0;
    14. this.spin = 0;
    15. return;
    16. }
    17. this.thrusting = thrusting;
    18. this.spin = spin;
    19. }
    20. [ClientCallback]
    21. void Update()
    22. {
    23. int spin = 0;
    24. if (Input.GetKey(KeyCode.LeftArrow))
    25. {
    26. spin += 1;
    27. }
    28. if (Input.GetKey(KeyCode.RightArrow))
    29. {
    30. spin -= 1;
    31. }
    32. // this will be called on the server
    33. CmdThrust(Input.GetAxis("Vertical"), spin);
    34. }
    35. }

    通过在客户端上正常调用函数来调用命令。但不是在客户端上运行的命令功能,而是在服务器上该客户端的玩家对象上调用它。所以,命令是类型安全的,具有内置的安全性和路由到玩家,并且使用高效的序列化机制来使参数快速调用。

    客户端RPC调用

    客户端RPC调用是服务器对象在客户端对象上发生事件的一种方式。这与命令如何发送消息的方向相反,但概念是相同的。然而,客户端RPC调用不仅可以在玩家对象上调用,还可以在任何NetworkIdentity对象上调用。它们必须以前缀“Rpc”开头并具有[ClientRPC]自定义属性,如下所示:

    联网事件与客户端RPC调用相似,但不是仅调用客户端对象上的函数,而是触发客户端对象上的事件。然后调用为该事件注册的其他脚本 - 使用来自服务器的参数,以便在客户端上实现联网的脚本间交互。事件必须以前缀“Event”开始,并具有SyncEvent自定义属性。

    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. // Server script
    4. public class MyCombat : NetworkBehaviour
    5. {
    6. public delegate void DieDelegate();
    7. public delegate void RespawnDelegate();
    8. bool alive;
    9. int health;
    10. [SyncEvent(channel=1)]
    11. public event TakeDamageDelegate EventTakeDamage;
    12. [SyncEvent]
    13. public event DieDelegate EventDie;
    14. [SyncEvent]
    15. public event RespawnDelegate EventRespawn;
    16. [Server]
    17. void EventTakeDamage(int amount)
    18. {
    19. if (!alive)
    20. return;
    21. if (health > amount) {
    22. health -= amount;
    23. }
    24. else
    25. {
    26. health = 0;
    27. alive = false;
    28. // send die event to all clients
    29. EventDie();
    30. deathTimer = Time.time + 5.0f;
    31. }
    32. }
    33. [ServerCallback]
    34. void Update()
    35. {
    36. if (!alive)
    37. {
    38. if (Time.time > deathTimer)
    39. {
    40. Respawn();
    41. }
    42. return;
    43. }
    44. }
    45. [Server]
    46. void Respawn()
    47. {
    48. alive = true;
    49. // send respawn event to all clients
    50. EventRespawn();
    51. }

    提示

    ?