public CharacterController CharacterController { get; private set; }
private MoveData _clientMoveData;
private void Awake()
{
InstanceFinder.TimeManager.OnTick += TimeManager_OnTick;
InstanceFinder.TimeManager.OnUpdate += TimeManager_OnUpdate;
CharacterController = GetComponent<CharacterController>();
}
private void OnDestroy()
{
if (InstanceFinder.TimeManager != null)
{
InstanceFinder.TimeManager.OnTick -= TimeManager_OnTick;
InstanceFinder.TimeManager.OnUpdate -= TimeManager_OnUpdate;
}
}
public override void OnStartClient()
{
base.OnStartClient();
CharacterController.enabled = IsServer || IsOwner;
}
private void TimeManager_OnTick()
{
if (IsOwner)
{
Reconciliation(default, false);
CheckInput(out var md);
Move(md, false);
}
if (IsServer)
{
Move(default, true);
var rd = new ReconcileData(transform.position);
// Reconcile only every X ticks
if (TimeManager.Tick % 2 == 0)
Reconciliation(rd, true);
}
}
private void TimeManager_OnUpdate()
{
if (IsOwner)
MoveWithData(_clientMoveData, Time.deltaTime);
}
private void CheckInput(out MoveData md)
{
md = default;
if (IsFrozen) return;
var horizontal = X
var vertical = Y
if (horizontal == 0f && vertical == 0f)
return;
md = new MoveData
{
Horizontal = horizontal,
Vertical = vertical
};
}
[Replicate]
private void Move(MoveData md, bool asServer, bool replaying = false)
{
//Sanity check!
if (asServer)
if (IsFrozen)
{
md.Horizontal = 0;
md.Vertical = 0;
}
if (asServer || replaying)
MoveWithData(md, (float)TimeManager.TickDelta);
// ReSharper disable once ConditionIsAlwaysTrueOrFalse //Wrong ReSharper assumption
else if (!asServer)
_clientMoveData = md;
}
private void MoveWithData(MoveData md, float delta)
{
if (IsFrozen && IsClient)
return;
if (IsFrozen)
{
md.Horizontal = 0;
md.Vertical = 0;
}
var direction = new Vector3(md.Horizontal, 0, md.Vertical).normalized + new Vector3(0,Physics.gravity.y,0);
//Move char controller
if (CharacterController.enabled)
CharacterController.Move(direction * (_currentMoveRate * delta));
}
[Reconcile]
private void Reconciliation(ReconcileData rd, bool asServer)
{
//Skip, if client and disabled reconciling
if (!asServer && !_clientReconcile) return;
transform.position = rd.GetPosition();
}