Mirror/UNET c# - 即使使用 Command & ClientRpc 也没有对象权限 - 我错过了什么?
Mirror/UNET c# - No authority on object even when using Command & ClientRpc - What am I missing?
长话短说: 我使用 Mirror/Unet 进行了多人聊天,效果很好。我已经做到了,在 x 秒后,显示聊天的游戏对象(“textContainer”)变为非活动状态。我希望这样当客户端 1 按下“提交”时,所有客户端的 textContainer 游戏对象再次激活。但它只适用于按下提交的客户端,而不适用于所有客户端。我已经在 [Client] [Command] 和 [ClientRpc] 中设置了函数,但仍然收到关于对象没有权限的错误。
我认为这是因为客户端 1 没有权限请求客户端 2 激活他们的 UI 面板。我以为 Command 和 ClientRpc 会解决这个问题?
短篇小说: 所以,为了简单起见,假设当客户端 1 按下输入“提交”时,我希望所有客户端的 textContainer 游戏对象都处于活动状态。
我希望有人能指出我正确的方向。干杯。
此脚本将附加到播放器预制件。
public GameObject textContainer;
[Client]
void Update()
{
if (Input.GetAxisRaw("Submit") == 1)
{
CmdActivateChatClientRPC();
textContainer.SetActive(true);
}
}
[Command]
private void CmdActivateChatClientRPC()
{
ActivateChatClientRPC();
}
[ClientRpc]
private void ActivateChatClientRPC()
{
textContainer.SetActive(true);
}
怎么样
客户端->服务器:请求激活
然后
服务器->客户端:单
[SyncVar(hook = nameof(AcivateText))]
bool textActivated = false;
[Command]
private void CmdActivateChatClientRPC()
{
ActivateChatClientRPC();
}
void AcivateText(bool oldval, bool newval)
{
textContainer.SetActive(newval);
}
您没有检查您是否有此对象的 authority。
void Update()
{
// Does your device have the authority over this object?
// only then you can invoke a Cmd
if(!hasAuthority) return;
if (Input.GetAxisRaw("Submit") == 1)
{
CmdActivateChatClientRPC();
textContainer.SetActive(true);
}
}
[Command]
private void CmdActivateChatClientRPC()
{
ActivateChatClientRPC();
}
// This will be executed on ALL clients!
// BUT only for this one instance of this class
[ClientRpc]
private void ActivateChatClientRPC()
{
textContainer.SetActive(true);
}
如果只是您尝试对属于服务器的对象调用命令,那将变得棘手 ;)
您必须通过本地播放器对象中继命令,然后在服务器上将调用转发给相应的对象,例如通过它的网络身份引用实际目标。
对我来说,这听起来有点像你让每个玩家预制件都有这个 class 并且你想在所有这些预制件上调用 RPC。
这只能由服务器完成,例如
void Update()
{
// Does your device have the authority over this object?
// only then you can invoke a Cmd
if(!hasAuthority) return;
if (Input.GetAxisRaw("Submit") == 1)
{
CmdActivateChatClientRPC();
textContainer.SetActive(true);
}
}
[Command]
private void CmdActivateChatClientRPC()
{
foreach (var player in NetworkManager.singleton.client.connection.playerControllers)
{
if (player.IsValid)
{
player.gameObject.GetComponent<YourScriptName>().ActivateChatClientRPC();
}
}
}
似乎 .client.connection.playerControllers
已被删除。
我想在那种情况下你需要一个自定义 NetworkManager
并通过 OnServerConnect
and OnServerDisconnect
自己跟踪它们,有点像
public CustomNetworkManager : NetworkManager
{
public static readonly HashSet<NetworkConnection> players = new HashSet<NetworkConnection>();
public override void OnServerConnect(NetworkConnection conn)
{
base.OnServerConnect(conn);
players.Add(conn);
}
public override void OnServerDisconnect(NetworkConnection conn)
{
base.OnServerDisconnect(conn);
players.Remove(conn);
}
}
然后改为访问
foreach (var player in CustomNetworkManager.players)
{
player.identity.GetComponent<YourScriptName>().ActivateChatClientRPC();
}
长话短说: 我使用 Mirror/Unet 进行了多人聊天,效果很好。我已经做到了,在 x 秒后,显示聊天的游戏对象(“textContainer”)变为非活动状态。我希望这样当客户端 1 按下“提交”时,所有客户端的 textContainer 游戏对象再次激活。但它只适用于按下提交的客户端,而不适用于所有客户端。我已经在 [Client] [Command] 和 [ClientRpc] 中设置了函数,但仍然收到关于对象没有权限的错误。
我认为这是因为客户端 1 没有权限请求客户端 2 激活他们的 UI 面板。我以为 Command 和 ClientRpc 会解决这个问题?
短篇小说: 所以,为了简单起见,假设当客户端 1 按下输入“提交”时,我希望所有客户端的 textContainer 游戏对象都处于活动状态。
我希望有人能指出我正确的方向。干杯。
此脚本将附加到播放器预制件。
public GameObject textContainer;
[Client]
void Update()
{
if (Input.GetAxisRaw("Submit") == 1)
{
CmdActivateChatClientRPC();
textContainer.SetActive(true);
}
}
[Command]
private void CmdActivateChatClientRPC()
{
ActivateChatClientRPC();
}
[ClientRpc]
private void ActivateChatClientRPC()
{
textContainer.SetActive(true);
}
怎么样 客户端->服务器:请求激活
然后
服务器->客户端:单
[SyncVar(hook = nameof(AcivateText))]
bool textActivated = false;
[Command]
private void CmdActivateChatClientRPC()
{
ActivateChatClientRPC();
}
void AcivateText(bool oldval, bool newval)
{
textContainer.SetActive(newval);
}
您没有检查您是否有此对象的 authority。
void Update()
{
// Does your device have the authority over this object?
// only then you can invoke a Cmd
if(!hasAuthority) return;
if (Input.GetAxisRaw("Submit") == 1)
{
CmdActivateChatClientRPC();
textContainer.SetActive(true);
}
}
[Command]
private void CmdActivateChatClientRPC()
{
ActivateChatClientRPC();
}
// This will be executed on ALL clients!
// BUT only for this one instance of this class
[ClientRpc]
private void ActivateChatClientRPC()
{
textContainer.SetActive(true);
}
如果只是您尝试对属于服务器的对象调用命令,那将变得棘手 ;)
您必须通过本地播放器对象中继命令,然后在服务器上将调用转发给相应的对象,例如通过它的网络身份引用实际目标。
对我来说,这听起来有点像你让每个玩家预制件都有这个 class 并且你想在所有这些预制件上调用 RPC。
这只能由服务器完成,例如
void Update()
{
// Does your device have the authority over this object?
// only then you can invoke a Cmd
if(!hasAuthority) return;
if (Input.GetAxisRaw("Submit") == 1)
{
CmdActivateChatClientRPC();
textContainer.SetActive(true);
}
}
[Command]
private void CmdActivateChatClientRPC()
{
foreach (var player in NetworkManager.singleton.client.connection.playerControllers)
{
if (player.IsValid)
{
player.gameObject.GetComponent<YourScriptName>().ActivateChatClientRPC();
}
}
}
似乎 .client.connection.playerControllers
已被删除。
我想在那种情况下你需要一个自定义 NetworkManager
并通过 OnServerConnect
and OnServerDisconnect
自己跟踪它们,有点像
public CustomNetworkManager : NetworkManager
{
public static readonly HashSet<NetworkConnection> players = new HashSet<NetworkConnection>();
public override void OnServerConnect(NetworkConnection conn)
{
base.OnServerConnect(conn);
players.Add(conn);
}
public override void OnServerDisconnect(NetworkConnection conn)
{
base.OnServerDisconnect(conn);
players.Remove(conn);
}
}
然后改为访问
foreach (var player in CustomNetworkManager.players)
{
player.identity.GetComponent<YourScriptName>().ActivateChatClientRPC();
}