最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Unity Mirror multiplayer - Make GameObject visible to only 1 player - Stack Overflow

programmeradmin5浏览0评论

How can I make a GameObject visible to only one specific player in a Unity multiplayer game using Mirror? The method I’m using works correctly when a non-host client picks up the object (it becomes invisible for everyone else). However, when the host picks it up, the object remains visible for all players instead of only the host. Does anyone knows how to fix this?

Here is my code:

[Command]
public void CmdHideObject()
{
    var script = FindObjectOfType<HideScript>();
    script.HideObject(connectionToClient);
}

[Server]
public void HideObject(NetworkConnectionToClient client)
{
    SetObjectVisibility(false);
    TargetSetActive(client);
}

private void SetObjectVisibility(bool visible)
{
    GetComponent<Renderer>().enabled = visible;
    foreach (var image in GetComponentsInChildren<Image>())
    {
        image.enabled = visible;
    }
}

[TargetRpc]
private void TargetSetActive(NetworkConnectionToClient client)
{
    SetObjectVisibility(true);
}

The GameObject that I want to hide has Network Identity and Network Transform attached to it. It has 6 children, of which 2 contain Image component, so that is the reason I am disabling Image components as well.

How can I make a GameObject visible to only one specific player in a Unity multiplayer game using Mirror? The method I’m using works correctly when a non-host client picks up the object (it becomes invisible for everyone else). However, when the host picks it up, the object remains visible for all players instead of only the host. Does anyone knows how to fix this?

Here is my code:

[Command]
public void CmdHideObject()
{
    var script = FindObjectOfType<HideScript>();
    script.HideObject(connectionToClient);
}

[Server]
public void HideObject(NetworkConnectionToClient client)
{
    SetObjectVisibility(false);
    TargetSetActive(client);
}

private void SetObjectVisibility(bool visible)
{
    GetComponent<Renderer>().enabled = visible;
    foreach (var image in GetComponentsInChildren<Image>())
    {
        image.enabled = visible;
    }
}

[TargetRpc]
private void TargetSetActive(NetworkConnectionToClient client)
{
    SetObjectVisibility(true);
}

The GameObject that I want to hide has Network Identity and Network Transform attached to it. It has 6 children, of which 2 contain Image component, so that is the reason I am disabling Image components as well.

Share Improve this question asked yesterday Davor HomaDavor Homa 1 1
  • Could you show how exactly these methods are called? In general it seems that SetObjectVisibility(false); is only ever executed on the server so how is this forwarded to clients? – derHugo Commented yesterday
Add a comment  | 

2 Answers 2

Reset to default 0

Sounds less than a Mirror related problem that just scripting. You could use a dual camera setup for each player, like FPSs usually do to draw weapons on the screen independently of environment geometry (so that the model doesn't clip through meshes if you get close to a wall).

You make two cameras, with the exact same behavior, except that one has its culling mask set to render objects on the current player's client layer (which you have to set in projects props), and the other renders everything except the client layer.

When you pick up an object, you just have to change the layer on which the gameobject and its children are on: you put them on all on the client mask. This way, other player's cameras are simply not rendering it.

This has the downside that, for each players, there has to be an available layer for its Client camera's culling mask to set on (and for the others to exclude). So if your game is 8 players, there has to be 8 layers. It makes this solution rather inelegant, because you rely on the editor max layer count, but except if you plan on making your game playable by more player than you can declare layers on, which shouldn't be the case, then you're good.

To summarize:

  • Create as many layers as you can have max player. ie, 8 players game, 8 layers named ClienLayer[1-8]
  • Make it so that the player prefab contains 2 cameras, both behaving the same way.
  • One camera should have a culling mask containing everything EXCEPT ANY ClienLayer
  • The other camera should be given, when connected, a culling mask containing ONLY the ClienLayer corresponding to the player
  • When a player picks an object up, you set that object renderers gameobject's layer the ClienLayer corresponding to the player who picked it up.

The result is:

  • Each player have one camera that draws the environment only
  • Each player have one camera that draws object on a layer exclusive to the Client

Thank you both for your help. derHugo is right, my SetObjectVisibility(false); was executed only on server. I changed my HideObject method so it calls ClientRpc method for setting object visibility and now it works.

[Server]
public void HideObject(NetworkConnectionToClient client)
{
    RpcSetObjectVisibility(false);
    TargetSetActive(client);
}

[ClientRpc]
private void RpcSetObjectVisibility(bool visible)
{
    SetObjectVisibility(visible);
}
发布评论

评论列表(0)

  1. 暂无评论