Space-Smash-Out/Assets/FishNet/Demos/Prediction 2/Rigidbody/Scripts/RigidbodyPredictionV2.cs

211 lines
7.5 KiB
C#

using FishNet.Object;
using FishNet.Object.Prediction;
using FishNet.Transporting;
using UnityEngine;
/*
*
* See TransformPrediction.cs for more detailed notes.
*
*/
namespace FishNet.PredictionV2
{
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
* AN EXAMPLE TO FOLLOW. */
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
* AN EXAMPLE TO FOLLOW. */
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
* AN EXAMPLE TO FOLLOW. */
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
* AN EXAMPLE TO FOLLOW. */
public class RigidbodyPredictionV2 : NetworkBehaviour
{
#if !PREDICTION_1
public struct MoveData : IReplicateData
{
public bool Jump;
public float Horizontal;
public float Vertical;
public Vector3 OtherImpulseForces;
public MoveData(bool jump, float horizontal, float vertical, Vector3 otherImpulseForces)
{
Jump = jump;
Horizontal = horizontal;
Vertical = vertical;
OtherImpulseForces = otherImpulseForces;
_tick = 0;
}
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 Vector3 Velocity;
public Vector3 AngularVelocity;
public ReconcileData(Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity)
{
Position = position;
Rotation = rotation;
Velocity = velocity;
AngularVelocity = angularVelocity;
_tick = 0;
}
private uint _tick;
public void Dispose() { }
public uint GetTick() => _tick;
public void SetTick(uint value) => _tick = value;
}
//[SerializeField]
//private float _jumpForce = 15f;
[SerializeField]
private float _moveRate = 15f;
public Rigidbody Rigidbody { get; private set; }
private bool _jump;
private void Update()
{
if (base.IsOwner)
{
if (Input.GetKeyDown(KeyCode.Space))
_jump = true;
}
}
public override void OnStartNetwork()
{
Rigidbody = GetComponent<Rigidbody>();
base.TimeManager.OnTick += TimeManager_OnTick;
base.TimeManager.OnPostTick += TimeManager_OnPostTick;
}
public override void OnStopNetwork()
{
base.TimeManager.OnTick -= TimeManager_OnTick;
base.TimeManager.OnPostTick -= TimeManager_OnPostTick;
}
private void TimeManager_OnTick()
{
Move(BuildMoveData());
}
private void TimeManager_OnPostTick()
{
CreateReconcile();
}
private MoveData BuildMoveData()
{
if (!IsOwner && Owner.IsValid)
return default;
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
//MoveData md = new MoveData(_jump, horizontal, vertical, (SpringForces + RocketForces));
MoveData md = new MoveData(_jump, horizontal, vertical, Vector3.zero);
//SpringForces = Vector3.zero;
//RocketForces = Vector3.zero;
_jump = false;
return md;
}
public uint LastMdTick;
[Replicate]
private void Move(MoveData md, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
{
LastMdTick = md.GetTick();
//if (base.IsOwner)
// Debug.Log(PredictionManager.ClientReplayTick + " > " + md.GetTick());
//if (state == ReplicateState.Future)
//{
// /* Reduce velocity slightly. This will be slightly less accurate if
// * the object continues to move in the same direction but can drastically
// * reduce jarring visuals if the object changes path rather than predicted(future)
// * forward. */
// _rigidbody.velocity *= 0.65f;
// _rigidbody.angularVelocity *= 0.65f;
// return;
//}
//Vector3 forces = new Vector3(md.Horizontal, 0f, md.Vertical) * _moveRate;
//Rigidbody.AddForce(forces);
//if (md.Jump)
// Rigidbody.AddForce(new Vector3(0f, _jumpForce, 0f), ForceMode.Impulse);
////Add gravity to make the object fall faster.
//Rigidbody.AddForce(Physics.gravity * 3f);
Vector3 forces = new Vector3(md.Horizontal, 0f, md.Vertical) * _moveRate;
//PRB.AddForce(forces);
forces += Physics.gravity * 3f;
//if (md.Jump)
// PRB.AddForce(new Vector3(0f, _jumpForce, 0f), ForceMode.Impulse);
////Add gravity to make the object fall faster.
//PRB.AddForce(forces);
//if (IsOwner)
//{
// if (state.IsReplayed())
// Debug.Log($"{md.GetTick()} -> {transform.position.x} -> {Rigidbody.velocity.x}");
// else
// Debug.LogWarning($"{md.GetTick()} -> {transform.position.x} -> {Rigidbody.velocity.x}");
//}
//if ((!base.IsServerStarted && base.IsOwner) || (base.IsServerStarted && !base.IsOwner))
// Debug.LogWarning($"Frame {Time.frameCount}. State {state}, Horizontal {md.Horizontal}. MdTick {md.GetTick()}, PosX {transform.position.x.ToString("0.##")}. VelX {Rigidbody.velocity.x.ToString("0.###")}.");
}
public override void CreateReconcile()
{
/* The base.IsServer check is not required but does save a little
* performance by not building the reconcileData if not server. */
if (IsServerStarted)
{
ReconcileData rd = new ReconcileData(transform.position, transform.rotation, Rigidbody.velocity, Rigidbody.angularVelocity);
//if (!base.IsOwner)
// Debug.LogError($"Frame {Time.frameCount}. Reconcile, MdTick {LastMdTick}, PosX {transform.position.x.ToString("0.##")}. VelX {Rigidbody.velocity.x.ToString("0.###")}.");
Reconciliation(rd);
}
}
[Reconcile]
private void Reconciliation(ReconcileData rd, Channel channel = Channel.Unreliable)
{
transform.position = rd.Position;
transform.rotation = rd.Rotation;
Rigidbody.velocity = rd.Velocity;
Rigidbody.angularVelocity = rd.AngularVelocity;
//if (PrintForClient())
//{
// Debug.LogError($"Frame {Time.frameCount}. Reconcile, MdTick {rd.GetTick()}, PosX {transform.position.x.ToString("0.##")}. VelX {Rigidbody.velocity.x.ToString("0.###")}. RdPosX " +
// $"{rd.Position.x.ToString("0.##")}. RdVelX {Rigidbody.velocity.x.ToString("0.###")}");
//}
}
private bool PrintForClient() => ((!base.IsServerStarted && base.IsOwner) || (base.IsServerStarted && !base.IsOwner));
#endif
}
}