so i want to get into Unity by making a small Multiplayer FPS, but something doesn’t quite work…
I have a bullet that is a rigidbody that gets spawned , has Network Identity and Network Transform Script and is a registered Spawnable Prefab in the Network Manager, and everything seems to work fine from host side, i can shoot and the bullets also appear on client side, but when i shoot as client the bullets get spawned on client but not on host, i also get an error - "“SpawnObject for dart(clone) (UnityEngine.GameObject), NetworkServer is not active. Cannot spawn objects without an active server”…
My code:
using UnityEngine;
using UnityEngine.Networking;
public class Shoot : NetworkBehaviour {
public GameObject dartPrefab;
public Transform DartSpawn;
void Start () {
dartPrefab = Resources.Load("dart") as GameObject;
}
void Update () {
if (Input.GetMouseButtonDown(0))
{
CmdFire();
}
}
void CmdFire()
{
GameObject newArrow = Instantiate(dartPrefab, transform.position, transform.rotation) as GameObject;
Rigidbody rb = newArrow.GetComponent<Rigidbody>();
rb.velocity = this.transform.forward * 30;
NetworkServer.Spawn(newArrow);
}
}
i think it doesnt work because the client wants to spawn it but because its a client, not a host, it doesnt find a server to communicate with - i read somewhere that i should put a [Command] in front of (or rather above) the void CmdFire, which makes the function being called by client, but executed by server or sth like that, but if i put that there, when i press the shoot button nothing happens at all
please, i’m pretty much a newbie but i want this to work before i move on
First off, on your commands you need to put the [Command] attribute. Also, Commands only get ran on the server. So with your current code even if you put a command attribute, it would only run on the server. This may fix it:
using UnityEngine;
using UnityEngine.Networking;
public class Shoot : NetworkBehaviour {
public GameObject dartPrefab;
public Transform DartSpawn;
void Start () {
dartPrefab = Resources.Load("dart") as GameObject;
}
void Update () {
if (!isLocalPlayer)
return;
if (Input.GetMouseButtonDown(0))
{
CmdFire(transform.position, transform.rotation);
}
}
[Command]
void CmdFire(Vector3 position, Quaternion rotation)
{
RpcClientShot(position, rotation);
}
[ClientRpc]
void RpcClientShot(Vector3 position, Quaternion rotation)
{
GameObject newArrow = Instantiate(dartPrefab, position, rotation) as GameObject;
Rigidbody rb = newArrow.GetComponent<Rigidbody>();
rb.velocity = this.transform.forward * 30;
}
}
Commands are ONLY ran on the server(Or host), and Client Rpc’s are ONLY ran on the clients.If you are having the Network Manager automatically spawn a player on the server, that player is technically a client even though it is hosting the server so Client Rpc’s will still run. Also, when it comes to projectiles i wouldnt sync them on the network. I would just pass the position and rotation to spawn the projectile so you save a LOT of network traffic. If you do want to spawn something with NetworkServer.spawn, make sure you add it to the spawnable prefabs list on the network manager component
The way the code i wrote works is when the client wants to shoot, It runs the CmdFire command. This command is ran ONLY on the server (Very useful for stuff you dont want other clients to run, like killing a player!). The RpcCientShot is ran on ALL clients but not the server. So all this is doing is when you shoot, if tells the server “Hey, I want to shoot!” then the server receives that message and proceeds to tell all clients that you shot!
Thank you for the answer - i replaced the code in my script with yours, but like when i just added the [Command] myself, it still doesn’t do anything at all, and i continuosly get 2 error messages in the console (a LOT of them - i suppose each Update() another one)
There is no NetworkIdentity on this object. Please add one.
UnityEngine.Networking.NetworkBehaviour:get_isLocalPlayer()
Shoot:Update() (at Assets/Own Assets/Scripts/Shoot.cs:13)
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.Networking.NetworkBehaviour.get_isLocalPlayer () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBehaviour.cs:21)
Shoot.Update () (at Assets/Own Assets/Scripts/Shoot.cs:13)
i mean apparently something improtant is missing a Network Identity, but i don’t know what - the player prefab as well as the bullet prefab have one
btw, i have the Shoot script on a GameObject, which is a child of a gun model, which is a child of the player cam, which is a child of the player itself - maybe this is causing problems? because according to the error message there seems to be a problem with the isLocalPlayer, so maybe i placed the script at the wrong place in the hierarchy so it is confused because it cant find the LocalPlayer? at least that would be my assumption