Server player movement running same on all clients

I am a newbie in bolt.
So I made my own simple movement scripts which doesn't use server authoritative movement and uses rigidbody to move the player around.

The problem is I can't move or rotate the clients individually, but when I move or rotate the server player, all clients also does same. They move and rotate with server player.

I will explain my Setup so far:
I used the same scripts from advanced tutorial of spawning the player by creating server or client player, etc. In addition to that I made a singleton prefab - "GameManagerController" whose job is to look for objects with tag "SpawnPoint" and store them in array. Then get the random spawn point for spawning the player.

Here are the codes:

Player Controller (this class takes input from player):
public class PlayerController : Bolt.EntityBehaviour<ISniperPlayerState>
{
    [SerializeField] private float moveSpeed = 10f;
    [SerializeField] private float lookSensitivity = 3f;

    PlayerMotor motor;

    private void Awake()
    {
        motor = GetComponent<PlayerMotor>();
    }

    public override void Attached()
    {
        state.SetTransforms(state.Transform, transform);
    }

    public override void SimulateOwner()
    {
        //Movement region
        #region
        float _xMov = Input.GetAxis("Horizontal");
        float _zMov = Input.GetAxis("Vertical");

        Vector3 _moveHorizontal = transform.right * _xMov;
        Vector3 _moveVertical = transform.forward * _zMov;

        //Final Movement
        Vector3 _velocity = Vector3.zero;

        _velocity = (_moveHorizontal + _moveVertical) * moveSpeed;

        //Apply movement
        motor.Move(_velocity);
        #endregion

        //Rotation region
        #region
        var _yRot = Input.GetAxis("Mouse X");
        var _xRot = Input.GetAxis("Mouse Y");

        var _rotation = new Vector3(0f, _yRot, 0f) * lookSensitivity;

        motor.Rotate(_rotation);

        var _cameraRotationX = _xRot * lookSensitivity;

        motor.RotateCamera(_cameraRotationX);
        #endregion
    }
}
PlayerMotor (this class applies motion by taking input from player controller):

[RequireComponent (typeof(Rigidbody))]
public class PlayerMotor : MonoBehaviour
{
    private float cameraRotationX = 0f;
    private float currentCameraRotationX = 0f;

    [SerializeField] private float cameraRotationLimit = 85f;

    Vector3 velocity = Vector3.zero;
    Vector3 rotation = Vector3.zero;
    Rigidbody _rb;

    [SerializeField] Camera cam;

    private void Awake()
    {
        _rb = GetComponent<Rigidbody>();
        cam = CameraController.instance.myCamera;
    }

    public Vector3 Velocity
    {
        get { return _rb.velocity; }
    }

    public void Move(Vector3 _velocity)
    {
        velocity = _velocity;
    }

    public void Rotate(Vector3 _rotation)
    {
        rotation = _rotation;
    }

    public void RotateCamera(float _cameraRotationX)
    {
        cameraRotationX = _cameraRotationX;
    }

    private void FixedUpdate()
    {
        PerformMovement();
        PerformRotation();
    }

    void PerformMovement()
    {
        if (velocity != Vector3.zero)
            _rb.MovePosition(_rb.position + velocity * BoltNetwork.frameDeltaTime);

        //rb.AddForce(jumpForce /* * Time.fixedDeltaTime*/, ForceMode.Impulse);
    }

    void PerformRotation()
    {
        _rb.MoveRotation(_rb.rotation * Quaternion.Euler(rotation));
        if (cam != null)
        {
            //cam.transform.Rotate(-cameraRotation);

            //New Camera Rotation code
            currentCameraRotationX -= cameraRotationX;
            currentCameraRotationX = Mathf.Clamp(currentCameraRotationX, -cameraRotationLimit, cameraRotationLimit);

            cam.transform.localEulerAngles = new Vector3(currentCameraRotationX, 0</f, 0f);
        }
    }
}
Here is how I spawn my player:

[BoltGlobalBehaviour(BoltNetworkModes.Server, "Prototype_Level1")] public class NetworkCallbackTest : Bolt.GlobalEventListener { void Awake() { SniperPlayerRegistry.CreateServerPlayer(); } public override void Connected(BoltConnection connection) { SniperPlayerRegistry.CreateClientPlayer(connection); } public override void SceneLoadLocalDone(string map) { GameManagerController.Instantiate(); GameManagerController.instance.SetupSpawnPoints(); SniperPlayerRegistry.ServerPlayer.Spawn(); //GameObject spawnPoint = GetRandomSpawnPoint(); //BoltNetwork.Instantiate(BoltPrefabs.SniperPlayer, spawnPoint.transform.position, spawnPoint.transform.rotation); } public override void SceneLoadRemoteDone(BoltConnection connection) { SniperPlayerRegistry.GetPlayer(connection).Spawn(); } }

Comments

  • For non authoritative you need to spawn the local player on the client like in the Getting Started docs
  • Okay thanks, that works.
    Here is the latest code:
    
    [BoltGlobalBehaviour]
    public class NetworkCallbackTest : Bolt.GlobalEventListener
    {
        GameObject spawnPoint;
        BoltEntity character;
    
        public override void SceneLoadLocalDone(string map)
        {
            GameManagerController.Instantiate();
            GameManagerController.instance.SetupSpawnPoints();
    
            if (GameManagerController.instance != null)
                spawnPoint = GameManagerController.instance.FindRandomSpawnPoint();
    
            character = BoltNetwork.Instantiate(BoltPrefabs.SniperPlayer, spawnPoint.transform.position, spawnPoint.transform.rotation);
            character.TakeControl();
        }
    }
    
    Is the calling of TakeControl() method correct or some conditions needs to be checked first?
    One more question, how do I get the camera per player? Because playermotor script is dependent on camera to rotate around. Since CameraController is another singleton prefab spawned per player.

    My CameraController:
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CameraController : BoltSingletonPrefab<CameraController>
    {
        [SerializeField] Transform Cam;
    
        public Camera myCamera
        {
            get { return Cam.GetComponent<Camera>(); }
        }
    
        private readonly string newName = "PlayerCamera";
    
        void Awake()
        {
            DontDestroyOnLoad(gameObject);
        }
    
        // Setup the camera with the default view
        public void Configure(BoltEntity entity)
        {
            Debug.Log("Configure Called on player camera");
            Transform CameraPos = entity.transform.Find("CameraPos");
    
            gameObject.transform.name = newName;
            gameObject.transform.parent = CameraPos;
            gameObject.transform.position = CameraPos.position;
            gameObject.transform.rotation = CameraPos.rotation;
            //gameObject.transform.localPosition = new Vector3(0, 100, 0);
            //gameObject.transform.localRotation = Quaternion.Euler(90f, 0, 0);
        }
    }
    
    This is how PlayerMotor tries to access the camera:
    cam = CameraController.instance.myCamera;
  • You don't need to use TakeControl or anything related to control if you're not using commands ie not server authoritative

    "how do I get the camera per player?"
    Not sure what you mean. All movement logic of the player you own is on your client, you just use the local singleton camera.
  • If I don't use TakeControl the CameraController is spawned at the middle of map and not assigned as child of player. I call the CameraController Configure() method from ControlofEntityGained() method or something like that called.

    About camera lets say by example. One player starts a server, then comes the client player. The Client's playermotor is trying to access the camera from the server player and not it own child camera.