在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执行)