holopy3/Assets/Plugins/RootMotion/FinalIK/_DEMOS/Aim IK/Scripts/SimpleAimingSystem.cs
2020-12-10 15:25:12 +01:00

97 lines
3.1 KiB
C#

using RootMotion.Demos;
using UnityEngine;
using System.Collections;
using RootMotion.FinalIK;
namespace RootMotion.Demos {
// Demonstrating 360-degree aiming system built with 6 static aiming poses and AimIK.
public class SimpleAimingSystem : MonoBehaviour {
[Tooltip("AimPoser is a tool that returns an animation name based on direction.")]
public AimPoser aimPoser;
[Tooltip("Reference to the AimIK component.")]
public AimIK aim;
[Tooltip("Reference to the LookAt component (only used for the head in this instance).")]
public LookAtIK lookAt;
[Tooltip("Reference to the Animator component.")]
public Animator animator;
[Tooltip("Time of cross-fading from pose to pose.")]
public float crossfadeTime = 0.2f;
[Tooltip("Will keep the aim target at a distance.")]
public float minAimDistance = 0.5f;
private AimPoser.Pose aimPose, lastPose;
void Start() {
// Disable IK components to manage their updating order
aim.enabled = false;
lookAt.enabled = false;
}
// LateUpdate is called once per frame
void LateUpdate () {
if (aim.solver.target == null) {
Debug.LogWarning("AimIK and LookAtIK need to have their 'Target' value assigned.", transform);
}
// Switch aim poses (Legacy animation)
Pose();
// Update IK solvers
aim.solver.Update();
if (lookAt != null) lookAt.solver.Update();
}
private void Pose() {
// 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).
LimitAimTarget();
// Get the aiming direction
Vector3 direction = (aim.solver.target.position - aim.solver.bones[0].transform.position);
// Getting the direction relative to the root transform
Vector3 localDirection = transform.InverseTransformDirection(direction);
// Get the Pose from AimPoser
aimPose = aimPoser.GetPose(localDirection);
// If the Pose has changed
if (aimPose != lastPose) {
// Increase the angle buffer of the pose so we won't switch back too soon if the direction changes a bit
aimPoser.SetPoseActive(aimPose);
// Store the pose so we know if it changes
lastPose = aimPose;
}
// Direct blending
foreach (AimPoser.Pose pose in aimPoser.poses) {
if (pose == aimPose) {
DirectCrossFade(pose.name, 1f);
} else {
DirectCrossFade(pose.name, 0f);
}
}
}
// 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 LimitAimTarget() {
Vector3 aimFrom = aim.solver.bones[0].transform.position;
Vector3 direction = (aim.solver.target.position - aimFrom);
direction = direction.normalized * Mathf.Max(direction.magnitude, minAimDistance);
aim.solver.target.position = aimFrom + direction;
}
// Uses Mecanim's Direct blend trees for cross-fading
private void DirectCrossFade(string state, float target) {
float f = Mathf.MoveTowards(animator.GetFloat(state), target, Time.deltaTime * (1f / crossfadeTime));
animator.SetFloat(state, f);
}
}
}