I have an authoritative server/client setup, the client sends its inputs to the server, which performs all movements/rotations and the end result is streamed back to the client using OnSerializeNetworkView.
Keyboard movement (transform.position) is working just fine, whats giving me a headache is the rotation, as the rotation is determined by the camera.eulerangle.y.
So when i send the inputs to the server (through an RPC called in Update() on the client), i set the eulerangle.y of the camera to a variable, i send this variable inside the RPC, and then the server rotates the charactercontroller transform using the camera’s euler angles sent from the client.
When i move around, things run smoothly only sometimes. During rotation on the server side, the player snaps around a little bit, and sometimes gets stuck completely till i rotate more. on the client side, no rotation is applied at all.
A Video of the problem: - YouTube
If somebody could offer some advice, thatd be great
void Awake()
{
CharacterController = GetComponent("CharacterController") as CharacterController;
if (Network.isClient)
{
enabled = false;
}
}
void Update()
{
if (Network.isServer)
{
DetermineServerMoveDirection();
ProcessServerMotion();
}
else if (Network.isClient)
{
if ((owner != null) && (Network.player == owner))
{
targetLookAtTransform = transform.FindChild ("targetLookAt");
PlayerCam.UseExistingOrCreateNewMainCamera(targetLookAtTransform);
if(Camera.main == null)
return;
MoveVector = Vector3.zero;
if(Input.GetAxis("Vertical") > DeadZone || Input.GetAxis("Vertical") < -DeadZone)
MoveVector += new Vector3 (0,0,Input.GetAxis("Vertical"));
if(Input.GetAxis("Horizontal") > DeadZone || Input.GetAxis("Horizontal") < -DeadZone)
MoveVector += new Vector3 (Input.GetAxis("Horizontal"),0,0);
CameraEulerY = Camera.main.transform.eulerAngles.y;
networkView.RPC("SendMotionInput", RPCMode.Server, MoveVector, CameraEulerY);
}
}
}
[RPC]
void SendMotionInput(Vector3 MoveVector, float CameraEulerY)
{
newMoveVector = MoveVector;
ServerEulerY = CameraEulerY;
}
void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
{
Vector3 positionReceive = Vector3.zero;
Quaternion rotationReceive = Quaternion.identity;
Vector3 position = Vector3.zero;
Quaternion rotation = Quaternion.identity;
if ((stream.isWriting))
{
position = transform.position;
rotation = transform.rotation;
stream.Serialize(ref rotation);
stream.Serialize(ref position);
}
else
{
stream.Serialize(ref rotationReceive);
transform.rotation = rotationReceive;
stream.Serialize(ref positionReceive);
transform.position = positionReceive;
}
}
void ProcessServerMotion()
{
newMoveVector = transform.TransformDirection(newMoveVector);
if (newMoveVector.magnitude > 1) newMoveVector = Vector3.Normalize(newMoveVector);
newMoveVector *= MoveSpeed();
newMoveVector = new Vector3(newMoveVector.x, newMoveVector.y, newMoveVector.z);
CharacterController.Move(newMoveVector * Time.deltaTime);
newServerRotation = Quaternion.Euler(CharacterController.transform.eulerAngles.x,ServerEulerY,CharacterController.transform.eulerAngles.z);
CharacterController.transform.rotation = Quaternion.Slerp(transform.rotation, newServerRotation, 0.1f * Time.deltaTime);
}
float MoveSpeed()
{
var moveSpeed = 0f;
switch (MoveDirection)
{
case Direction.Stationary:
moveSpeed = 0;
break;
case Direction.Forward:
moveSpeed = ForwardSpeed;
break;
case Direction.Backward:
moveSpeed = BackwardSpeed;
break;
case Direction.Left:
moveSpeed = StrafingSpeed;
break;
case Direction.Right:
moveSpeed = StrafingSpeed;
break;
case Direction.LeftForward:
moveSpeed = ForwardSpeed;
break;
case Direction.RightForward:
moveSpeed = ForwardSpeed;
break;
case Direction.LeftBackward:
moveSpeed = BackwardSpeed;
break;
case Direction.RightBackward:
moveSpeed = BackwardSpeed;
break;
}
return moveSpeed;
}
public enum Direction
{
Stationary, Forward, Backward, Left, Right, LeftForward, RightForward, LeftBackward, RightBackward
}
public void DetermineServerMoveDirection()
{
bool forward = false;
bool backward = false;
bool left = false;
bool right = false;
if(newMoveVector.z > 0)
forward = true;
if(newMoveVector.z < 0)
backward = true;
if(newMoveVector.x > 0)
right = true;
if(newMoveVector.x < 0)
left = true;
if(forward)
{
if(left)
MoveDirection = Direction.LeftForward;
else if(right)
MoveDirection = Direction.RightForward;
else
MoveDirection = Direction.Forward;
}
else if(backward)
{
if(left)
MoveDirection = Direction.LeftBackward;
else if(right)
MoveDirection = Direction.RightBackward;
else
MoveDirection = Direction.Backward;
}
else if(left)
MoveDirection = Direction.Left;
else if(right)
MoveDirection = Direction.Right;
else
MoveDirection = Direction.Stationary;
}
[RPC]
void setOwner ( NetworkPlayer player )
{
owner = player;
if(player == Network.player)
{
enabled=true;
}
}
public NetworkPlayer getOwner ()
{
return owner;
}