Files
2026-03-04 09:37:33 +08:00

169 lines
4.1 KiB
C#

using System;
using UnityEngine;
namespace RootMotion.FinalIK
{
[Serializable]
public class IKSolverArm : IKSolver
{
[Range(0f, 1f)]
public float IKRotationWeight = 1f;
public Quaternion IKRotation = Quaternion.identity;
public Point chest = new Point();
public Point shoulder = new Point();
public Point upperArm = new Point();
public Point forearm = new Point();
public Point hand = new Point();
public bool isLeft;
public IKSolverVR.Arm arm = new IKSolverVR.Arm();
private Vector3[] positions = new Vector3[6];
private Quaternion[] rotations = new Quaternion[6];
public override bool IsValid(ref string message)
{
if (chest.transform == null || shoulder.transform == null || upperArm.transform == null || forearm.transform == null || hand.transform == null)
{
message = "Please assign all bone slots of the Arm IK solver.";
return false;
}
UnityEngine.Object[] objects = new Transform[5] { chest.transform, shoulder.transform, upperArm.transform, forearm.transform, hand.transform };
Transform transform = (Transform)Hierarchy.ContainsDuplicate(objects);
if (transform != null)
{
message = transform.name + " is represented multiple times in the ArmIK.";
return false;
}
return true;
}
public void SetRotationWeight(float weight)
{
IKRotationWeight = weight;
}
public bool SetChain(Transform chest, Transform shoulder, Transform upperArm, Transform forearm, Transform hand, Transform root)
{
this.chest.transform = chest;
this.shoulder.transform = shoulder;
this.upperArm.transform = upperArm;
this.forearm.transform = forearm;
this.hand.transform = hand;
Initiate(root);
return base.initiated;
}
public override Point[] GetPoints()
{
return new Point[5] { chest, shoulder, upperArm, forearm, hand };
}
public override Point GetPoint(Transform transform)
{
if (chest.transform == transform)
{
return chest;
}
if (shoulder.transform == transform)
{
return shoulder;
}
if (upperArm.transform == transform)
{
return upperArm;
}
if (forearm.transform == transform)
{
return forearm;
}
if (hand.transform == transform)
{
return hand;
}
return null;
}
public override void StoreDefaultLocalState()
{
shoulder.StoreDefaultLocalState();
upperArm.StoreDefaultLocalState();
forearm.StoreDefaultLocalState();
hand.StoreDefaultLocalState();
}
public override void FixTransforms()
{
if (base.initiated)
{
shoulder.FixTransform();
upperArm.FixTransform();
forearm.FixTransform();
hand.FixTransform();
}
}
protected override void OnInitiate()
{
IKPosition = hand.transform.position;
IKRotation = hand.transform.rotation;
Read();
}
protected override void OnUpdate()
{
Read();
Solve();
Write();
}
private void Solve()
{
arm.PreSolve(1f);
arm.ApplyOffsets(1f);
arm.Solve(isLeft);
arm.ResetOffsets();
}
private void Read()
{
arm.IKPosition = IKPosition;
arm.positionWeight = IKPositionWeight;
arm.IKRotation = IKRotation;
arm.rotationWeight = IKRotationWeight;
positions[0] = root.position;
positions[1] = chest.transform.position;
positions[2] = shoulder.transform.position;
positions[3] = upperArm.transform.position;
positions[4] = forearm.transform.position;
positions[5] = hand.transform.position;
rotations[0] = root.rotation;
rotations[1] = chest.transform.rotation;
rotations[2] = shoulder.transform.rotation;
rotations[3] = upperArm.transform.rotation;
rotations[4] = forearm.transform.rotation;
rotations[5] = hand.transform.rotation;
arm.Read(positions, rotations, hasChest: false, hasNeck: false, hasShoulders: true, hasToes: false, hasLegs: false, 1, 2);
}
private void Write()
{
arm.Write(ref positions, ref rotations);
shoulder.transform.rotation = rotations[2];
upperArm.transform.rotation = rotations[3];
forearm.transform.rotation = rotations[4];
hand.transform.rotation = rotations[5];
forearm.transform.position = positions[4];
hand.transform.position = positions[5];
}
}
}