using System; using System.Collections.Generic; using System.Linq; using RootMotion.FinalIK; using UnityEngine; public class FullBodyIKCtrl : MonoBehaviour { public TBody TgtBody { get { return this.m_TgtBody; } } public Maid TgtChara { get { return this.m_TgtBody.maid; } } public Transform IKTgtRoot { get { return this.m_IKTgtRoot; } } public FullBodyBipedIK FullbodyIK { get { return this.m_FullbodyIK; } } public IKEffector BodyEffector { get { return this.m_FullbodyIK.solver.bodyEffector; } } public BodyCtrlData BodyCtrlData { get { return this.m_BodyCtrlData; } } public Transform BodyTarget { get; private set; } public bool IsUpdateEnd { get; private set; } public Dictionary strIKDataPair { get { return this.m_StrIKDataPair; } } public bool IsIKExec { get { return this.m_StrIKDataPair.Any((KeyValuePair ik) => ik.Value.IsIKExec) && this.IKActive; } } public bool IsSelfIKAttach { get { return this.m_StrIKDataPair.Any((KeyValuePair ik) => ik.Value.IsSelfIKAttach) && this.IKActive; } } public void Init() { this.m_TgtBody = base.GetComponent(); if (!this.m_IKTgtRoot) { this.m_IKTgtRoot = new GameObject("IK Target Root").transform; this.m_IKTgtRoot.SetParent(this.m_TgtBody.m_trBones, false); } if (!this.TgtChara.boMAN) { this.m_STRoot = this.m_TgtBody.m_trBones.Find("ST_Root"); } if (this.m_FullbodyIK) { UnityEngine.Object.DestroyImmediate(this.m_FullbodyIK); } this.m_FullbodyIK = this.m_IKTgtRoot.gameObject.AddComponent(); if (this.m_Mouth) { UnityEngine.Object.DestroyImmediate(this.m_Mouth); } this.m_Mouth = new GameObject("Mouth").transform; this.m_Mouth.SetParent(this.TgtBody.trsHead, false); this.m_Mouth.localEulerAngles = new Vector3(-90f, 90f, 0f); if (!this.TgtChara.boMAN) { if (this.m_NippleL) { UnityEngine.Object.DestroyImmediate(this.m_NippleL); } if (this.m_NippleR) { UnityEngine.Object.DestroyImmediate(this.m_NippleR); } this.m_NippleL = new GameObject("Nipple_L").transform; this.m_NippleL.SetParent(CMT.SearchObjName(this.TgtBody.m_trBones, "Mune_L_sub", true), false); this.m_NippleR = new GameObject("Nipple_R").transform; this.m_NippleR.SetParent(CMT.SearchObjName(this.TgtBody.m_trBones, "Mune_R_sub", true), false); } this.m_NameFlagObjpair.Clear(); this.m_IKBoneDic = FullBodyIKCtrl.GetAllIKBoneDic(this.TgtChara); this.m_FullbodyIK.references.root = this.m_TgtBody.m_trBones; this.m_FullbodyIK.references.pelvis = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Root); if (!this.TgtChara.boMAN) { this.m_FullbodyIK.references.spine = new Transform[] { this.m_IKBoneDic[FullBodyIKCtrl.IKBoneType.Spine0], this.m_IKBoneDic[FullBodyIKCtrl.IKBoneType.Spine3] }; } else { this.m_FullbodyIK.references.spine = new Transform[] { this.m_IKBoneDic[FullBodyIKCtrl.IKBoneType.Spine0], this.m_IKBoneDic[FullBodyIKCtrl.IKBoneType.Spine2] }; } this.m_FullbodyIK.references.head = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Head); this.m_FullbodyIK.references.leftUpperArm = this.GetIKBone(FullBodyIKCtrl.IKBoneType.UpperArm_L); this.m_FullbodyIK.references.leftForearm = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Forearm_L); this.m_FullbodyIK.references.leftHand = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Hand_L); this.m_FullbodyIK.references.rightUpperArm = this.GetIKBone(FullBodyIKCtrl.IKBoneType.UpperArm_R); this.m_FullbodyIK.references.rightForearm = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Forearm_R); this.m_FullbodyIK.references.rightHand = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Hand_R); this.m_FullbodyIK.references.leftThigh = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Thigh_L); this.m_FullbodyIK.references.leftCalf = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Calf_L); this.m_FullbodyIK.references.leftFoot = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Foot_L); this.m_FullbodyIK.references.rightThigh = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Thigh_R); this.m_FullbodyIK.references.rightCalf = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Calf_R); this.m_FullbodyIK.references.rightFoot = this.GetIKBone(FullBodyIKCtrl.IKBoneType.Foot_R); this.m_FullbodyIK.solver.SetToReferences(this.m_FullbodyIK.references, null); this.m_FullbodyIK.fixTransforms = false; foreach (IKEffector ikeffector in this.m_FullbodyIK.solver.effectors) { ikeffector.positionWeight = 0f; ikeffector.rotationWeight = 0f; } foreach (FBIKChain fbikchain in this.m_FullbodyIK.solver.chain) { fbikchain.bendConstraint.weight = 0f; } this.m_BodyCtrlData = this.SafeAddBodyCtrlData("体全体"); this.FullbodyIK.solver.GetChain(FullBodyBipedChain.LeftLeg).pull = 0f; this.FullbodyIK.solver.GetChain(FullBodyBipedChain.RightLeg).pull = 0f; this.AddLimbIKData(FullBodyIKCtrl.IKBoneType.Hand_L, FullBodyIKCtrl.IKBoneType.Forearm_L, FullBodyIKCtrl.IKBoneType.UpperArm_L, FullBodyBipedEffector.LeftHand, FullBodyBipedEffector.LeftShoulder, true); this.AddLimbIKData(FullBodyIKCtrl.IKBoneType.Hand_R, FullBodyIKCtrl.IKBoneType.Forearm_R, FullBodyIKCtrl.IKBoneType.UpperArm_R, FullBodyBipedEffector.RightHand, FullBodyBipedEffector.RightShoulder, true); this.AddLimbIKData(FullBodyIKCtrl.IKBoneType.Foot_L, FullBodyIKCtrl.IKBoneType.Calf_L, FullBodyIKCtrl.IKBoneType.Thigh_L, FullBodyBipedEffector.LeftFoot, FullBodyBipedEffector.LeftThigh, false); this.AddLimbIKData(FullBodyIKCtrl.IKBoneType.Foot_R, FullBodyIKCtrl.IKBoneType.Calf_R, FullBodyIKCtrl.IKBoneType.Thigh_R, FullBodyBipedEffector.RightFoot, FullBodyBipedEffector.RightThigh, false); if (!this.BodyTarget) { Transform transform = this.m_IKTgtRoot.Find(this.BodyEffector.bone.name); if (!transform) { transform = new GameObject(this.BodyEffector.bone.name).transform; } transform.SetParent(this.m_IKTgtRoot, false); this.BodyTarget = new GameObject("IKTarget").transform; this.BodyTarget.SetParent(transform, false); } this.BodyEffector.target = this.BodyTarget; this.BodyEffector.effectChildNodes = false; this.m_FullbodyIK.enabled = false; } private BodyCtrlData SafeAddBodyCtrlData(string key_str) { BodyCtrlData bodyCtrlData = new BodyCtrlData(this); if (this.m_StrIKDataPair.ContainsKey(key_str)) { this.m_StrIKDataPair[key_str] = bodyCtrlData; } else { this.m_StrIKDataPair.Add(key_str, bodyCtrlData); } this.m_BodyCtrlData = bodyCtrlData; return (BodyCtrlData)this.m_StrIKDataPair[key_str]; } private LimbIKData[] AddLimbIKData(FullBodyIKCtrl.IKBoneType hand_foot, FullBodyIKCtrl.IKBoneType elbow_knee, FullBodyIKCtrl.IKBoneType shoulder_thigh, FullBodyBipedEffector handfoot_effector, FullBodyBipedEffector shoulderthigh_effector, bool use_old = false) { IKSolverFullBodyBiped solver = this.FullbodyIK.solver; IKMappingLimb limbMapping = solver.GetLimbMapping(handfoot_effector); FBIKChain chain = solver.GetChain(handfoot_effector); ShoulderThighIKData shoulderThighIKData = new ShoulderThighIKData(solver.GetEffector(shoulderthigh_effector), chain, limbMapping, this, this.GetIKBone(shoulder_thigh)); this.m_StrIKDataPair[FullBodyIKCtrl.IKBoneTypeStrDic[shoulder_thigh]] = shoulderThighIKData; ElbowKneeIKData elbowKneeIKData = new ElbowKneeIKData(chain, limbMapping, this, this.GetIKBone(elbow_knee)); this.m_StrIKDataPair[FullBodyIKCtrl.IKBoneTypeStrDic[elbow_knee]] = elbowKneeIKData; HandFootIKData handFootIKData = new HandFootIKData(solver.GetEffector(handfoot_effector), chain, limbMapping, this, this.GetIKBone(hand_foot), use_old); this.m_StrIKDataPair[FullBodyIKCtrl.IKBoneTypeStrDic[hand_foot]] = handFootIKData; shoulderThighIKData.SetChainData(handFootIKData, elbowKneeIKData); elbowKneeIKData.SetChainData(handFootIKData, shoulderThighIKData); handFootIKData.SetChainData(elbowKneeIKData, shoulderThighIKData); return new LimbIKData[] { shoulderThighIKData, elbowKneeIKData, handFootIKData }; } private void Update() { this.IsUpdateEnd = false; if (this.IKActive) { this.BodyCtrlData.CharaPosReset(); } } private void OnDestroy() { if (this.m_IKTgtRoot) { UnityEngine.Object.Destroy(this.m_IKTgtRoot); } } public void IKUpdate() { if (!this.m_IsPelvisPull) { this.BodyEffector.positionWeight = 1f; } else { this.BodyEffector.positionWeight = 0f; } this.BodyTarget.position = this.BodyEffector.bone.position; this.IsUpdateLate = false; foreach (IKCtrlData ikctrlData in this.m_StrIKDataPair.Values) { ikctrlData.TagetTransCpy(); } this.BodyCtrlData.ApplyIKSetting(); if (this.IsUpdateLate) { return; } if (this.BodyCtrlData.IsIKExec) { this.BodyCtrlData.Update(); } foreach (IKCtrlData ikctrlData2 in this.m_StrIKDataPair.Values) { if (!(ikctrlData2 is BodyCtrlData)) { ikctrlData2.ApplyIKSetting(); } } if (!this.IsUpdateLate) { if (this.IsIKExec || this.AllForceIK) { this.SolverUpdate(); } else { foreach (IKCtrlData ikctrlData3 in this.m_StrIKDataPair.Values) { ikctrlData3.SaveLastBonePosRot(); } } } } public void AttachPointTransCpy(Transform trans, string slot_name, string attach_name, bool scale_cpy = false) { int slotNo = this.TgtBody.GetSlotNo(slot_name); if (this.TgtBody.goSlot[slotNo].morph == null) { return; } Vector3 position; Quaternion rotation; Vector3 localScale; this.TgtBody.goSlot[slotNo].morph.GetAttachPoint(attach_name, out position, out rotation, out localScale, false); trans.position = position; trans.rotation = rotation; if (scale_cpy) { trans.localScale = localScale; } } public void SolverUpdate() { this.IsUpdateEnd = true; Action postSolverUpdate = this.PostSolverUpdate; this.PostSolverUpdate = null; if (this.IKActive) { bool flag = false; foreach (IKCtrlData ikctrlData in this.m_StrIKDataPair.Values) { if (!(ikctrlData is BodyCtrlData)) { if (ikctrlData.NeedFullbodySolverUpdate) { flag = true; break; } } } if (flag) { Vector3 localPosition = this.m_FullbodyIK.references.spine[1].localPosition; this.m_FullbodyIK.solver.Update(); this.m_FullbodyIK.references.spine[1].localPosition = localPosition; } foreach (IKCtrlData ikctrlData2 in this.m_StrIKDataPair.Values) { if (!(ikctrlData2 is BodyCtrlData)) { if (ikctrlData2.IsIKExec) { ikctrlData2.Update(); } } } } foreach (IKCtrlData ikctrlData3 in this.m_StrIKDataPair.Values) { ikctrlData3.LateUpdate(); } if (this.IKActive && postSolverUpdate != null) { postSolverUpdate(); } } public void LateIKUpdate() { this.IKUpdate(); this.TgtBody.AutoTwist(); this.TgtBody.SkinMeshUpdate(); } public Transform GetIKBone(FullBodyIKCtrl.IKBoneType boneType) { return (!this.m_IKBoneDic.ContainsKey(boneType)) ? null : this.m_IKBoneDic[boneType]; } public Transform[] GetChainBonesToInit(FullBodyIKCtrl.IKBoneType boneType) { Transform[] result = new Transform[0]; switch (boneType) { case FullBodyIKCtrl.IKBoneType.UpperArm_R: case FullBodyIKCtrl.IKBoneType.Forearm_R: case FullBodyIKCtrl.IKBoneType.Hand_R: result = new Transform[] { this.GetIKBone(FullBodyIKCtrl.IKBoneType.UpperArm_R), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Forearm_R), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Hand_R) }; break; case FullBodyIKCtrl.IKBoneType.UpperArm_L: case FullBodyIKCtrl.IKBoneType.Forearm_L: case FullBodyIKCtrl.IKBoneType.Hand_L: result = new Transform[] { this.GetIKBone(FullBodyIKCtrl.IKBoneType.UpperArm_L), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Forearm_L), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Hand_L) }; break; case FullBodyIKCtrl.IKBoneType.Thigh_R: case FullBodyIKCtrl.IKBoneType.Calf_R: case FullBodyIKCtrl.IKBoneType.Foot_R: result = new Transform[] { this.GetIKBone(FullBodyIKCtrl.IKBoneType.Thigh_R), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Calf_R), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Foot_R) }; break; case FullBodyIKCtrl.IKBoneType.Thigh_L: case FullBodyIKCtrl.IKBoneType.Calf_L: case FullBodyIKCtrl.IKBoneType.Foot_L: result = new Transform[] { this.GetIKBone(FullBodyIKCtrl.IKBoneType.Thigh_L), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Calf_L), this.GetIKBone(FullBodyIKCtrl.IKBoneType.Foot_L) }; break; } return result; } public IKCtrlData GetIKData(string tag_name, bool flagcheck = false) { return this.GetIKData(tag_name); } public IKCtrlData GetIKData(string tag_name) { if (this.m_StrIKDataPair.ContainsKey(tag_name)) { return this.m_StrIKDataPair[tag_name]; } return null; } public T GetIKData(string tag_name) where T : IKCtrlData { IKCtrlData ikdata = this.GetIKData(tag_name); if (ikdata != null && ikdata is T) { return ikdata as T; } return (T)((object)null); } public IKCtrlData GetIKData(FullBodyIKCtrl.IKBoneType bone_type) { if (FullBodyIKCtrl.IKBoneTypeStrDic.ContainsKey(bone_type)) { return this.GetIKData(FullBodyIKCtrl.IKBoneTypeStrDic[bone_type]); } return null; } public T GetIKData(FullBodyIKCtrl.IKBoneType bone_type) where T : IKCtrlData { IKCtrlData ikdata = this.GetIKData(bone_type); if (ikdata != null && ikdata is T) { return ikdata as T; } return (T)((object)null); } public Transform GetSTFlagObj(string name) { if (this.m_NameFlagObjpair.ContainsKey(name)) { return this.m_NameFlagObjpair[name]; } Transform transform = this.m_STRoot.Find(name); if (!transform) { transform = this.TgtBody.GetBone(name); if (!transform) { Debug.LogErrorFormat("{0}は存在しません", new object[] { name }); return null; } } this.m_NameFlagObjpair.Add(name, transform); return transform; } public bool IsCharaIKAttach(Maid chara) { if (!this.IKActive || !this.IsIKExec) { return false; } foreach (IKCtrlData ikctrlData in this.strIKDataPair.Values) { if (ikctrlData.IsIKTargetChara(chara)) { return true; } } return false; } public bool IsTargetIKAttachSelf(bool check_ikend = true) { if (!this.IKActive || !this.IsIKExec) { return false; } using (Dictionary.ValueCollection.Enumerator enumerator = this.strIKDataPair.Values.GetEnumerator()) { while (enumerator.MoveNext()) { IKCtrlData ik_data = enumerator.Current; Func func = delegate(IKCtrlData.IKAttachType attach_type) { IKCtrlData.IKSettingData iksettingData = ik_data.GetIKSettingData(attach_type); foreach (IKCtrlData.IKExecTiming exec_timing in (IKCtrlData.IKExecTiming[])Enum.GetValues(typeof(IKCtrlData.IKExecTiming))) { IKCtrlData.IKTargetData targetData = ik_data.GetTargetData(attach_type, exec_timing); if (targetData.TgtChara) { bool flag; if (check_ikend) { flag = (targetData.TgtChara.IKCtrl.IsCharaIKAttach(this.TgtChara) && !targetData.TgtChara.IKCtrl.IsUpdateEnd && !targetData.TgtChara.IKCtrl.IsUpdateLate); } else { flag = targetData.TgtChara.IKCtrl.IsCharaIKAttach(this.TgtChara); } if (flag) { return true; } } } return false; }; if (func(IKCtrlData.IKAttachType.NewPoint) || func(IKCtrlData.IKAttachType.Rotate)) { return true; } } } return false; } public void SetPelvisPull(bool pull_on) { this.m_IsPelvisPull = pull_on; } public static Dictionary GetAllIKBoneDic(Maid chara) { if (chara == null) { return null; } NDebug.Assert(chara.body0 != null, "[body0] it does not end load."); string text = (!chara.boMAN) ? "Bip01" : "ManBip"; Dictionary dictionary = new Dictionary(); dictionary.Add(FullBodyIKCtrl.IKBoneType.TopFixed, chara.body0.GetBone(text).parent); dictionary.Add(FullBodyIKCtrl.IKBoneType.Root, chara.body0.GetBone(text)); dictionary.Add(FullBodyIKCtrl.IKBoneType.Pelvis, chara.body0.GetBone(text + " Pelvis")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Spine0, chara.body0.GetBone(text + " Spine")); if (!chara.boMAN) { dictionary.Add(FullBodyIKCtrl.IKBoneType.Spine1, chara.body0.GetBone(text + " Spine0a")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Spine2, chara.body0.GetBone(text + " Spine1")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Spine3, chara.body0.GetBone(text + " Spine1a")); } else { dictionary.Add(FullBodyIKCtrl.IKBoneType.Spine1, chara.body0.GetBone(text + " Spine1")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Spine2, chara.body0.GetBone(text + " Spine2")); } dictionary.Add(FullBodyIKCtrl.IKBoneType.Head, chara.body0.GetBone(text + " Head")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Neck, chara.body0.GetBone(text + " Neck")); dictionary.Add(FullBodyIKCtrl.IKBoneType.UpperArm_R, chara.body0.GetBone(text + " R UpperArm")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Forearm_R, chara.body0.GetBone(text + " R Forearm")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Hand_R, chara.body0.GetBone(text + " R Hand")); dictionary.Add(FullBodyIKCtrl.IKBoneType.UpperArm_L, chara.body0.GetBone(text + " L UpperArm")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Forearm_L, chara.body0.GetBone(text + " L Forearm")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Hand_L, chara.body0.GetBone(text + " L Hand")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Thigh_R, chara.body0.GetBone(text + " R Thigh")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Calf_R, chara.body0.GetBone(text + " R Calf")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Foot_R, chara.body0.GetBone(text + " R Foot")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Thigh_L, chara.body0.GetBone(text + " L Thigh")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Calf_L, chara.body0.GetBone(text + " L Calf")); dictionary.Add(FullBodyIKCtrl.IKBoneType.Foot_L, chara.body0.GetBone(text + " L Foot")); return dictionary; } public const float PULL_MIN_VALUE = 0.1f; public static readonly Dictionary IKBoneTypeStrDic = new Dictionary { { FullBodyIKCtrl.IKBoneType.Root, "体全体" }, { FullBodyIKCtrl.IKBoneType.Hand_R, "右手" }, { FullBodyIKCtrl.IKBoneType.Forearm_R, "右肘" }, { FullBodyIKCtrl.IKBoneType.UpperArm_R, "右肩" }, { FullBodyIKCtrl.IKBoneType.Hand_L, "左手" }, { FullBodyIKCtrl.IKBoneType.Forearm_L, "左肘" }, { FullBodyIKCtrl.IKBoneType.UpperArm_L, "左肩" }, { FullBodyIKCtrl.IKBoneType.Foot_R, "右足" }, { FullBodyIKCtrl.IKBoneType.Calf_R, "右膝" }, { FullBodyIKCtrl.IKBoneType.Thigh_R, "右腿" }, { FullBodyIKCtrl.IKBoneType.Foot_L, "左足" }, { FullBodyIKCtrl.IKBoneType.Calf_L, "左膝" }, { FullBodyIKCtrl.IKBoneType.Thigh_L, "左腿" } }; [SerializeField] private TBody m_TgtBody; [SerializeField] private Transform m_IKTgtRoot; [SerializeField] private Transform m_STRoot; [SerializeField] private FullBodyBipedIK m_FullbodyIK; private Dictionary m_IKBoneDic = new Dictionary(); [SerializeField] private BodyCtrlData m_BodyCtrlData; private Transform m_NippleL; private Transform m_NippleR; private Transform m_Mouth; private Dictionary m_StrIKDataPair = new Dictionary(); private Dictionary m_NameFlagObjpair = new Dictionary(); public bool IKActive = true; [HideInInspector] public bool IsUpdateLate; public Action PostSolverUpdate; public bool AllForceIK; public float BlendTime = 0.5f; private bool m_IsPelvisPull; public enum IKBoneType { TopFixed, Root, Spine0, Spine1, Spine2, Spine3, Neck, Head, Clavicle_R, UpperArm_R, Forearm_R, Hand_R, Clavicle_L, UpperArm_L, Forearm_L, Hand_L, Pelvis, Thigh_R, Calf_R, Foot_R, Thigh_L, Calf_L, Foot_L } }