StationObscurum/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs

127 lines
3.5 KiB
C#

using FishNet;
using FishNet.Object;
using FishNet.Object.Prediction;
using FishNet.Transporting;
using UnityEngine;
/*
*
* See TransformPrediction.cs for more detailed notes.
*
*/
namespace FishNet.Example.Prediction.CharacterControllers
{
public class CharacterControllerPrediction : NetworkBehaviour
{
#region Types.
public struct MoveData : IReplicateData
{
public float Horizontal;
public float Vertical;
private uint _tick;
public void Dispose() { }
public uint GetTick() => _tick;
public void SetTick(uint value) => _tick = value;
}
public struct ReconcileData : IReconcileData
{
public Vector3 Position;
public Quaternion Rotation;
public ReconcileData(Vector3 position, Quaternion rotation)
{
Position = position;
Rotation = rotation;
_tick = 0;
}
private uint _tick;
public void Dispose() { }
public uint GetTick() => _tick;
public void SetTick(uint value) => _tick = value;
}
#endregion
#region Serialized.
[SerializeField]
private float _moveRate = 5f;
#endregion
#region Private.
private CharacterController _characterController;
#endregion
private void Awake()
{
InstanceFinder.TimeManager.OnTick += TimeManager_OnTick;
_characterController = GetComponent<CharacterController>();
}
public override void OnStartClient()
{
base.OnStartClient();
_characterController.enabled = (base.IsServer || base.IsOwner);
}
private void OnDestroy()
{
if (InstanceFinder.TimeManager != null)
{
InstanceFinder.TimeManager.OnTick -= TimeManager_OnTick;
}
}
private void TimeManager_OnTick()
{
if (base.IsOwner)
{
Reconciliation(default, false);
CheckInput(out MoveData md);
Move(md, false);
}
if (base.IsServer)
{
Move(default, true);
ReconcileData rd = new ReconcileData(transform.position, transform.rotation);
Reconciliation(rd, true);
}
}
private void CheckInput(out MoveData md)
{
md = default;
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
if (horizontal == 0f && vertical == 0f)
return;
md = new MoveData()
{
Horizontal = horizontal,
Vertical = vertical
};
}
[Replicate]
private void Move(MoveData md, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false)
{
Vector3 move = new Vector3(md.Horizontal, 0f, md.Vertical).normalized + new Vector3(0f, Physics.gravity.y, 0f);
_characterController.Move(move * _moveRate * (float)base.TimeManager.TickDelta);
}
[Reconcile]
private void Reconciliation(ReconcileData rd, bool asServer, Channel channel = Channel.Unreliable)
{
transform.position = rd.Position;
transform.rotation = rd.Rotation;
}
}
}