手足にコライダーをつけてキックやパンチの判定に使います。剣にコライダーをつけて斬撃を判定するのと仕組みは同じです。
UI的に手動でコライダーをつけることもできますが、それだとキャラを追加するごとに作業が要ります。
プログラムでコライダーを装着すれば、キャラ追加時もなにも作業が要りませんので効率的です。
具体的には、球型のIsTriggerなコライダーをprefabとして準備しておきます。
骨の位置を取得して子要素として登録します。
球コライダーはmeshを非表示にしておけば、コライダーのみ有効になります。
足の攻撃として、足首よりもつま先にコライダーが欲しいので、forward*0.1fだけ足して、つま先方向に動かしました。
anim = GetComponent<Animator>(); //右手のコライダー Transform Rhand = anim.GetBoneTransform(HumanBodyBones.RightHand); GameObject RhandSph = Instantiate((GameObject)Resources.Load("Sphere"), Vector3.zero, Quaternion.identity) as GameObject; RhandSph.transform.position = Rhand.position;// +Rhand.right*0.1f; RhandSph.transform.SetParent(Rhand); //左手のコライダー Transform Lhand = anim.GetBoneTransform(HumanBodyBones.LeftHand); GameObject LhandSph = Instantiate((GameObject)Resources.Load("Sphere"), Vector3.zero, Quaternion.identity) as GameObject; LhandSph.transform.SetParent(Lhand); LhandSph.transform.position = Lhand.position;// + Rhand.right * 0.1f; //右足のコライダー Transform Rfoot = anim.GetBoneTransform(HumanBodyBones.RightFoot); GameObject RfootSph = Instantiate((GameObject)Resources.Load("Sphere"), Vector3.zero, Quaternion.identity) as GameObject; RfootSph.transform.SetParent(Rfoot); RfootSph.transform.position = Rfoot.position + Rfoot.forward*0.1f -Rfoot.up*0.1f; //左足のコライダー Transform Lfoot = anim.GetBoneTransform(HumanBodyBones.LeftFoot); GameObject LfootSph = Instantiate((GameObject)Resources.Load("Sphere"), Vector3.zero, Quaternion.identity) as GameObject; LfootSph.transform.SetParent(Lfoot); LfootSph.transform.position = Lfoot.position + Lfoot.forward * 0.1f -Lfoot.up*0.1f;
衝突判定の部分は次のような感じになります。足や手の衝突はSphereとして取れます。
普通の状態で接触しても攻撃にならないように、Sphereの持ち主が攻撃モーション実行中かどうかを調べます。
自分が味方側で、相手が敵側の場合に、5ダメージを、ApplyDamage関数に渡します。Sphereの持ち主を表す番号noと、打突位置も渡します。
(持ち主にexpなどの加点を行い、打突位置にエフェクトを表示します)
void OnTriggerEnter(Collider other) { if (other.name == "Sphere") { AnimatorStateInfo stateInfo = _parent.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0); if (stateInfo.IsName("Zattack") && stateInfo.normalizedTime <= 1f) if (!isMonster(name) && isMonster(_parent.name)) ApplyDamage(5, _parent.GetComponent<character>().no, other.transform); }
ほぼ同じロジックですが、剣の衝突の場合は、以下のような感じ。
相手が剣をふるモーションを実行しているか確認します。また、ハンマー斬撃など動きが大きい場合、振り下ろしと振り上げで二回Enterが発生したりするので、
振り下ろしモーション時の衝突のみ有効にカウントするために、「stateInfo.normalizedTime < 0.6f」と判定します。
これは、アニメーションの再生時間位置の正規化された値で、0→1で変化します。
0.6だと60%ぐらいなので、振り下ろしのみ有効という感じです。実行時の様子などを見てアバウトに決めています。
if (other.name == "Sword") { AnimatorStateInfo stateInfo = _parent.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0); if (stateInfo.IsName("Sword") && stateInfo.normalizedTime < 0.6f) { if (isMonster(name) && !isMonster(_parent.name)) ApplyDamage(20, _parent.GetComponent<character>().no, other.transform); if (!isMonster(name) && isMonster(_parent.name)) ApplyDamage(20, _parent.GetComponent<character>().no, other.transform); } }