Last active
May 26, 2024 12:01
-
-
Save Kellojo/1f13002116cce6ebbc37a1f97d3db722 to your computer and use it in GitHub Desktop.
Revisions
-
Kellojo revised this gist
May 26, 2024 . 1 changed file with 74 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,74 @@ using System.Collections; using System.Collections.Generic; using KinematicCharacterController; using Unity.Netcode; using UnityEngine; [RequireComponent(typeof(PhysicsMover))] public abstract class PhysicsMoverNetworkTransform : NetworkBehaviour, IMoverController { PhysicsMover PhysicsMover; PhysicsMoverState PreviousState; float LastUpdateTime; [SerializeField] NetworkVariable<PhysicsMoverState> State = new NetworkVariable<PhysicsMoverState>(writePerm: NetworkVariableWritePermission.Owner); float TickDuration { get { return 1f / (float)NetworkManager.Singleton.NetworkTickSystem.TickRate; } } protected virtual void Awake() { PhysicsMover = GetComponent<PhysicsMover>(); PhysicsMover.MoverController = this; } private void OnEnable() { State.OnValueChanged += OnStateChance; } private void OnDisable() { State.OnValueChanged -= OnStateChance; } private void Update() { if (!IsSpawned) return; // collect state if (IsOwner) { State.Value = PhysicsMover.GetState(); } } void OnStateChance(PhysicsMoverState oldState, PhysicsMoverState newState) { LastUpdateTime = Time.time; PreviousState = oldState; } public virtual void UpdateMovement(out Vector3 goalPosition, out Quaternion goalRotation, float deltaTime) { if (IsOwner) { // generate movement input, if we're the owner UpdateMovementOwner(out goalPosition, out goalRotation, deltaTime); } else { // apply movement input, if we're not the owner if (IsSpawned) { var t = (Time.time - LastUpdateTime) / TickDuration; var newState = State.Value; goalPosition = Vector3.Lerp(PreviousState.Position, newState.Position, t); goalRotation = Quaternion.Slerp(PreviousState.Rotation, newState.Rotation, t); } else { goalPosition = transform.position; goalRotation = transform.rotation; } } } public abstract void UpdateMovementOwner(out Vector3 goalPosition, out Quaternion goalRotation, float deltaTime); } -
Kellojo created this gist
May 25, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,145 @@ using System.Collections; using System.Collections.Generic; using KinematicCharacterController; using Unity.Netcode; using UnityEngine; [RequireComponent(typeof(PlayerPhysicsSticker))] public class PlayerNetworkTransform : NetworkBehaviour { public NetworkVariable<PlayerNetworkTransformState> State = new NetworkVariable<PlayerNetworkTransformState>(writePerm: NetworkVariableWritePermission.Owner); public KinematicCharacterMotor PlayerMotor; PlayerPhysicsSticker PlayerPhysicsSticker; PlayerNetworkTransformState PreviousState; Rigidbody Rigidbody; float LastUpdateTime; float TickDuration { get { return 1f / (float) NetworkManager.Singleton.NetworkTickSystem.TickRate; } } private void Awake() { PlayerPhysicsSticker = GetComponent<PlayerPhysicsSticker>(); Rigidbody = GetComponent<Rigidbody>(); } private void OnEnable() { State.OnValueChanged += OnStateChange; } private void OnDisable() { State.OnValueChanged -= OnStateChange; } public override void OnNetworkSpawn() { base.OnNetworkSpawn(); Rigidbody.isKinematic = !IsLocalPlayer; } private void LateUpdate() { // update state, if we're the owner if (IsLocalPlayer) { var state = new PlayerNetworkTransformState(); state.WorldPosition = transform.position; state.WorldRotation = transform.rotation; state.LocalPosition = Vector3.zero; var physicsMover = PlayerPhysicsSticker.CurrentMover; state.IsGroundedOnPhysicsMover = physicsMover != null; state.IsGrounded = PlayerMotor.GroundingStatus.FoundAnyGround; state.SetUsedPhysicsMover(physicsMover); if (physicsMover != null) { state.LocalPosition = physicsMover.transform.InverseTransformPoint(state.WorldPosition); } State.Value = state; } // apply state, if we're not the owner if (!IsLocalPlayer) { var t = (Time.time - LastUpdateTime) / TickDuration; var playerTransform = transform; var state = State.Value; var newPos = Vector3.Lerp(PreviousState.WorldPosition, state.WorldPosition, t); // world pos if (state.IsGroundedOnPhysicsMover) { // standard moving case var ilocalPos = Vector3.Lerp(PreviousState.LocalPosition, state.LocalPosition, t); newPos = state.GetWorldPosOn(ilocalPos); // jumping on a mover // entering / exiting a mover if (!PreviousState.IsGroundedOnPhysicsMover) { newPos = Vector3.Lerp(PreviousState.WorldPosition, state.GetWorldPosOn(state.LocalPosition), t); } } playerTransform.position = newPos; playerTransform.rotation = Quaternion.Slerp(PreviousState.WorldRotation, state.WorldRotation, t); } } void OnStateChange(PlayerNetworkTransformState oldState, PlayerNetworkTransformState newState) { LastUpdateTime = Time.time; PreviousState = oldState; //Debug.Log(newState); } [System.Serializable] public struct PlayerNetworkTransformState : INetworkSerializable { public Vector3 WorldPosition; public Quaternion WorldRotation; public Vector3 LocalPosition; public bool IsGroundedOnPhysicsMover; public bool IsGrounded; public NetworkObjectReference UsedPhysicsMoverReference; public void SetUsedPhysicsMover(PhysicsMover physicsMover) { if (physicsMover == null) return; UsedPhysicsMoverReference = new NetworkObjectReference(physicsMover.NetworkObject); } public PhysicsMover GetUsedPhysicsMover() { if (!IsGroundedOnPhysicsMover) return null; UsedPhysicsMoverReference.TryGet(out NetworkObject physicsMoverObj); if (physicsMoverObj == null) return null; return physicsMoverObj.GetComponent<PhysicsMover>(); } public Vector3 GetWorldPosOn(Vector3 localPos) { var mover = GetUsedPhysicsMover(); return mover.transform.TransformPoint(localPos); } public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter { serializer.SerializeValue(ref WorldPosition); serializer.SerializeValue(ref WorldRotation); serializer.SerializeValue(ref LocalPosition); serializer.SerializeValue(ref IsGroundedOnPhysicsMover); serializer.SerializeValue(ref IsGrounded); serializer.SerializeValue(ref UsedPhysicsMoverReference); } public override string ToString() { return $"{WorldPosition}, ${WorldRotation.eulerAngles}, {IsGroundedOnPhysicsMover} on {GetUsedPhysicsMover()} with {LocalPosition}"; } } }