AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

IKを使った足の接地

Unity でキャラクタの足の位置を地面の形状に合わせてみた - 凹みTips

上記の記事を参考に足の接地をやってみました。
ただ、PMCAのモブ子さんはつま先のboneがもともと無いようです。


 接地とは、身体のコライダーが地面のコライダーと接地しているのは同じで、そこから体全体を下げつつ、でも、足はめり込まないように持ち上げるという処理になりますね。
f:id:yasu9780:20161009152438p:plain


 下のブロックを左右で上下させた結果
f:id:yasu9780:20161009152348g:plain

 処理の流れとしては、
①左右の足の下にそれぞれ光線を出して地面との距離を計測
②足と地面が接地するように足を動かす
③左右の足の移動量のうち、大きい方だけ体全体を動かす
 本来はかかとを浮かしてつま先だけ接地とかやるべきなんでしょうけど。とりあえずそれは無し。

using UnityEngine;
using System.Collections;

public class IKmain : MonoBehaviour {
    Animator anim;
    GameObject box;
    GameObject box2;
    void Start () {
        box = GameObject.Find("Cube");
        box2 = GameObject.Find("Cube2");
        anim = GetComponent<Animator>();
    }
    void Update () {
        if (Input.GetKeyDown(KeyCode.DownArrow)) box.transform.position -= Vector3.up*Time.deltaTime;
        if (Input.GetKeyDown(KeyCode.UpArrow)  ) box.transform.position += Vector3.up * Time.deltaTime;
        if (Input.GetKeyDown(KeyCode.LeftArrow)) box2.transform.position -= Vector3.up * Time.deltaTime;
        if (Input.GetKeyDown(KeyCode.RightArrow)) box2.transform.position += Vector3.up * Time.deltaTime;
    }
    void OnAnimatorIK()
    {
        Vector3 rightPos = anim.GetIKPosition(AvatarIKGoal.RightFoot);
        Vector3 leftPos = anim.GetIKPosition(AvatarIKGoal.LeftFoot);
        Vector3 diffR=Vector3.zero;
        Vector3 diffL = Vector3.zero;
        RaycastHit ray;
        if (Physics.Raycast(rightPos+ Vector3.up * 0.3f, Vector3.down, out ray))
        {
            diffR = (rightPos - ray.point) - Vector3.up * 0.1f;
            SetIk(AvatarIKGoal.RightFoot, -diffR, Quaternion.Euler(Vector3.zero) );
        }
        if (Physics.Raycast(leftPos + Vector3.up * 0.3f, Vector3.down, out ray))
        {
            diffL = (leftPos - ray.point) - Vector3.up * 0.1f;
            SetIk(AvatarIKGoal.LeftFoot, -diffL, Quaternion.Euler(Vector3.zero));
        }
        anim.bodyPosition += Mathf.Max(diffR.y, diffL.y)*Vector3.down;
    }
    void SetIk(AvatarIKGoal goal,Vector3 pos, Quaternion rot)
    {
        anim.SetIKRotation(goal, rot);
        anim.SetIKPosition(goal, anim.GetIKPosition(goal)+pos);
        anim.SetIKPositionWeight(goal, 1f);
        anim.SetIKRotationWeight(goal, 1f);
    }
}