Hi, I am making a multiplayer game with Netcode for Gameobjects, and I have a problem. You see, whenever the player tries to move, their transform is reset to 0, 0, 0. Here is the movement code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
using Cinemachine;
using System;
using Unity.VisualScripting;
public class PlayerNetwork : NetworkBehaviour, IDamageable
{
[SerializeField]
CinemachineFreeLook vc;
[SerializeField]
AudioListener listener;
public float maxHealth = 100f;
NetworkVariable<float> currHealth = new NetworkVariable<float>();
int tick = 0;
float tickRate = 1f / 60f;
float tickDeltaTime = 0f;
const int buffer = 1024;
public float moveSpeed = 3f;
HandleStates.InputState[] _inputStates = new HandleStates.InputState[buffer];
HandleStates.TransformStateRW[] _transformStates = new HandleStates.TransformStateRW[buffer];
public NetworkVariable<HandleStates.TransformStateRW> currentServerTransformState = new();
public HandleStates.TransformStateRW previousTransformState;
void OnServerStateChanged(HandleStates.TransformStateRW previousValue, HandleStates.TransformStateRW newValue)
{
previousTransformState = previousValue;
}
public void ProcessLocalPlayerMovement(Vector2 _moveInput)
{
tickDeltaTime += Time.deltaTime;
if (tickDeltaTime > tickRate)
{
int bufferIndex = tick % buffer;
MovePlayerWithServerTickServerRPC(tick, _moveInput);
Move(_moveInput);
HandleStates.InputState inputState = new()
{
tick = tick,
moveInput = _moveInput,
};
HandleStates.TransformStateRW transformState = new()
{
tick = tick,
finalPos = transform.position,
finalRot = transform.rotation,
isMoving = true
};
_inputStates[bufferIndex] = inputState;
_transformStates[bufferIndex] = transformState;
tickDeltaTime -= tickRate;
if (tick == buffer)
{
tick = 0;
}
else
{
tick++;
}
}
}
[ServerRpc]
private void MovePlayerWithServerTickServerRPC(int tick, Vector2 moveInput)
{
Move(moveInput);
HandleStates.TransformStateRW transformState = new()
{
tick = tick,
finalPos = transform.position,
finalRot = transform.rotation,
isMoving = true
};
previousTransformState = currentServerTransformState.Value;
currentServerTransformState.Value = transformState;
}
void Move(Vector2 _input)
{
Vector3 moveDir = Vector3.ProjectOnPlane(GetComponentInChildren<Camera>().transform.right, Vector3.up) * _input.x + Vector3.ProjectOnPlane(GetComponentInChildren<Camera>().transform.forward, Vector3.up) * _input.y;
transform.position = moveDir * moveSpeed * tickRate;
}
public void SimulateOtherPlayers()
{
tickDeltaTime += Time.deltaTime;
if (tickDeltaTime > tickRate)
{
if (currentServerTransformState.Value.isMoving)
{
transform.position = currentServerTransformState.Value.finalPos;
transform.rotation = currentServerTransformState.Value.finalRot;
}
tickDeltaTime -= tickRate;
if (tick == buffer)
{
tick = 0;
}
else
{
tick++;
}
}
}
private void OnEnable()
{
currentServerTransformState.OnValueChanged += OnServerStateChanged;
}
public override void OnNetworkSpawn()
{
/*
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
*/
currHealth.Value = maxHealth;
if (IsOwner)
{
listener.enabled = true;
vc.Priority = 1;
}
else
{
vc.Priority = 0;
}
}
private void Update()
{
Vector2 move = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
transform.forward = Vector3.ProjectOnPlane(GetComponentInChildren<Camera>().transform.forward, Vector3.up);
if (IsClient && IsLocalPlayer)
{
ProcessLocalPlayerMovement(move);
}
else
{
SimulateOtherPlayers();
}
if (currHealth.Value <= 0)
{
Debug.Log("health 0");
DieServerRpc();
}
}
[ServerRpc(RequireOwnership = false)]
public void DamageServerRpc(float damage)
{
Debug.Log("damaged");
currHealth.Value -= damage;
}
[ServerRpc]
void DieServerRpc()
{
Debug.Log("should die");
GetComponent<NetworkObject>().Despawn(true);
}
}
and here is the HandleStates script it is referincing:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class HandleStates
{
public class InputState
{
public int tick;
public Vector2 moveInput;
public Vector2 lookAround;
}
public class TransformStateRW : INetworkSerializable
{
public int tick;
public Vector3 finalPos;
public Quaternion finalRot;
public bool isMoving;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
if (serializer.IsReader)
{
var reader = serializer.GetFastBufferReader();
reader.ReadValueSafe(out tick);
reader.ReadValueSafe(out finalPos) ;
reader.ReadValueSafe(out finalRot);
reader.ReadValueSafe(out isMoving);
}
else
{
var writer = serializer.GetFastBufferWriter();
writer.WriteValueSafe(tick);
writer.WriteValueSafe(finalPos);
writer.WriteValueSafe(finalRot);
writer.WriteValueSafe(isMoving);
}
}
}
}
There is no network transform in the player nor is there a charactercontroller or rigidbody or any of that. I have a networkmanager in the scene which has the player as the player prefab and the player has a network object. Let me know if there is any more information i can give. Thanks