Chom1czek, your example does not solve the task of running a same function on server and client because the code within the ClientRpc is executed on all clients, but not on the server. If you want the code to be run on the server, it will work on hosts only, where you have both server and client in one instance, but it won’t run the code on dedicated servers.
Sahkan, I think your intial approach of using another function call is quite fine. One could just call the function either from server-side (e.g. from a command) or client-side (e.g. from an Rpc). You could even pass a boolean flag like firedOnClient or something. I actually think yours is a clean and structured solution already. Currently, I don’t know other UNET mechanics to achieve this yet, or why there even would be a need to have such. But maybe there are some reasons or use cases.
Honestly, the way to approach something is entirely dependant on what exactly it is you’re trying to do. Maybe it’s something that has use call backs. Maybe it’s something that can be done via an animation event. However, @Chom1czek 's approach does PARTIALLY solve the task…possibly…
[Command]
private void CmdComand()
{
RpcToClients();
//CODE GOES HERE TO EXECUTE THE PROCESS ON THE SERVER.
}
[ClientRpc]
private void RpcToClients()
{
//CODE GOES HERE TO EXECUTE THE PROCESS ON ALL CLIENTS
}
Can I ask a backup question along these lines? I’ve been trying to sync animations for awhile now, and the “Network Animator” script is not working as I thought it would. My unit’s animations sync properly with the Network Animator if I uncheck “Local Player Authority” on my Network Identity script for the object. However, I need my objects to have Local Player Authority in order for them to be spawned and registered with different remote clients. The animations do NOT sync when Local Player Authority is checked, only when it is unchecked – I don’t know why this is.
So using what you guys are discussing, I get the fact that a client needs to call a [Command] to execute a function on the server. However, where does the [ClientRpc] function need to sit? Should it be in a script only located on a server object? Or can it be called from the same object/script as the one that makes the [Command] function call?
@Velo222 I’ll expand on my example/suggestion a bit more.
public class PlayerInput : NetworkBehaviour
{
public Material thisMaterial;
void Update()
{
if(Input.GetKey(Keycode.SPACE))
CmdChangeColor(); //This sends a request to the server to execute the "CmdChangeColor" function on the server.
}
public void ChangeColor()
{
thisMaterial.color = new Color(255, 255, 255,255);
}
[Command]
public void CmdChangeColor()
{
RpcClientChangeColor(); //This sends a message from the server to all connected clients that have THIS GameObject and tells them to execute all code inside the "RpcClientChangeColor" function.
ChangeColor(); //This executes the "ChangeColor" function on the server ONLY.
}
[ClientRpc]
public void RpcClientChangeColor()
{
ChangeColor(); //This executes the "ChangeColor" function on the client ONLY.
}
}
All this code exists in a single script on the Player GameObject. When the player presses the SPACE BAR the Command portion is executed on the SERVER, which in turn sends a message to all connected clients to execute the ClientRpc portion.
I just use SyncVar hooks if it’s something like changing a color. This way all you have to do is call the function on the server, and it will also do the same thing on all clients. Plus it’s buffered so it works on future clients, very simple!
[SyncVar(hook="SetColor")]
public Color32 MyColor;
public override void OnStartClient()
{
SetColor(MyColor);
}
public void SetColor(Color32 color)
{
MyColor = color;
GetComponent<MeshRenderer>().material.color = MyColor;
}
I wouldn’t normally write nonsense like this, but if you run DoSomething() the method something() will be called on the server and all clients no matter who is calling it, as long as if a client it has the proper authority over the object to issue commands.