- Home /
UNet - How do I make Network.Spawn not show the prefab to the user that called it?
I'm currently working on an FPS and I'm trying to network a bullet impact.
I've coded it in such a way that the bullet impact prefab is instantiated on the local client so the client can see where it has shot, which then sends a command to spawn the bullet impact prefab over the network at the same location as the client.
Here's my code:
// Hit is from a raycast
GameObject impact = Instantiate(impactEffect, hit.point, Quaternion.identity);
Destroy(impact, 1.5f);
// Prevents double-instantiation on LAN games
if (!isServer) {
// If you're not the host of the game, send the impact location to the host
CmdSendServerImpactEffectLocation(hit.point);
} else {
// If you are the host of the game, send the impact location to the clients
RpcSendClientImpactEffectLocation(hit.point);
}
[Command]
void CmdSendServerImpactEffectLocation(Vector3 loc) {
GameObject impact = Instantiate(impactEffect, loc, Quaternion.identity);
Destroy(impact, 1.5f);
NetworkServer.Spawn(impact);
}
[ClientRpc]
void RpcSendClientImpactEffectLocation(Vector3 loc) {
GameObject impact = Instantiate(impactEffect, loc, Quaternion.identity);
Destroy(impact, 1.5f);
}
The first part is wrapped in a method, obviously. What I have done here, unfortunately, doesn't work on matchmaking. Since there is no player that is the host/server, the client sees the instantiation happen twice, one locally, and one from the Network.Spawn()
Any suggestions/information about anything relating to my issue is greatly appreciated! Thank you so much! I'm also wondering, is the user that created the matchmaking room considered the host or the server?
Answer by DougRichardson · Nov 19, 2017 at 10:46 PM
Don't use NetworkServer.Spawn, since you only want to start an effect at the same location on each client but do not need to keep anything about it in sync after that.
The code changes below always send the Command to the host but include the netId of the sender. Then you can switch on that netId to determine if you were the connection who sent the original command and, if so, do nothing in that case (to prevent the prefab from being instantiated twice).
WARNING: I did not test the code at all.
// Hit is from a raycast
GameObject impact = Instantiate(impactEffect, hit.point, Quaternion.identity);
Destroy(impact, 1.5f);
// Send the impact location to the host
CmdSendServerImpactEffectLocation(hit.point, netId);
[Command]
void CmdSendServerImpactEffectLocation(Vector3 loc, NetworkInstanceId senderNetId) {
RpcSendClientImpactEffectLocation(loc, senderNetId);
}
[ClientRpc]
void RpcSendClientImpactEffectLocation(Vector3 loc, NetworkInstanceId senderNetId) {
if (netId != senderNetId)
{
GameObject impact = Instantiate(impactEffect, loc, Quaternion.identity);
Destroy(impact, 1.5f);
}
}
I'm sorry, but this isn't a valid answer. The code which I have posted is from a script that is disabled, since they are not the local player. For some reason when I call ClientRpc, it doesn't remotely get the NetworkInstanceId for each client, but it does it for the caller.
Ok, I'm incredibly confused. I was messing around with the solution for a while and then decided to abandon my changes and revert back to an earlier save on my version control. All of a sudden it started working. Thanks for your help! Haha