Aim Controller

这个案例是用脚本改变Aim Ik 组件的Target 来改变人物Aim瞄准的目标
Aim ik的参数
在这里插入图片描述
这是Aim Controller脚本参数 (最后给代码)
在这里插入图片描述
通过改脚 本Target Smoothing 下的Target而改变Aim瞄准
效果:
在这里插入图片描述

瞄准第二个
在这里插入图片描述
走动时
在这里插入图片描述

using UnityEngine;
using System.Collections;

namespace RootMotion.FinalIK {


    /// Handles smooth aim target switching, weight blending, target interpolation and root rotation.
    /// 处理平滑目标切换,权重融合,目标插值和根旋转。
    public class AimController : MonoBehaviour {


		/// Reference to the AimIK component.
        /// 引用 AimIK 组件
	
		public AimIK ik;


		/// Master weight of the IK solver.
        /// IK的权重(0-1)
		[Range(0f, 1f)] public float weight = 1f;

		**[Header("Target Smoothing")]**


        /// The target to aim at. Do not use the Target transform that is assigned to AimIK. Set to null if you wish to stop aiming.
        /// 瞄准的目标。不要使用分配给AimIK的目标转换。如果希望停止瞄准,则设置为NULL。
        public Transform target;


        /// The time it takes to switch targets.
        /// 切换目标所需的时间。
        public float targetSwitchSmoothTime = 0.3f;


        /// The time it takes to blend in/out of AimIK weight.
        /// 在AIMIK权重中混入的时间。
        public float weightSmoothTime = 0.3f;

		**[Header("Turning Towards The Target")]**


        /// Enables smooth turning towards the target according to the parameters under this header.
        /// 根据该标头下的参数,能够平滑地向目标旋转。
        public bool smoothTurnTowardsTarget = true;


        /// Speed of turning towards the target using Vector3.RotateTowards.
        /// 使用矢量旋转方向旋转目标的速度。
        public float maxRadiansDelta = 3f;


        /// Speed of moving towards the target using Vector3.RotateTowards.
        /// 向目标移动的速度 使用 Vector3.RotateTowards
        public float maxMagnitudeDelta = 3f;


        /// Speed of slerping towards the target.
        /// 向目标倾斜的速度。
        public float slerpSpeed = 3f;

		
        /// The position of the pivot that the aim target is rotated around relative to the root of the character.
        /// 枢轴的位置,瞄准目标相对于人物的根旋转。
        public Vector3 pivotOffsetFromRoot = Vector3.up;


        /// Minimum distance of aiming from the first bone. Keeps the solver from failing if the target is too close.
        /// 从第一骨的最小距离瞄准。如果目标太近,保持解算器失效。
        public float minDistance = 1f;


        /// Offset applied to the target in world space. Convenient for scripting aiming inaccuracy.
        /// 在世界空间中应用到目标的偏移量。便于脚本瞄准不准确。
        public Vector3 offset;

		**[Header("RootRotation")]**


        ///Character root will be rotate around the Y axis to keep root forward within this angle from the aiming direction.
        ///人物根将围绕Y轴旋转,以使根从该瞄准方向保持在该角度内。
        [Range(0f, 180f)] public float maxRootAngle = 45f;

		**[Header("Mode")]**


        /// If true, AimIK will consider whatever the current direction of the weapon to be the forward aiming direction and work additively on top of that. This enables you to use recoil and reloading animations seamlessly with AimIK. Adjust the Vector3 value below if the weapon is not aiming perfectly forward in the aiming animation clip.
        /// 如果是真的,AIMIK将考虑武器的当前方向是向前瞄准的方向,
        /// 并在上面加上额外的工作。这使你可以使用AimIK无缝地反冲和重新加载动画。
        /// 如果在瞄准动画剪辑中武器没有完全瞄准,则调整下面的矢量3值。
        public bool useAnimatedAimDirection;


        /// The direction of the animated weapon aiming in character space. Tweak this value to adjust the aiming. 'Use Animated Aim Direction' must be enabled for this property to work. 
        /// 指向角色空间的动画武器的方向。调整这个值来调整瞄准。必须启用动画目标方向,才能使该属性工作。
        public Vector3 animatedAimDirection = Vector3.forward;
        //动画Aim方向 = z轴向前

		private Transform lastTarget;
        //最后目标标
		private float switchWeight, switchWeightV;
		private float weightV;
		private Vector3 lastPosition;
        //最后位置
		private Vector3 dir;
		private bool lastSmoothTowardsTarget;

		void Start() {
			lastPosition = ik.solver.IKPosition;
			dir = ik.solver.IKPosition - pivot;

			ik.solver.target = null;
		}

		void LateUpdate () {
			// If target has changed...
            //如果目标转换
			if (target != lastTarget) {
				if (lastTarget == null && target != null) {
					lastPosition = target.position;
					dir = target.position - pivot;
					ik.solver.IKPosition = target.position + offset;
				} else {
					lastPosition = ik.solver.IKPosition;
					dir = ik.solver.IKPosition - pivot;
				}

				switchWeight = 0f;
				lastTarget = target;
			}

			// Smooth weight
            //平滑权重
			ik.solver.IKPositionWeight = Mathf.SmoothDamp(ik.solver.IKPositionWeight, (target != null? weight: 0f), ref weightV, weightSmoothTime);
			if (ik.solver.IKPositionWeight >= 0.999f) ik.solver.IKPositionWeight = 1f;
			if (ik.solver.IKPositionWeight <= 0.001f) ik.solver.IKPositionWeight = 0f;

			if (ik.solver.IKPositionWeight <= 0f) return;

			// Smooth target switching
            //转换平滑目标
			switchWeight = Mathf.SmoothDamp(switchWeight, 1f, ref switchWeightV, targetSwitchSmoothTime);
			if (switchWeight >= 0.999f) switchWeight = 1f;

			if (target != null) {
				ik.solver.IKPosition = Vector3.Lerp(lastPosition, target.position + offset, switchWeight);
			}

            // Smooth turn towards target
            //平滑转向目标
            if (smoothTurnTowardsTarget != lastSmoothTowardsTarget) {
				dir = ik.solver.IKPosition - pivot;
				lastSmoothTowardsTarget = smoothTurnTowardsTarget;
			}

			if (smoothTurnTowardsTarget) {
				Vector3 targetDir = ik.solver.IKPosition - pivot;
				dir = Vector3.Slerp(dir, targetDir, Time.deltaTime * slerpSpeed);
				dir = Vector3.RotateTowards(dir, targetDir, Time.deltaTime * maxRadiansDelta, maxMagnitudeDelta);
				ik.solver.IKPosition = pivot + dir;
			}

            // Min distance from the pivot
            //枢轴最小距离
            ApplyMinDistance();

            // Root rotation
            //根系旋转
            RootRotation();

            // Offset mode
            //偏移模式
            if (useAnimatedAimDirection) {
				ik.solver.axis = ik.solver.transform.InverseTransformVector(ik.transform.rotation * animatedAimDirection);
			}
		}

        // Pivot of rotating the aiming direction.
        //转动瞄准方向的枢轴。
        private Vector3 pivot {
			get {
				return ik.transform.position + ik.transform.rotation * pivotOffsetFromRoot;
			}
		}

        // Make sure aiming target is not too close (might make the solver instable when the target is closer to the first bone than the last bone is).
       //确保瞄准目标不是太近(当目标靠近最后一根骨头时,可能会使解算器不稳定)
		void ApplyMinDistance() {
			Vector3 aimFrom = pivot;
			Vector3 direction = (ik.solver.IKPosition - aimFrom);
			direction = direction.normalized * Mathf.Max(direction.magnitude, minDistance);
				
			ik.solver.IKPosition = aimFrom + direction;
		}

        // Character root will be rotate around the Y axis to keep root forward within this angle from the aiming direction.
        //人物根将围绕Y轴旋转,以使根从该瞄准方向保持在该角度内。
        private void RootRotation() {
			float max = Mathf.Lerp(180f, maxRootAngle, ik.solver.IKPositionWeight);

			if (max < 180f) {
				Vector3 faceDirLocal = Quaternion.Inverse(ik.transform.rotation) * (ik.solver.IKPosition - pivot);
				float angle = Mathf.Atan2(faceDirLocal.x, faceDirLocal.z) * Mathf.Rad2Deg;

				float rotation = 0f;

				if (angle > max) {
					rotation = angle - max;
				}
				if (angle < -max) {
					rotation = angle + max;
				}

				ik.transform.rotation = Quaternion.AngleAxis(rotation, ik.transform.up) * ik.transform.rotation;		
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42782299/article/details/83020581
今日推荐