- Home /
Using .SetActive() over Unity Network for multiplayer. (Enable weapons on clients)
Hello, I've been struggling to get this right. I've googled around quite a bit and have found examples of other people using [ClientRpc] to activate objects over a network which I am trying to do but I think I am doing it wrong.
What I am trying to do it activate a weapon on my player and have all other clients see the weapon. All the weapons are attached to the player at once but are deactivated at start. When I want the weapon, I call SetActive() and activate the weapon I want.
Here is my full weaponManager Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class WeaponsManager : NetworkBehaviour
{
//The Gameobject holding the weapons
[SerializeField]
GameObject weaponHolder;
//Holds all of the players weapons
[SerializeField]
GameObject[] Weapons;
int weaponNumber = 0; //Used to scroll through weapons in inventory through Weapons Array
//For now just increase weapons when "1" is pressed
private void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
weaponNumber++;
//Apply weapon through out the network
CmdSwapWeapon();
}
}
//Gives the player Their start Weapon
private void Start()
{
weaponNumber = 0;
//Apply weapon through out the network
CmdSwapWeapon();
}
[Command]
void CmdSwapWeapon()
{
//Apply it to all other clients
RpcSwapWeapon();
}
[ClientRpc]
void RpcSwapWeapon()
{
//Disable previous weapon
if (weaponNumber > 0)
Weapons[weaponNumber - 1].SetActive(false);
//If weapon Number is greater than all weapons in inventory, set it to 0 for weapon 1
if (weaponNumber >= Weapons.Length)
{
weaponNumber = 0;
}
//Set current weapon active
Weapons[weaponNumber].SetActive(true);
}
}
If the above is too much, I can split up each method and explain it. Basically all the above script does is on start, it assigns the default weapon. Than when, "1" is pressed, it swaps to a new weapon and deactivates the last weapon
Here is an image of what the script looks like in the editor
The above works on the local player but it does not sync. Please ask if you have any questions.
Answer by FernandoGBR · Oct 01, 2017 at 08:13 AM
Assuming that every player has the authority on his playerPrefab. Assuming that you want a non server-authority model (own players decide themseleves if the weapon switch can be done).
Some things to considerate: - You can only send Rpc from the server instance. - You can only ask for Cmd from the instance that you have the authority.
With all the assumptions and considerations that is what i would do:
Add the weapon manager script to the player prefab (if it is not done)
on update, check if you are the local player (the script will be running for each player instance, and you only want to affect the player that has the authority in that machine). you can do
if(isLocalPlayer)
orif(hasAuthority)
. If you arent justreturn
From update, call to
localSwapWeapon
. This function will do what currently is inside your RPC, also thatcurrentWeapon++
Also from update, do the following:
if(isServer){ RpcSwap(); }else{ CmdSwap(); }
this will ask all the clients to swap if you are the server, or the sewrver to swap if you are a client
RpcSwap will only call localSwap . Making the clients that receive the rpc to update
CmdSwap will call localSwap and RpcSwap. Making the host update the changes and distribute them.
On top of RpcSwap ask
if(isLocalPlayer)
and return (because you are receiving back the notification that you started)
Thanks for your help. I've changed the code as followed and it now looks like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class Weapons$$anonymous$$anager : NetworkBehaviour
{
//The Gameobject holding the weapons
[SerializeField]
GameObject weaponHolder;
//Holds all of the players weapons
[SerializeField]
GameObject[] Weapons;
int weaponNumber = 0; //Used to scroll through weapons in inventory
//Gives the player Their start Weapon
private void Start()
{
weaponNumber = 0;
//Apply weapon through out the network
localSwapWeapon();
if (isServer)
{
RpcSwapWeapon();
}
else
{
CmdSwapWeapon();
}
}
private void Update()
{
if (!isLocalPlayer)
return;
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Alpha1))
{
localSwapWeapon();
if (isServer)
{
RpcSwapWeapon();
}
else
{
CmdSwapWeapon();
}
}
}
void localSwapWeapon()
{
weaponNumber++;
//Disable previous weapon
if (weaponNumber > 0)
Weapons[weaponNumber - 1].SetActive(false);
//If we are greater than all weapons in inventory, set it to 0
if (weaponNumber >= Weapons.Length)
{
weaponNumber = 0;
}
//Set current weapon active
Weapons[weaponNumber].SetActive(true);
}
[Command]
void CmdSwapWeapon()
{
//Apply it to all other clients
localSwapWeapon();
RpcSwapWeapon();
}
[ClientRpc]
void RpcSwapWeapon()
{
if (isLocalPlayer)
return;
localSwapWeapon();
}
}
The same issue happens. Both players spawn in and only the local player can see the weapon.
Also on top of that I seem to get a warning in unity: Trying to send command for object without authority.
Both player prefabs in the editor have Local Player Authority selected in the editor.
What do u mean with "Both player prefabs in the editor have Local Player Authority selected in the editor."
You are supposed to have only one player prefab, and set it into the player prefab slot in the network manager. This will make a new player spawn every time a new player joins the network. With the Local Player Authority checkbox marked in the prefab every client will be able to send commands only from their own playerObject.
For clarify how this works, lets talk about what must happen in a mor formal way.
When you launch the host instance lets call it A. a new player is created, the host player. Lets call it A0.
When you launch the client instance, lets call it B. 3 new players are created. A1, which is the client player in the host instance. B0 which is the host player in the client instance. And B1, which is the client player in the client instance. A0 and B1 have player authority for A and B respectively.
When yo do something in A instance, your are supposed to do it on A0. And as you are the host, you only need to ask B0( and other possible C0, D0, ... ) via RPC for do the same thing.
When you do something in B instance (C, D, ...), you are supposed to do it on B1 (C2, D3, ...), who has the authority. Then ask by Command to A1 (which is yourself in the server) to do the same thing and ask the rest (C1, D1, ...) to do the same thing too.
The Trying to send command for object without authority.
warning is just because you are sending Rpc without the authority as i explain u above.
Thank you. It was a stupid mistake on my end. I had attached the Gun Holder to the Camera. So when the Client joined, I disabled his camera, which in turn disabled the guns on the client. But you definitely helped me understand more about networking.
Your answer
Follow this Question
Related Questions
Unity networking tutorial? 6 Answers
Sending Animation Over Network 0 Answers
Requesting data from server 1 Answer
Multiplayer - Opposite names above players 1 Answer
Can a person be both a client and a server? (and more) 0 Answers