Files
2026-03-04 10:03:45 +08:00

90 lines
2.2 KiB
C#

using RootMotion.FinalIK;
using UnityEngine;
namespace RootMotion.Demos
{
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;
private AimPoser.Pose lastPose;
private void Start()
{
aim.enabled = false;
lookAt.enabled = false;
}
private void LateUpdate()
{
if (aim.solver.target == null)
{
Debug.LogWarning("AimIK and LookAtIK need to have their 'Target' value assigned.", base.transform);
}
Pose();
aim.solver.Update();
if (lookAt != null)
{
lookAt.solver.Update();
}
}
private void Pose()
{
LimitAimTarget();
Vector3 direction = aim.solver.target.position - aim.solver.bones[0].transform.position;
Vector3 localDirection = base.transform.InverseTransformDirection(direction);
aimPose = aimPoser.GetPose(localDirection);
if (aimPose != lastPose)
{
aimPoser.SetPoseActive(aimPose);
lastPose = aimPose;
}
AimPoser.Pose[] poses = aimPoser.poses;
foreach (AimPoser.Pose pose in poses)
{
if (pose == aimPose)
{
DirectCrossFade(pose.name, 1f);
}
else
{
DirectCrossFade(pose.name, 0f);
}
}
}
private void LimitAimTarget()
{
Vector3 position = aim.solver.bones[0].transform.position;
Vector3 vector = aim.solver.target.position - position;
vector = vector.normalized * Mathf.Max(vector.magnitude, minAimDistance);
aim.solver.target.position = position + vector;
}
private void DirectCrossFade(string state, float target)
{
float value = Mathf.MoveTowards(animator.GetFloat(state), target, Time.deltaTime * (1f / crossfadeTime));
animator.SetFloat(state, value);
}
}
}