I have got a problem with Gun not sticking to a Player. It only happens for a client. As you can see on the screen, the gun position is fine for the host(Player on the right). Gun Prefab has Network Identity with Local Player Authority checked, and Network Transform, same for Player. This is my code for Player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class Player : NetworkBehaviour
{
[SerializeField] float speed = 10f;
[HideInInspector] public GameObject playerGun;
public GameObject gunPrefab;
void Update()
{
if (!isLocalPlayer)
{
return;
}
Movement();
if (Input.GetKeyDown(KeyCode.I))
{
CmdGetGun();
}
if (playerGun)
CarryGun();
}
private void Movement()
{
Vector3 position = new Vector3(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * speed;
transform.position += position;
MouseMovement();
}
private void MouseMovement()
{
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
mousePosition.Normalize();
float rotation_z = Mathf.Atan2(mousePosition.y, mousePosition.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotation_z);
}
[Command]
public void CmdGetGun()
{
Debug.Log("SPAWNING A GUN");
playerGun = (GameObject)Instantiate(gunPrefab, transform.position, transform.rotation);
NetworkServer.SpawnWithClientAuthority(playerGun, connectionToClient);
}
public void CarryGun()
{
Debug.Log("carring A GUN");
playerGun.transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z - 1);
playerGun.transform.rotation = transform.rotation;
}
}
I spent days trying to figure it out. I am new to Unity, especially Unet and maybe i do not understand something.
I know the position of a gun is wrong but i will change it after i deal with this problem. For now i just want it to stick to a Player both on Client and Host side.
Problem
This
Command
method is always executed on the server .. so also with the properties on the server.Meaning: You never set
playerGun
on the client side only on the server inSo, since your client never gets its
playerGun
value setCarryGun
is never executed on the client.Solution 1
To avoid that you should use a
ClientRpc
method to set the value also on all clients.Solution 2
This is an alternative solution which does basically the same steps from above but it would not longer need the
CarryGun
method and aNetworkTransform
, making your code more efficient by saving both, method calls and network bandwidth:Instead of spawning the gun on top level in hierarchy to a certain global position and rotation
and than updating it's position and rotation all the time to the player's tranfroms and transfere them separately via the
NetworkTransform
s you could simply make it a child of the Player object itself using e.g.Instantiate(Object original, Vector3 position, Quaternion rotation, Transform parent);
on the server:This should allways keep it in the correct position without having to
Update
and synchronize it's position and rotation all the time and without any further transfere methods and values.All you have to do is again have a
ClientRpc
in order to tell the clients as well to make this gun a a child of your Player using e.g.SetParent(Trasnform parent, bool worldPositionStays)
:and if necessary apply the local position and rotation offsets. Again you could use a value, everyone has acces to or pass it to the
ClientRpc
from the server - your choice ;)so your methods could now look like
Update1
For overcoming the problem with later connected clients refer to this answer.
It suggests using a
[SyncVar]
and overrideOnStartClient
. An adopted version could look like(Note you still need the
ClientRpc
for the already connected clients.)Update2
The method from Update1 might not work because
playetGunNetId
might not be set yet whenOnStartPlayer
is executed.To overcome this you can use a hook method for our
SyncVar
. Something likeNow you shouldn't even need the
ClientRpc
anymore since everything is handled by thehook
for both, already connected and newly connected clients.