Unity Mirror关于服务器上的local player研究

·  阅读 52

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第43天,点击查看活动详情

前言

Local player是指客户端上自己操作的这个player对象。那么服务器上会有local player存在吗?

实例分析

player网络脚本上有如下一些属性,我们研究一下在不同的模式下分别是什么情况:

 public bool isServer => netIdentity.isServer;

/// <summary>True if this object is on the client and has been spawned by the server.</summary>
public bool isClient => netIdentity.isClient;

/// <summary>True if this object is the the client's own local player.</summary>
public bool isLocalPlayer => netIdentity.isLocalPlayer;

复制代码

还是使用Tanks这个例子,在Tanks.cs中添加如下log:

private void Start() {
    Debug.Log("isServer:"+isServer);
    Debug.Log("isClient:"+isClient);
    Debug.Log("isLocalPlayer:"+isLocalPlayer);
}
复制代码

Host模式开启游戏

  • 开启时服务器输出:

image.png

说明Host模式下,服务器上的第一Player(主机玩家)即是在Server上,又是在Client上,并且还是Local Player。这是因为Host模式是共享内存的,服务器的Player和主机客户端的Player是同一个对象。并且这对象在服务器上也是Local Player,这也是因为共享内存,因为local player是记录在NetworkClient上的静态变量。其实正确的理解是,这是Host模式下,主机Client的local player。

  • 客户端连入后服务器输出:

image.png

红框上是服务器上新加入的这个player,同样是同时在服务器和客户端上,只是这个Player不是Local Player。 此时连入的这个客户端上的输出为:

image.png

此时直接输出了两个player的信息,因为连接上服务后,会在客户端上创建所有已有的Player。绿框是之前服务器上的主机player在客户端上的镜像对象,显然isServer是False, isClient是True,而local player是False。红框是当前这个客户端的player,同样isServer是False, isClient是True,但local player是True。

Server Only模式开启游戏

我们使用Server Only模式将上面的操作重复一下看看。

  • 启动Server 服务器没有任何输出,因为没有Player被创建
  • 客户端连入 服务器的输出为:

image.png

看到和上面Host模式的区别了吧。这儿的player只有isServer是True。因为它真的就只在服务器上。另外,此时服务器上是没有local player的,因为local player原本就是客户端的概念。

此时客户端输出为:

image.png

不用多说了,客户端就只有自己这个player,是local player。

为啥要研究这个?

因为我在研读Mirror源码的过程中,看到NetworkIdentity.OnStartServer方法里面有这么一段:

internal void OnStartServer()
{
    // do nothing if already spawned
    if (isServer)
        return;

    // set isServer flag
    isServer = true;

    // set isLocalPlayer earlier, in case OnStartLocalplayer is called
    // AFTER OnStartClient, in which case it would still be falsse here.
    // many projects will check isLocalPlayer in OnStartClient though.
    // TODO ideally set isLocalPlayer when NetworkClient.localPlayer is set?
    if (NetworkClient.localPlayer == this)
    {
        isLocalPlayer = true;
    }
}
复制代码

这个代码是在服务器上运行的,我看到这儿居然在调用NetworkClient.localPlayer,我当时脑子就蒙了。我说服务器上怎么还有客户端代码呢?我当时没想到Host模式,因为看到有Host模式的地方要么就是判断mode,要么就是判断if (conn is LocalConnectionToClient), 这个地方没有任何判断,所以我当时就想,难道纯server模式也可能有local player? 那么他是谁呢?所以就做了这个实验。现在是想通了,真的是只有Host模式才有,而且之所以有是因为共享内存。这儿代码加了一通注释我也没看明白,但看上去就是一个补丁,所以写的随意了点吧。

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改