- Home /
Problems with synchronizationg networked vehicle
I am trying to make enterable networked vehicle using mirror. For now everything works exept synchronization. Client and server/host sees its own position of vehicle. Looks like its problem with authority (trying to send commands without authority ), this error shows in other clients that arent in vehicle. Authority is assigned to player who is in vehicle. I am using clientRPC to tell server to execute vehicle movement in all clients
vehicle controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class car_controller : NetworkBehaviour
{
public bool is_car_on = false;
private float m_horizontal_input;
private float m_vertical_input;
private float m_sterring_angle;
public WheelCollider fl_w, fr_w;
public WheelCollider rl_w, rr_w;
public Transform fl_t, fr_t;
public Transform rl_t, rr_t;
public float max_steer_angle = 30;
public float motor_force = 50;
[ClientRpc]
public void RpcGet_input()
{
m_horizontal_input = Input.GetAxis("Horizontal");
m_vertical_input = Input.GetAxis("Vertical");
Debug.Log("sent to client");
}
[ClientRpc]
private void RpcSteer()
{
m_sterring_angle = max_steer_angle * m_horizontal_input;
fl_w.steerAngle = m_sterring_angle;
fr_w.steerAngle = m_sterring_angle;
}
[ClientRpc]
private void RpcAccelerate()
{
if (Input.GetKey("left shift"))
{
motor_force = 1300;
}
else
{
motor_force = 800;
}
if (is_car_on == true)
{
fl_w.motorTorque = m_vertical_input * motor_force;
fr_w.motorTorque = m_vertical_input * motor_force;
}
}
[ClientRpc]
private void RpcUpdate_wheel_poses()
{
update_wheel_pose(fl_w, fl_t);
update_wheel_pose(fr_w, fr_t);
update_wheel_pose(rl_w, rl_t);
update_wheel_pose(rr_w, rr_t);
}
private void update_wheel_pose(WheelCollider _collider, Transform _transform)
{
Vector3 _pos = _transform.position;
Quaternion _quat = _transform.rotation;
_collider.GetWorldPose(out _pos, out _quat);
_transform.position = _pos;
_transform.rotation = _quat;
}
private void FixedUpdate()
{
if (is_car_on == true)
{
CmdGet_input();
CmdSteer();
CmdAccelerate();
CmdUpdate_wheel_poses();
}
}
[Command]
void CmdGet_input()
{
RpcGet_input();
Debug.Log("sent to server");
}
[Command]
void CmdSteer()
{
RpcSteer();
}
[Command]
void CmdAccelerate()
{
RpcAccelerate();
}
[Command]
void CmdUpdate_wheel_poses()
{
RpcUpdate_wheel_poses();
}
}
assigning authority
void interact()
{
RaycastHit hit;
if (Physics.Raycast(fps_cam.transform.position, fps_cam.transform.forward, out hit, range) && hit.collider.gameObject.name == "driver_seat_name")
{
if (GameObject.Find("basic_car").GetComponent<seatsController>().in_drivers_entrance == false)
{
if (Input.GetButtonDown("interact"))
{
NetworkIdentity carIdentity = GameObject.Find("basic_car").GetComponent<NetworkIdentity>();
carAuth(carIdentity);
NetworkIdentity identity = NetworkClient.localPlayer.GetComponent<NetworkIdentity>();
playerIdentity = identity;
GameObject.Find("basic_car").GetComponent<seatsController>().CmdEnteringDriver(identity);
}
}
}
}
[Command]
void carAuth(NetworkIdentity carIdentity)
{
carIdentity.AssignClientAuthority(connectionToClient);
}
}
Pleased to see your issue as I think I have the same problem, I am also confused and in need of light on this same issue. Need help. tellthebell
Than @Dennis65 I suggest you watch this and make question and tell us where did you get stuck. @bartektnt55_unity if you are happy with my answer I'd be happy you would accept the answer.
Answer by MilitaryG · Nov 24, 2021 at 03:12 AM
ok this is how I would do it so you get basic understanding I hope it works.I personally use TargetRpc witch needs a target that's why it's commented I think it needs to be passing variables like this
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class car_controller : NetworkBehaviour
{
public bool is_car_on = false;
private float m_horizontal_input;
private float m_vertical_input;
private float m_sterring_angle;
public WheelCollider fl_w, fr_w;
public WheelCollider rl_w, rr_w;
public Transform fl_t, fr_t;
public Transform rl_t, rr_t;
public float max_steer_angle = 30;
public float motor_force = 50;
private void update_wheel_pose(WheelCollider _collider, Transform _transform)
{
Vector3 _pos = _transform.position;
Quaternion _quat = _transform.rotation;
_collider.GetWorldPose(out _pos, out _quat);
_transform.position = _pos;
_transform.rotation = _quat;
}
[Client]
private void FixedUpdate()
{
if (is_car_on == true)
{
CmdSet_input(this.gameObject, Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
/*CmdSteer();
CmdAccelerate();
CmdUpdate_wheel_poses();
*/
}
}
[Command]
void CmdSet_input(GameObject Me, float h, float v)
{
car_controller car = Me.GetComponent<car_controller>();
m_horizontal_input = h;
m_vertical_input = v;
RpcSet_input(/*car.netIdentity, */h, v);
Debug.Log("sent to server");
}
[ClientRpc]
public void RpcSet_input(/*NetworkConnection target, */float h, float v)
{
m_horizontal_input = h;
m_vertical_input = v;
}
}
I think that every function after [whatever] is treated as inside that's why I moved those functions up there.
try if stearing works and it it does than you know the basics to move forward
comment everything else to get basics
In
[Command] functions only work on server on client they aren't run
In
[Client Rpc]functions only work on clients
How to communicate
With parameters
I kinda understand your point but for me it looks like that on other clients calls that are supposed to move car are from local client that is not in vehicle and that client dont have authority because authority is given to client on vehicle, sorry if i am not explaining it clearly
Oh than only check isLocalPlayer also [client] will force to run only on local pc Atributes
Adding isLocalPlayer (at least in FixedUpdate function in car controller) stops working at all
That is because you are using local variables you need to pass it with parentesis like this:
RpcAccellerate(bool acc){
If(acc){
Motorforce...
}
}
Just found something that might be a good idea for you: [Command(requiresAuthority = false)]
okay actually it partially works, client moves doesnt see vehicle's move for himself but host/server see that move. Host/server see his move but of course client doesnt and move can be seen for host/server if only client have is_car_on = true link to video in case you have trouble understanding what i am talking about https://www.youtube.com/watch?v=cEcuYBKZwIU I really appreciate your efforts also I didnt know [Command(requiresAuthority = false)] exists, while its actual game changer for me
also your version of car_controller code if i just did something wrong
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class carController2 : NetworkBehaviour
{
public bool is_car_on = false;
private float m_horizontal_input;
private float m_vertical_input;
private float m_sterring_angle;
public WheelCollider fl_w, fr_w;
public WheelCollider rl_w, rr_w;
public Transform fl_t, fr_t;
public Transform rl_t, rr_t;
public float max_steer_angle = 30;
public float motor_force = 50;
private void update_wheel_pose(WheelCollider _collider, Transform _transform)
{
Vector3 _pos = _transform.position;
Quaternion _quat = _transform.rotation;
_collider.GetWorldPose(out _pos, out _quat);
_transform.position = _pos;
_transform.rotation = _quat;
}
[Client]
private void FixedUpdate()
{
if (is_car_on == true)
{
CmdSet_input(this.gameObject, Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
CmdAccelerate(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
/*CmdSteer();
CmdAccelerate();
CmdUpdate_wheel_poses();
*/
}
}
[Command(requiresAuthority = false)]
void CmdSet_input(GameObject Me, float h, float v)
{
car_controller car = Me.GetComponent<car_controller>();
m_horizontal_input = h;
m_vertical_input = v;
RpcSet_input(/*car.netIdentity, */h, v);
Debug.Log("sent to server");
}
[Command(requiresAuthority = false)]
void CmdAccelerate(float h, float v)
{
m_horizontal_input = h;
m_vertical_input = v;
if (Input.GetKey("left shift"))
{
motor_force = 1300;
}
else
{
motor_force = 800;
}
fl_w.motorTorque = m_vertical_input * motor_force;
fr_w.motorTorque = m_vertical_input * motor_force;
RpcSet_input(/*car.netIdentity, */h, v);
}
[ClientRpc]
public void RpcSet_input(/*NetworkConnection target, */float h, float v)
{
m_horizontal_input = h;
m_vertical_input = v;
}
}
So cmd works
Now you need to set the rpc just as it is done in cmd
How differently have you done for the playre?
Maybe some info to read
okay i hope last but probably unexpected question. How can I set ur comment as answer, probably i am blind but i cant really find that button anywhere, i have only "convert to answer" under my comments. After all your code worked for me after some little editing so yeah big thanks
Ok click on text of your comment than button will apear on top right of your comment and click and convert
Or did you mean my comment?