MRTK-Solver

作者:追风剑情 发布于:2023-7-5 18:50 分类:Unity3d

所有解算器要从中派生的抽象基类。参见 求解器概述 - MRTK2

using System;
using UnityEngine;
using UnityEngine.Serialization;

namespace Microsoft.MixedReality.Toolkit.Utilities.Solvers
{
   [RequireComponent(typeof(SolverHandler))]
   public abstract class Solver : MonoBehaviour
   {
        //如果为true,将计算位置和方向,但不应用于其他组件。
	private bool updateLinkedTransform = false;
        //移动插值时间,值越大移动越缓慢
        //参见:UpdateWorkingPositionToGoal()
        private float moveLerpTime = 0.1f;
        //旋转插值时间,值越大旋转越缓慢
        //参见:UpdateWorkingRotationToGoal()
        private float rotateLerpTime = 0.1f;
        //缩放插值时间,值越大缩放越缓慢
        //参见:UpdateWorkingScaleToGoal()
        private float scaleLerpTime = 0;
        //true:初始化时保持transform的localScale值不变。
        //参见 Awake()
        private bool maintainScaleOnInitialization = true;
        //是否采用平滑插值。
        //参见: UpdateWorkingPositionToGoal()、UpdateWorkingRotationToGoal()、UpdateWorkingScaleToGoal()
        private bool smoothing = true;
        //解算器生命周期,0:无限
        //参见: SolverUpdateEntry()
        private float lifetime = 0;
        //参见: Awake()
        protected SolverHandler SolverHandler;

        /// <summary>
        /// 最终坐标,由GameObject上所有解算器共同计算所得。
        /// </summary>
        protected Vector3 GoalPosition
        {
            get { return SolverHandler.GoalPosition; }
            set { SolverHandler.GoalPosition = value; }
        }

        /// <summary>
        /// 最终旋转,由GameObject上所有解算器共同计算所得。
        /// </summary>
        protected Quaternion GoalRotation
        {
            get { return SolverHandler.GoalRotation; }
            set { SolverHandler.GoalRotation = value; }
        }

        /// <summary>
        /// 最终缩放,由GameObject上所有解算器共同计算所得。
        /// </summary>
        protected Vector3 GoalScale
        {
            get { return SolverHandler.GoalScale; }
            set { SolverHandler.GoalScale = value; }
        }

        /// <summary>
        /// 当前坐标
        /// </summary>
        public Vector3 WorkingPosition
        {
            get
            {
                return updateLinkedTransform ? GoalPosition : transform.position;
            }
            protected set
            {
                if (updateLinkedTransform)
                {
                    GoalPosition = value;
                }
                else
                {
                    transform.position = value;
                }
            }
        }

        /// <summary>
        /// 当前旋转
        /// </summary>
        public Quaternion WorkingRotation
        {
            get
            {
                return updateLinkedTransform ? GoalRotation : transform.rotation;
            }
            protected set
            {
                if (updateLinkedTransform)
                {
                    GoalRotation = value;
                }
                else
                {
                    transform.rotation = value;
                }
            }
        }

        /// <summary>
        /// 当前缩放
        /// </summary>
        public Vector3 WorkingScale
        {
            get
            {
                return updateLinkedTransform ? GoalScale : transform.localScale;
            }
            protected set
            {
                if (updateLinkedTransform)
                {
                    GoalScale = value;
                }
                else
                {
                    transform.localScale = value;
                }
            }
        }

        #region MonoBehaviour Implementation

        protected virtual void Awake()
        {
            if (SolverHandler == null)
            {
                SolverHandler = GetComponent<SolverHandler>();
            }

            if (updateLinkedTransform && SolverHandler == null)
            {
                Debug.LogError("No SolverHandler component found on " + name + 
                      " when UpdateLinkedTransform was set to true! Disabling UpdateLinkedTransform.");
                updateLinkedTransform = false;
            }

            GoalScale = maintainScaleOnInitialization ? transform.localScale : Vector3.one;
        }

        protected virtual void OnEnable()
        {
            if (SolverHandler != null)
            {
                SnapGoalTo(GoalPosition, GoalRotation, GoalScale);
            }

            currentLifetime = 0;
        }

        protected virtual void Start()
        {
            if (SolverHandler != null)
            {
                //注册解算器
                SolverHandler.RegisterSolver(this);
            }
        }
        protected virtual void OnDestroy()
        {
            if (SolverHandler != null)
            {
                //注销解算器
                SolverHandler.UnregisterSolver(this);
            }
        }

        #endregion MonoBehaviour Implementation

        /// <summary>
        /// 由子类实现,更新游戏内容变换。
        /// </summary>
        public abstract void SolverUpdate();

        /// <summary>
        /// 此方法在SolverHandler类的LateUpdate()中被每帧调用。
        /// </summary>
        public void SolverUpdateEntry()
        {
            currentLifetime += SolverHandler.DeltaTime;
            //判断解算器的生命周期是否结束
            if (lifetime > 0 && currentLifetime >= lifetime)
            {
                enabled = false;
                return;
            }

            SolverUpdate();
            UpdateWorkingToGoal();
        }

        /// <summary>
        /// 更新解算器的变换值
        /// </summary>
        public virtual void SnapTo(Vector3 position, Quaternion rotation, Vector3 scale)
        {
            SnapGoalTo(position, rotation, scale);

            WorkingPosition = position;
            WorkingRotation = rotation;
            WorkingScale = scale;
        }

        /// <summary>
        /// 更新解算器的最终变换值
        /// </summary>
        public virtual void SnapGoalTo(Vector3 position, Quaternion rotation, Vector3 scale)
        {
            GoalPosition = position;
            GoalRotation = rotation;
            GoalScale = scale;
        }

        /// <summary>
        /// 坐标偏移
        /// </summary>
        public virtual void AddOffset(Vector3 offset)
        {
            GoalPosition += offset;
        }

        /// <summary>
        /// 更新Transform
        /// </summary>
        protected void UpdateTransformToGoal()
        {
            if (smoothing)
            {
                Vector3 pos = transform.position;
                Quaternion rot = transform.rotation;
                Vector3 scale = transform.localScale;

                pos = SmoothTo(pos, GoalPosition, SolverHandler.DeltaTime, moveLerpTime);
                rot = SmoothTo(rot, GoalRotation, SolverHandler.DeltaTime, rotateLerpTime);
                scale = SmoothTo(scale, GoalScale, SolverHandler.DeltaTime, scaleLerpTime);

                transform.position = pos;
                transform.rotation = rot;
                transform.localScale = scale;
            }
            else
            {
                transform.position = GoalPosition;
                transform.rotation = GoalRotation;
                transform.localScale = GoalScale;
            }
        }

        public void UpdateWorkingToGoal()
        {
            UpdateWorkingPositionToGoal();
            UpdateWorkingRotationToGoal();
            UpdateWorkingScaleToGoal();
        }

        public void UpdateWorkingPositionToGoal()
        {
            WorkingPosition = smoothing ? SmoothTo(WorkingPosition, GoalPosition, SolverHandler.DeltaTime, moveLerpTime) : GoalPosition;
        }

        public void UpdateWorkingRotationToGoal()
        {
            WorkingRotation = smoothing ? SmoothTo(WorkingRotation, GoalRotation, SolverHandler.DeltaTime, rotateLerpTime) : GoalRotation;
        }

        public void UpdateWorkingScaleToGoal()
        {
            WorkingScale = smoothing ? SmoothTo(WorkingScale, GoalScale, SolverHandler.DeltaTime, scaleLerpTime) : GoalScale;
        }

        // 向量平滑插值
        public static Vector3 SmoothTo(Vector3 source, Vector3 goal, float deltaTime, float lerpTime)
        {
            return Vector3.Lerp(source, goal, lerpTime.Equals(0.0f) ? 1f : deltaTime / lerpTime);
        }

        // 四元数平滑插值
        public static Quaternion SmoothTo(Quaternion source, Quaternion goal, float deltaTime, float lerpTime)
        {
            return Quaternion.Slerp(source, goal, lerpTime.Equals(0.0f) ? 1f : deltaTime / lerpTime);
        }
   }
}

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号