You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			78 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			78 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C#
		
	
using UnityEngine;
 | 
						|
using System.Collections;
 | 
						|
using RootMotion.FinalIK;
 | 
						|
 | 
						|
namespace RootMotion.FinalIK {
 | 
						|
 | 
						|
	/// <summary>
 | 
						|
	/// Shoulder rotator is a workaround for FBBIK not rotating the shoulder bones when pulled by hands.
 | 
						|
	/// It get's the job done if you need it, but will take 2 solving iterations.
 | 
						|
	/// </summary>
 | 
						|
	public class ShoulderRotator : MonoBehaviour {
 | 
						|
 | 
						|
		[Tooltip("Weight of shoulder rotation")]
 | 
						|
		public float weight = 1.5f;
 | 
						|
		[Tooltip("The greater the offset, the sooner the shoulder will start rotating")]
 | 
						|
		public float offset = 0.2f;
 | 
						|
 | 
						|
		private FullBodyBipedIK ik;
 | 
						|
		private bool skip;
 | 
						|
 | 
						|
		void Start() {
 | 
						|
			ik = GetComponent<FullBodyBipedIK>();
 | 
						|
 | 
						|
			// You can use just LateUpdate, but note that it doesn't work when you have animatePhysics turned on for the character.
 | 
						|
			ik.solver.OnPostUpdate += RotateShoulders;
 | 
						|
		}
 | 
						|
 | 
						|
		private void RotateShoulders () {
 | 
						|
			if (ik == null) return;
 | 
						|
			if (ik.solver.IKPositionWeight <= 0f) return;
 | 
						|
 | 
						|
			// Skipping the second update cycle
 | 
						|
			if (skip) {
 | 
						|
				skip = false;
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			RotateShoulder(FullBodyBipedChain.LeftArm, weight, offset); // Rotate the left shoulder
 | 
						|
			RotateShoulder(FullBodyBipedChain.RightArm, weight, offset); // Rotate the right shoulder
 | 
						|
 | 
						|
			skip = true;
 | 
						|
			ik.solver.Update(); // Update FBBIK again with the rotated shoulders
 | 
						|
		}
 | 
						|
 | 
						|
		// Rotates a shoulder of a FBBIK character
 | 
						|
		private void RotateShoulder(FullBodyBipedChain chain, float weight, float offset) {
 | 
						|
			// Get FromToRotation from the current swing direction of the shoulder to the IK target direction
 | 
						|
			Quaternion fromTo = Quaternion.FromToRotation(GetParentBoneMap(chain).swingDirection, ik.solver.GetEndEffector(chain).position - GetParentBoneMap(chain).transform.position);
 | 
						|
 | 
						|
			// Direction to the IK target
 | 
						|
			Vector3 toTarget = ik.solver.GetEndEffector(chain).position - ik.solver.GetLimbMapping(chain).bone1.position;
 | 
						|
 | 
						|
			// Length of the limb
 | 
						|
			float limbLength = ik.solver.GetChain(chain).nodes[0].length + ik.solver.GetChain(chain).nodes[1].length;
 | 
						|
 | 
						|
			// Divide IK Target direction magnitude by limb length to know how much the limb is being pulled
 | 
						|
			float delta = (toTarget.magnitude / limbLength) - 1f + offset;
 | 
						|
			delta = Mathf.Clamp(delta * weight, 0f, 1f);
 | 
						|
 | 
						|
			// Calculate the rotation offset for the shoulder
 | 
						|
			Quaternion rotationOffset = Quaternion.Lerp(Quaternion.identity, fromTo, delta * ik.solver.GetEndEffector(chain).positionWeight * ik.solver.IKPositionWeight);
 | 
						|
 | 
						|
			// Rotate the shoulder
 | 
						|
			ik.solver.GetLimbMapping(chain).parentBone.rotation = rotationOffset * ik.solver.GetLimbMapping(chain).parentBone.rotation;
 | 
						|
		}
 | 
						|
 | 
						|
		// Get the shoulder BoneMap
 | 
						|
		private IKMapping.BoneMap GetParentBoneMap(FullBodyBipedChain chain) {
 | 
						|
			return ik.solver.GetLimbMapping(chain).GetBoneMap(IKMappingLimb.BoneMapType.Parent);
 | 
						|
		}
 | 
						|
 | 
						|
		// Remove the delegate when destroyed
 | 
						|
		void OnDestroy() {
 | 
						|
			if (ik != null) ik.solver.OnPostUpdate -= RotateShoulders;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |