using FishNet.Managing; using FishNet.Managing.Timing; using GameKit.Dependencies.Utilities; using UnityEngine; using UnityEngine.Serialization; namespace FishNet.Component.Transforming.Beta { /// /// Smoothes this object between ticks. /// /// This can be configured to smooth over a set interval of time, or to smooth adaptively and make path corrections for prediction. public class OfflineTickSmoother : MonoBehaviour { #region Public. /// /// Logic for owner smoothing. /// public TickSmootherController SmootherController { get; private set; } /// /// True if this component is initialized. /// /// This API is for internal use and may change at any time. public bool IsInitialized { get; private set; } #endregion #region Serialized. /// /// True to automatically initialize in Awake using InstanceFinder. When false you will need to manually call Initialize. /// [Tooltip("True to automatically initialize in Awake using InstanceFinder. When false you will need to manually call Initialize.")] [SerializeField] private bool _automaticallyInitialize = true; /// /// Settings required to initialize the smoother. /// [Tooltip("Settings required to initialize the smoother.")] [SerializeField] private InitializationSettings _initializationSettings = new(); /// /// How smoothing occurs when the controller of the object. /// [FormerlySerializedAs("_controllerMovementSettings")] [Tooltip("How smoothing occurs when the controller of the object.")] [SerializeField] private MovementSettings _movementSettings = new(true); #endregion private void Awake() { RetrieveControllers(); AutomaticallyInitialize(); } private void OnDestroy() { if (SmootherController != null) { SmootherController.StopSmoother(); SmootherController.OnDestroy(); } StoreControllers(); IsInitialized = false; } /// /// Automatically initializes if feature is enabled. /// private void AutomaticallyInitialize() { if (!_automaticallyInitialize) return; TimeManager tm = InstanceFinder.TimeManager; if (tm == null) { NetworkManagerExtensions.LogWarning($"Automatic initialization failed on {gameObject.name}. You must manually call Initialize."); return; } Initialize(tm); } /// /// Initializes using a specified TimeManager. /// /// public void Initialize(TimeManager timeManager) { if (timeManager == null) { NetworkManagerExtensions.LogError($"TimeManager cannot be null when initializing."); return; } SmootherController.SetTimeManager(timeManager); _initializationSettings.SetOfflineRuntimeValues(timeManager, graphicalTransform: transform); SmootherController.Initialize(_initializationSettings, _movementSettings, default); SmootherController.StartSmoother(); IsInitialized = true; } /// /// Sets a transform as the target to follow. /// /// New value. public void SetTargetTransform(Transform value) { if (IsInitialized) { NetworkManagerExtensions.LogError($"Target can only be set before Initialize is called."); return; } _initializationSettings.TargetTransform = value; } /// /// Stores smoothers if they have value. /// private void StoreControllers() { if (SmootherController == null) return; ResettableObjectCaches.Store(SmootherController); SmootherController = null; } /// /// Stores current smoothers and retrieves new ones. /// private void RetrieveControllers() { StoreControllers(); SmootherController = ResettableObjectCaches.Retrieve(); } } }