Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Unity3D网络中,如何;不止一个玩家;?_Unity3d_Unity3d Unet_Unet - Fatal编程技术网

在Unity3D网络中,如何;不止一个玩家;?

在Unity3D网络中,如何;不止一个玩家;?,unity3d,unity3d-unet,unet,Unity3d,Unity3d Unet,Unet,我有一个简单的局域网拓扑结构,有一个服务器和三个客户端 -client server -client -client (他们不是字面上的“玩家”) 这三个客户端与服务器通信各种信息。当然,只需使用[Command]调用即可 然而,它们“都是一样的”。也有同样的几个电话 (服务器通过ID知道是哪一个发送了信息。) 起初,我只是生成了一个“player”对象,上面有一个脚本,上面有各种[Command]调用 每个客户端都有一个抽象的player对象

我有一个简单的局域网拓扑结构,有一个服务器和三个客户端

          -client
server    -client
          -client
(他们不是字面上的“玩家”)

这三个客户端与服务器通信各种信息。当然,只需使用
[Command]
调用即可

然而,它们“都是一样的”。也有同样的几个电话

(服务器通过ID知道是哪一个发送了信息。)

起初,我只是生成了一个“player”对象,上面有一个脚本,上面有各种
[Command]
调用


每个客户端都有一个抽象的player对象


它由NetworkManager以通常的方式生成

不过

事实证明,服务器只“相信”连接的最后一个

在Unity网络中似乎只有一个“玩家”


真的,在Unity网络中你是如何做到这一点的

回答我自己的问题,对于任何与此抗争的人:

  • 关于“玩家”预置的自动生成,网络会这样做
事实上,每个玩家都会得到一个。(一旦你说出来,似乎很明显。)将会有一大堆这样的东西到处都是

因此,这里:

          -client
server    -client
          -client
事实上,您将看到三个衍生的预制件

(旁白:在我的示例中,我将服务器用作“服务器”,而不是“主机”。)

如果您使用的是“主机”概念,那么其中还会有另一个衍生的玩家预置。)

因此,当你启动应用程序时,只有一台电脑,你将其设为服务器,尚未建立连接

然后你启动第二台电脑,第一台客户端,它们连接。。。现在看起来像这样

然后你启动第三台电脑,第二台客户端,它们连接。。。现在看起来像这样

。。等等

因此,每个客户端都有一个克隆的播放器项。(同样,如果您对服务器使用“主机”概念,这只意味着在与服务器相同的物理机箱上会有另一个客户端。)

每个“玩家”都有自己的自动生成的玩家对象-,并且在所有设备上都有该对象。五个客户端,每个设备上都会有五个自动生成的玩家对象(在所有六个设备上)

那么是什么导致了上面提到的特定bug呢

Unet中隐藏的令人惊讶的困难是
.isLocalLayer
概念

假设您在示例中有一个类似于
Comms
的脚本,它位于播放器预置上,这似乎是很自然的事情。比如说游戏的其他部分必须联系通信(比如向服务器发送消息)

事实上,你必须找到你自己的球员预制

你必须找到你自己的球员预制。。。。 您可以使用类似这样的代码

// laser blows up
// tell Comms to send a message to the server about that
// find Comms ..
Comms co = FindObjectOfType<Comms>();
// tell it to send the message
co.TellServerLaserBlewUp();
//激光爆炸了
//告诉通讯员向服务器发送一条关于这一点的消息
//查找通讯。。
Comms co=FindObjectOfType();
//告诉它发送消息
TellServerLaserBlewUp()公司;
然而,这是错误的,调试将异常不稳定

实际上,您的代码如下所示:

// laser blows up
// tell Comms to send a message to the server about that
// find >> OUR << Comms ..
foreach (Comms co in FindObjectsOfType<Comms>() ) {

    string ilp = co.isLocalPlayer ? "YY" : "NN";
    Debug.Log("I tried one of the many Comms! .. " + ilp);
    if (co.isLocalPlayer) {
        
         Debug.Log("Found it!");
         co.TellServerLaserBlewUp();
    }
}
//激光爆炸了
//告诉通讯员向服务器发送一条关于这一点的消息

//找到>>我们的不是一个完整的答案,因为你已经自己找到了答案

(您没有一个最小的代码示例,所以老实说,我不完全理解您正在做的事情……但是)
无论如何,我想和大家分享一下我通常是怎么做的

在玩家预置(在connect上生成)上,我放置了一个特殊的组件,例如

使用UnityEngine;
使用UnityEngine。联网;
[不允许使用MultipleComponent]
[RequiredComponent(typeof(NetworkIdentity))]
公共类玩家信息:网络行为
{
//只是isLocalLayer的公共访问器
公共bool IsLocalPlayer
{
获取{return isLocalPlayer;}
}
}
如果需要,其他网络行为bool(如
isServer
等)也需要相同的设置

每当我必须从另一个组件调用一个方法时,我也会将
PlayerInformation

->我可以直接检查是否是本地玩家,例如

public void DoSomething(玩家信息播放器)
{
//即使不是本地玩家,也不要再往前走
如果(!player.IsLocalPlayer)返回;
//做你的事
}
现在,关于只向玩家传达某件事的部分,如何称呼某件事:

很遗憾,您无法将
组件
传递给命令和Rpc。。但是您可以传递
游戏对象
(具有网络标识)。NetworkIdentity确保可以在所有连接的实例上识别游戏对象

//这次由客户端调用
[客户]
私人无效剂量()
{
如果(!isLocalPlayer)返回;
//在这里,我们调用传递游戏对象的服务器上的命令
CmdDoSomething(游戏对象);
}
//这是在服务器上执行的
//由于玩家拥有网络身份,服务器可以识别我们传递的正确游戏对象
[命令]
私有void CmdDoSomething(游戏对象玩家)
{
//现在我们可以发回信息了
//例如,一个int或字符串再次通过游戏对象
RPCDO方法(玩家,“测试”);
}
//通常这将由所有客户端执行
//因此,我们必须检查我们是否是最初调用命令的玩家
//NetworkIdentity再次确保我们可以识别传递的游戏对象
[客户端RPC]
私有void RpcDoSomething(游戏对象播放器,字符串消息)
{
//如果我们不是调用命令的人,我们什么也不做
如果(玩家!=游戏对象)返回;
//我喜欢将包含“this”的Debug.Log放在最后,这样您就可以单击日志了
//进入并查看它的确切来源
Log(“我收到:+消息,这个”);
}
现在,只有调用该命令的玩家才应该执行Rpc方法的其余部分(通常由all执行)