Unity3D 階段を上り下りをするIKを作る方法が知りたい
Unity3Dで階段を上り下りするIKの作り方が知りたいです。段差や坂道で足を地面にくっつける方法などは調べましたが階段を上る下りるとなると情報がなく困っています。
質問としましては、階段として上る段差の高さの情報を得てそこに足が乗るようにモーションをIKさせて片足が乗ったらその足を固定して逆の足も物体に乗せるという処理のはずですがどうすればいいのでしょうか?
以下の画像のような段差を上りたいです。
提示コード
プレイヤーIK(暫定)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_IK : MonoBehaviour {
Animator ani;
// public Transform LeftFoot;
// public Transform RightFoot;
private bool cLeft, cRight;
private bool s;//IKを実行するかどうか?
private float f = -0.1f;
// Start is called before the first frame update
void Start( ) {
cRight = cLeft = false;
s = false;
ani = GetComponent<Animator>( );
isRightFootIK = false;
isLeftFootIK = false;
}
private Vector3 rightFootPos;
private Vector3 leftFootPos;
private Quaternion rightFootRot;
private Quaternion leftFootRot;
private bool isRightFootIK;
private bool isLeftFootIK;
private Vector3 rayPosoffset = Vector3.up * 0.3f;
//private Vector3 rayPosoffset = Vector3.up * -2.0f;
private float maxDistance = 1.0f;
// [SerializeField]
// private float ray_range = 1.0f;//レイの距離
private float ray_range = 0.45f;//レイの距離
[SerializeField]
float Leftpos = -0.5f;
[SerializeField]
float Rightpos = -0.5f;
/*ウエイト取得*/
[SerializeField]
private float rightFootWeight;
[SerializeField]
private float leftFootWeight;
// Update is called once per frame
void Update( ) {
rightFootWeight = ani.GetFloat( "Right" );
leftFootWeight = ani.GetFloat( "Left" );
//rightFootWeight = 1;
//leftFootWeight = 1;
// rightFootWeight = 0.6f;
// leftFootWeight = 0.6f;
Debug.Log( "righ: " + rightFootWeight );
Debug.Log( "Left: " + leftFootWeight );
}
private void OnAnimatorIK( ) {
Ray r = new Ray( ani.GetIKPosition( AvatarIKGoal.RightFoot ) + rayPosoffset, -transform.up );
RaycastHit rayHit;
Debug.DrawRay( ani.GetIKPosition( AvatarIKGoal.RightFoot ) + rayPosoffset, -transform.up * ray_range, Color.red );
/*右足のIK*************************/
if ( Physics.Raycast( r, out rayHit, ray_range ) ) {
rightFootPos = rayHit.point;
rightFootRot = Quaternion.FromToRotation( transform.up, rayHit.normal ) * transform.rotation;
isRightFootIK = true;
} else {
isRightFootIK = false;
}
/*左足のIK*************************/
r = new Ray( ani.GetIKPosition( AvatarIKGoal.LeftFoot ) + rayPosoffset, -transform.up );
Debug.DrawRay( ani.GetIKPosition( AvatarIKGoal.LeftFoot ) + rayPosoffset, -transform.up * ray_range, Color.red );
if ( Physics.Raycast( r, out rayHit, ray_range ) ) {
leftFootPos = rayHit.point;
leftFootRot = Quaternion.FromToRotation( transform.up, rayHit.normal ) * transform.rotation;
isLeftFootIK = true;
} else {
isLeftFootIK = false;
}
// Debug.DrawLine(RightFoot.position, RightFoot.position + new Vector3(0, f, 0),Color.red);
// Debug.DrawLine(LeftFoot.position, LeftFoot.position + new Vector3(0, f, 0),Color.blue);
/*IK処理*/
/*左足*/
if ( isLeftFootIK ) {
// Debug.Log("left");
ani.SetIKPositionWeight( AvatarIKGoal.LeftFoot, rightFootWeight );
ani.SetIKRotationWeight( AvatarIKGoal.LeftFoot, rightFootWeight );
ani.SetIKPosition( AvatarIKGoal.LeftFoot, leftFootPos + new Vector3( 0, Leftpos, 0 ) );
ani.SetIKRotation( AvatarIKGoal.LeftFoot, leftFootRot );
}
/*右足*/
if ( isRightFootIK ) {
// Debug.Log("right");
ani.SetIKPositionWeight( AvatarIKGoal.RightFoot, leftFootWeight );
ani.SetIKRotationWeight( AvatarIKGoal.RightFoot, leftFootWeight );
// ani.SetIKPosition(AvatarIKGoal.RightFoot, rightFootPos + new Vector3(0, Rightpos, 0));
ani.SetIKPosition( AvatarIKGoal.RightFoot, rightFootPos );
ani.SetIKRotation( AvatarIKGoal.RightFoot, rightFootRot );
}
}
}