SimpleAimingSystem.cs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using RootMotion.Demos;
  2. using UnityEngine;
  3. using System.Collections;
  4. using RootMotion.FinalIK;
  5. namespace RootMotion.Demos {
  6. // Demonstrating 360-degree aiming system built with 6 static aiming poses and AimIK.
  7. public class SimpleAimingSystem : MonoBehaviour {
  8. [Tooltip("AimPoser is a tool that returns an animation name based on direction.")]
  9. public AimPoser aimPoser;
  10. [Tooltip("Reference to the AimIK component.")]
  11. public AimIK aim;
  12. [Tooltip("Reference to the LookAt component (only used for the head in this instance).")]
  13. public LookAtIK lookAt;
  14. [Tooltip("Reference to the Animator component.")]
  15. public Animator animator;
  16. [Tooltip("Time of cross-fading from pose to pose.")]
  17. public float crossfadeTime = 0.2f;
  18. [Tooltip("Will keep the aim target at a distance.")]
  19. public float minAimDistance = 0.5f;
  20. private AimPoser.Pose aimPose, lastPose;
  21. void Start() {
  22. // Disable IK components to manage their updating order
  23. aim.enabled = false;
  24. lookAt.enabled = false;
  25. }
  26. // LateUpdate is called once per frame
  27. void LateUpdate () {
  28. if (aim.solver.target == null) {
  29. Debug.LogWarning("AimIK and LookAtIK need to have their 'Target' value assigned.", transform);
  30. }
  31. // Switch aim poses (Legacy animation)
  32. Pose();
  33. // Update IK solvers
  34. aim.solver.Update();
  35. if (lookAt != null) lookAt.solver.Update();
  36. }
  37. private void Pose() {
  38. // 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).
  39. LimitAimTarget();
  40. // Get the aiming direction
  41. Vector3 direction = (aim.solver.target.position - aim.solver.bones[0].transform.position);
  42. // Getting the direction relative to the root transform
  43. Vector3 localDirection = transform.InverseTransformDirection(direction);
  44. // Get the Pose from AimPoser
  45. aimPose = aimPoser.GetPose(localDirection);
  46. // If the Pose has changed
  47. if (aimPose != lastPose) {
  48. // Increase the angle buffer of the pose so we won't switch back too soon if the direction changes a bit
  49. aimPoser.SetPoseActive(aimPose);
  50. // Store the pose so we know if it changes
  51. lastPose = aimPose;
  52. }
  53. // Direct blending
  54. foreach (AimPoser.Pose pose in aimPoser.poses) {
  55. if (pose == aimPose) {
  56. DirectCrossFade(pose.name, 1f);
  57. } else {
  58. DirectCrossFade(pose.name, 0f);
  59. }
  60. }
  61. }
  62. // 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).
  63. void LimitAimTarget() {
  64. Vector3 aimFrom = aim.solver.bones[0].transform.position;
  65. Vector3 direction = (aim.solver.target.position - aimFrom);
  66. direction = direction.normalized * Mathf.Max(direction.magnitude, minAimDistance);
  67. aim.solver.target.position = aimFrom + direction;
  68. }
  69. // Uses Mecanim's Direct blend trees for cross-fading
  70. private void DirectCrossFade(string state, float target) {
  71. float f = Mathf.MoveTowards(animator.GetFloat(state), target, Time.deltaTime * (1f / crossfadeTime));
  72. animator.SetFloat(state, f);
  73. }
  74. }
  75. }