Network Group

来源:互联网 发布:硬笔字 知乎 编辑:程序博客网 时间:2024/04/28 09:29

Network Group局域网部分




初始化服务器端的方法

public static NetworkConnectionError InitializeServer(int connections, int listenPort);
public static NetworkConnectionError InitializeServer(int connections, int listenPort, bool useNat);

连接服务器端的方法

public static NetworkConnectionError Connect(string IP, int remotePort);
public static NetworkConnectionError Connect(string[] IPs, int remotePort);
public static NetworkConnectionError Connect(string GUID, [DefaultValue("\"\"")] string password);
public static NetworkConnectionError Connect(HostData hostData, [DefaultValue("\"\"")] string password);
public static NetworkConnectionError Connect(string IP, int remotePort, [DefaultValue("\"\"")] string password);
public static NetworkConnectionError Connect(string[] IPs, int remotePort, [DefaultValue("\"\"")] string password);


NetworkConnectionError 也是一个枚举变量,用来接收服务器端初始化或客户端连接的错误信息:

//    // Summary:    //     ///    //     Possible status messages returned by Network.Connect and in MonoBehaviour.OnFailedToConnect|OnFailedToConnect    //     in case the error was not immediate.    //     ///    public enum NetworkConnectionError    {        //        // Summary:        //     ///        //     Client could not connect internally to same network NAT enabled server.        //     ///        InternalDirectConnectFailed = -5,        //        // Summary:        //     ///        //     No host target given in Connect.        //     ///        EmptyConnectTarget = -4,        //        // Summary:        //     ///        //     Incorrect parameters given to Connect function.        //     ///        IncorrectParameters = -3,        //        // Summary:        //     ///        //     Internal error while attempting to initialize network interface. Socket possibly        //     already in use.        //     ///        CreateSocketOrThreadFailure = -2,        //        // Summary:        //     ///        //     Cannot connect to two servers at once. Close the connection before connecting        //     again.        //     ///        AlreadyConnectedToAnotherServer = -1,        //        // Summary:        //     ///        //     No error occurred.        //     ///        NoError = 0,        //        // Summary:        //     ///        //     Connection attempt failed, possibly because of internal connectivity problems.        //     ///        ConnectionFailed = 15,        //        // Summary:        //     ///        //     We are already connected to this particular server (can happen after fast disconnect/reconnect).        //     ///        AlreadyConnectedToServer = 16,        //        // Summary:        //     ///        //     The server is at full capacity, failed to connect.        //     ///        TooManyConnectedPlayers = 18,        //        // Summary:        //     ///        //     We presented an RSA public key which does not match what the system we connected        //     to is using.        //     ///        RSAPublicKeyMismatch = 21,        //        // Summary:        //     ///        //     We are banned from the system we attempted to connect to (likely temporarily).        //     ///        ConnectionBanned = 22,        //        // Summary:        //     ///        //     The server is using a password and has refused our connection because we did        //     not set the correct password.        //     ///        InvalidPassword = 23,        //        // Summary:        //     ///        //     The NAT target we are trying to connect to is not connected to the facilitator        //     server.        //     ///        NATTargetNotConnected = 69,        //        // Summary:        //     ///        //     Connection lost while attempting to connect to NAT target.        //     ///        NATTargetConnectionLost = 71,        //        // Summary:        //     ///        //     NAT punchthrough attempt has failed. The cause could be a too restrictive NAT        //     implementation on either endpoints.        //     ///        NATPunchthroughFailed = 73    }


NetworkPeerType表示和判断当前端的状态

public static NetworkPeerType peerType { get; }
Network.peerType用来接收当前端的状态,用来存储一个NetworkPeerType的枚举变量 

NetworkPeerType为一个枚举型变量,可以表示端的各种状态
//    // Summary:    //     ///    //     Describes the status of the network interface peer type as returned by Network.peerType.    //     ///    public enum NetworkPeerType    {        //        // Summary:        //     ///        //     No client connection running. Server not initialized.        //     ///没有客户端连接,客户端未初始化        Disconnected = 0,        //        // Summary:        //     ///        //     Running as server.        //     ///服务器端运行        Server = 1,        //        // Summary:        //     ///        //     Running as client.        //     ///客户端运行        Client = 2,        //        // Summary:        //     ///        //     Attempting to connect to a server.        //     ///连接到了一个服务器端        Connecting = 3    }



OnServerInitialized在服务器端运行,当服务器被初始化时被调用


void OnServerInitialized();


OnPlayerConnected在服务器端运行,当有客户端连接时被调用


void OnPlayerConnected(NetworkPlayer player);

参数NetworkPlayer player包含连接服务器的player的序号信息


OnConnectedToServer在客户端运行,当连接到服务器时被调用:


void OnConnectedToServer();


Network.player能够得到当前本地实例的NetworkPlayer


int group = int.Parse(Network.player + "");

Instantiate在局域网中创建Object:


public static Object Instantiate(Object prefab, Vector3 position, Quaternion rotation, int group);

int group = int.Parse(Network.player + "");



Network View用于数据通信


想要让在每个端创建的GameObject在其他端同步,还要在GameObject添加Network View组件。
 network view组件用来在局域网内同步一个游戏物体的组件属性
 network view会把创建出来他的客户端作为主人,其他客户端的数据都以创建他出来的客户端为准
 只有当创建出来它的客户端的物体组件属性改变时,其他客户端才会同步数据
 network view的state synchronization属性在5.0以上版本unity为数值,在5.0以下版本总共有三种属性

Properties 属性
  • State Synchronization
    状态同步
    The type of State Synchronization used by this Network View
    通过网络视图生效的状态同步的类型
  •     Off 关闭
    No State Synchronization will be used. This is the best option if you only want to send RPCs
    如果你只使用RPCs最好关闭状态同步功能。
  •     Reliable Delta Compressed
        延迟的使用压缩的可靠性
    The difference between the last state and the current state will be sent, if nothing has changed nothing will be sent. This mode is ordered. In the case of packet loss, the lost packet is re-sent automatically
    发生变化的状态会被通过网络传递,如果没有变化,没有传递。这种模式是次序化得,因此,如果有包丢失,丢失的包会自动重传。
  •     Unreliable 不可靠的
    The complete state will be sent. This uses more bandwidth, but the impact of packet loss is minimized
    完整的传递所有状态。这会导致更多带宽被占用,但因为丢包而导致的影响会降到最低。
  • Observed
    被观察的对象
    The Component data that will be sent across the network
    会通过网络进行同步的组件数据。
  • View ID 视图编号
    The unique identifier for this Network View. These values are read-only in the Inspector
    网络视图的唯一编号,这个值是只读的。
  •     Scene ID 场景编号
    The number id of the Network View in this particular scene
    在当前视图里的网络视图的数字编号。
  •     Type 类型
    Either saved to the Scene or Allocated at runtime
    这个选项将决定是在视图中预先创建或是实时创建。


state synchronization是一个枚举型变量,其变量内容如下所示:

 //    // Summary:    //     ///    //     Different types of synchronization for the NetworkView component.    //     ///    public enum NetworkStateSynchronization    {        //        // Summary:        //     ///        //     No state data will be synchronized.        //     ///        Off = 0,        //        // Summary:        //     ///        //     All packets are sent reliable and ordered.        //     ///        ReliableDeltaCompressed = 1,        //        // Summary:        //     ///        //     Brute force unreliable state sending.        //     ///        Unreliable = 2    }


状态同步的细节 State Synchronization Details


You can enable State Synchronization per Network View by choosing either Reliable Delta Compressed or Unreliable from the State Synchronization drop-down. You must then choose what kind of data will synchronized in the Observed property.

每个NetworkView都能通过在状态共享下拉菜单中选择可靠的有延迟的压缩或者不可靠的选项来开启状态共享,而在Observed(观察者)属性中必须选择设定同步的数据引用。

Unity can pack/unpack some specific classes: Transform, Animation, Rigidbody and MonoBehaviour.

Unity可以打包/解包一些特殊的类:如变换,动画,刚体,或者是组件。

Transforms are serialized by storing position, rotation and scale. Parenting information is not transferred over the network.

变换被设计用来保持位置,角度,尺寸。而父层次信息不会通过网络传输。

Animation serializes each running animation state, that is time, weight, speed and enabled.

动画内含每一个运行中的动画状态,如时间,重力,速度,和是否激活。

Rigidbody serializes position, rotation, velocity and angular velocity.

刚体包含了位置,角度,速度和角速度。

Scripts (MonoBehaviours) call the function OnSerializeNetworkView().

脚本(组件对象)调用OnSerializeNetworkView()函数。

Reliability and bandwidth 可靠性和带宽

Network Views currently support two types of reliability. Reliable Delta Compressed and Unreliable.

网络视图当前支持两种类型的可靠性设定。压缩的延迟的可靠性和不可靠。

Both have their own advantage and disadvantages, and the right mode should be chosen on a case by case basis.

这两种都有着自己的优势和劣势,正确的模式应该具体问题具体分析。

For additional information about minimizing bandwidth, please read the Minimizing Bandwidth page.

更多关于最小化带宽的附加信息,请查阅Minimizing Bandwidth page。

Reliable Delta Compressed 压缩的延迟的可靠性

Reliable Delta Compressed mode will automatically compare the data that was last received by the client. If no data has changed compared to it, no data will be sent. But on top of that the data will also be compared on a per property basis. For example, if your position has changed but your rotation has not. Only the position has to be sent across the network.

RDC(压缩的延迟的可靠性,我简写了,大家没意见吧)模式自动比对最后从客户端接收的数据。如果没有变化,没有数据会被发送。由于这个过程是按属性进行的,那么举个例子,如果你的位置变了,但角度没变,那么只有位置会被通过网络发送。

In this mode, Unity internally packs one bit prior to each property that determines if the data has actually changed. If it has not changed, the property will not be included in the serialized data thus saving a lot of bandwidth.

在这种模式下,如果数据确实的改变了,Unity内部会将改变了的每个属性转换成位。如果没有改变,属性不会被包括尽串行数据汇中,因此会节约大量带宽。

Unity will also ensure that every packet that is sent will arrive by resending the packet in the case of UDP packet drop until it is received. This means that if a packet is dropped, any packets sent later will not be applied until the dropped packet is re-sent and received. Until then, all later packets will wait in the buffer.

Unity会确保被发送的每一个包都会到达,甚至是在UDP包丢失的情况下也会通过重发确保其被送达。这意味着如果有一个包丢失,直到丢失的包被重发接收之前,所有之后发送的包都不会被应用,所有后发的包会等待在缓冲中。

Unreliable 不可靠

In Unreliable mode, Unity will send out the current state regardless of if it has changed or not. State will not be delta compressed since it is unknown if the sent data will actually arrive on the receiver.

在不可靠模式下,Unity会发送所有的状态而不管它是否改变。状态不会压缩的延迟,无法得知发送的数据是否被接收者收到。

Deciding which method to use 决定使用何种方法

The Network layer uses UDP which is an unreliable unordered protocol but it can send reliable ordered packets, just like TCP does. It internally uses ACKs and NACKs to control packet transmission, ensuring no packets are dropped. The downside to using reliable ordered packets is that if a packet is dropped or delayed, everything stops until that packet has arrived safely. This can cause noticeable delays in transmission in lag intensive networks.

网络层使用UDP工作,这是一种不可靠无次序的协议,但它也能发送可靠次序的包,就如同TCP能做到的一样。内在的它使用ACKs和NACKs(确认和反确认)来控制包的传输,可以保证没有包丢失。使用可靠次序的包的机制,在一个包丢失或者延迟的情况下,会带来性能损失。在丢失的包安全到达前所有的事情都会暂停。在滞后的网络条件下,这会导致明显能被察觉的延迟。

Unreliable sending is useful for data where you know that it is going to change every frame anyway. For example, in a racing game, you can practically rely on that the player's car is always moving. Thus delta compression and reliable transfer only adds overhead without adding an practical gain.

不可靠的发送对于你所发现的每帧都会发生变化的数据是非常有用的。例如,一个赛车游戏几乎完全依赖玩家的车体始终不停的移动。然而延迟的压缩和可靠传输只会增加增加你的管理费用而不会增加你的收入。(隐寓)

In general, you should use Unreliable sending when you know data is changing all the time and minimizing lag is critical. If the data tracked by the Network View is not changing every frame and bandwidth is important to you, then delta compressed is preferred.

通常来说,当你发现数据总是变化而且需要最小化数据延迟,你应该使用不可靠的传输。如果网络视图追踪的数据并不是每帧都发生变化,而且带宽对你来说更重要的话,请使用延迟的压缩模式。

It is important to understand that lag is not the same thing as bandwidth. They are two separate properties that you want to optimize for in different use case.

有一点很重要,延迟和带宽并不是同一件事。他们是在你想要为不同场景优化时存在的两个分离的属性。

Prediction 预测

When the server has full authority over the world state, the clients only update the game according to these states they receive from the server. One problem which arises is that controls feel unnatural as when a player pushes the forward button for example, he won't move until the updated state is received from the server. This delay depends on the latency of the connection so the worse the connection the more unnatural the actions of the player become.

当服务器全权管理世界状态时,客户端只是根据他们从服务器接收的状态更新游戏。当一个用户按住向前按钮时可能会出现意外,控制会变得不自然。在直到状态从服务器返回前他的角色不能移动。基于连接的延迟在较差的连接下会使用户的动作变得更糟。

One way to help with this is Player Prediction which means the client, knowing how the server calculates his movement, predicts the movement himself. So the player moves instantly with the control but the server sees his position from his last update. When the state update arrives from the server, the client will compare what he predicted with what actually happened. This might differ as the server might know more about the environment around the player, the client just knows what he needs to know. Errors in prediction are corrected as they happen, if they are corrected gradually the correction will look more smooth and less noticeable.

解决之道是客户端的角色预判技术,假设服务器会如何计算角色的移动,并预测角色的移动情况。因此用户角色即时的跟随用户的控制移动但在服务器看来角色最后的位置并没有移动。当状态的更新到达服务器时,客户端会比较他对角色的预测和服务器内实际发生的变化。服务器可能更多的了解客户端周围的环境,客户端却只知道他需要知道的部分,这两者间是有差异的。预判的错误发生时会得到修正,如果他们被逐步的修正屏幕上看起来会更加细腻而更少被玩家所察觉。

Dead reckoning or interpolation/extrapolation 航位推测法或内插/外插法

It is possible to apply the same principle with player prediction to the opponents of the player. Extrapolation is when several last (buffered) known position, velocity and direction of an opponent is used to predict where he will be in the next frames. When the next state update finally arrives with the correct position, the client state will be updated with accurate information, possibly skipping if the prediction was bad. In FPS games the behavior of players can be very erratic so this kind of prediction only has limited effect. If the lag gets high enough the opponent will skip badly as the errors in prediction get larger.

如果可能请给玩家角色以外的角色也使用同样的预测技术。外推(法)是指当几个最近(缓冲)确认的对手位置、对手速度和对手方向被用于预测玩家角色下一帧会出现的位置。当下一个状态最终被正确的位置更新时,客户端的状态会被精确的信息更新,如果预测错误可能会出现闪烁。在每秒帧数比较重要的游戏中,角色的行为会变得非常古怪,因此这种预测只能带来有限的效果。足够高的延迟情况下,预测会产生更大的错误而使对手的位置飘忽不定而变得更糟。

Interpolation is when packets get dropped on the way to the client and the opponent position would normally pause and then jump to the newest position when a new packet finally arrives. By delaying the world state by some set amount of time (like 100 ms) and then interpolating the last known position with the new one, the movement between these two points, where packets were dropped, will be smooth.

内插法指发向客户端的包丢失的时候,对手的位置一般情况下会暂停,然后当最终一个新的包送到本地时对手会跳跃至最新的位置。通过设定世界状态的延迟的数值(比如100ms),然后通过外插法根据最后的已知位置得出新的在两点中的移动位置。这种做法在有包丢失的情况下,会使得运动变得柔和。


物体移动代码:

using UnityEngine;using System.Collections;public class MyCube : MonoBehaviour {    public int speed = 5;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {        float h = Input.GetAxis("Horizontal");        float v = Input.GetAxis("Vertical");transform.Translate(new Vector3(h * speed * Time.deltaTime, 0, v * speed * Time.deltaTime));}}











局域网创建代码如下所示:

using UnityEngine;using System.Collections;/// <summary>/// 既是服务器端,也是客户端/// </summary>public class MyNetwork : MonoBehaviour {    public int connections = 10;   //连接数量上限    public int listenPort=8899;    //端口号    public bool useNat = false;    //Nat是否开启    public string ip = "127.0.0.1";//主机ip    public GameObject playerPrefab;//所要创建的GameObject     void OnGUI()    {        if (Network.peerType == NetworkPeerType.Disconnected)        {                        if (GUILayout.Button("Initialize Server."))            {                //初始化服务器端                NetworkConnectionError error = Network.InitializeServer(connections, listenPort, useNat);                print(error);            }            if (GUILayout.Button("Connected Server."))            {                //连接服务器端                NetworkConnectionError error=Network.Connect(ip, listenPort);            }        }        //如果peerType为服务器端时        else if(Network.peerType==NetworkPeerType.Server)        {            GUILayout.Label("Server has been initialize.");        }        //如果peerType为客户端时时        else if(Network.peerType==NetworkPeerType.Client)        {            GUILayout.Label("Client has been connected.");        }    }      /// <summary>    /// 在服务器端运行,当服务器被初始化时调用    /// </summary>    void OnServerInitialized()    {        print("Server has been Inintialize.");        //获得当前服务器或客户端的编号转换为int        int group = int.Parse(Network.player + "");        //在局域网中实例化一个对象        //参数:实例的对象,坐标,旋转,编号         Network.Instantiate(playerPrefab, new Vector3(0, 10, 0), Quaternion.identity, group);    }    /// <summary>    /// 在服务器端运行,当有player连接时被调用    /// </summary>    /// <param name="player">连接服务器的player的序号信息</param>    void OnPlayerConnected(NetworkPlayer player)    {        print("Player Connected,index number:"+player.ToString());    }    /// <summary>    /// 在客户端运行,当连接到服务器时运行    /// </summary>    void OnConnectedToServer()    {        print("Connected server successfully.");        int group = int.Parse(Network.player + " ");        Network.Instantiate(playerPrefab, new Vector3(0, 10, 0), Quaternion.identity, group);    }}


注意:

在PlayerSettings中的Settings for Web Player和Settings for PC,Mac & Linux Standalone下面,都有这么一句

 

Run in backgroundCheck this if you dont want to stop executing your game if the player looses focus.

 

勾选这个选项可以让你的播放器在失去焦点的情况下继续执行游戏(编辑器下也可以)。

可以看到,PlayerSettings中的Run in background后面有一个字符*,也就是Run In Background*

后面还有一句提示:* shared setting between multiple platform

也就是说,后面带有*的设置是多个平台共享通用的

就如Run In Background这个选项被WebPlayer和Standalone这两个平台共享使用,当其中一个平台下勾选了或者勾掉了这个选项,另外一个平台下也会同时勾选或勾掉。

这个选项也可以在脚本中用代码控制:

Application.runInBackground=ture;这可以使游戏在失去焦点的时候继续运行(编辑器下也可以)。默认值为false。

当运行这句代码时,PlayerSettings下面的Run In Background选项会做出相应的更改。

 

Run In Background这个选项只在WebPlayer和Standalone这两个平台下才有,是否意味着在别的平台下不能后台运行呢?


0 0
原创粉丝点击