① で移動の土台、② でIKによる視線・足・手の制御を作りました。
シリーズ最終回は、アニメーションクリップに頼らず 、コードで足を一歩ずつ運ばせる「手続き的歩行(Procedural Walk)」と、上体が倒れないようにする重心バランス補正(Balance)を解説します。
これができると、坂道・不整地でも自然に足を踏み替えるキャラが作れます。
・手続き的歩行とは
通常の歩行はWalkアニメをループ再生します。対して手続き的歩行は、
- 足を置くべき「目標地点(ステップターゲット)」を計算で決める
- 体が進んで足が目標から離れすぎたら、その足を振り上げて新しい位置へ着地させる
- 足の位置は②のIKで反映する
という仕組みです。
アニメが無くても動き、地形にも自動で追従するのが利点です。仕組みの核は「いつ足を踏み替えるか」の判定です。
全体の流れ [移動入力] → 体(ルート)が前進
→ 各足の「接地目標」を体の左右にオフセットして計算
→ 足が目標から閾値以上ズレたら STEP(振り上げ→着地)
→ 着地位置・浮いている間の弧を IK ターゲットへ渡す
→ BalanceController が重心を支持脚側へ寄せる
1.片足を表す構造体
左右の足それぞれに「今の接地点」「目標点」「ステップ進行度」を持たせます。
using UnityEngine; [System.Serializable]
public class FootStepper
{
public Transform ikTarget; // ②のHand/FootIKに渡すターゲット
public Vector3 restOffset; // 体から見た足の基準位置(左右)
[HideInInspector] public Vector3 currentPos; // 今の接地点(ワールド)
[HideInInspector] public bool isStepping;
[HideInInspector] public float stepT; // 0→1 のステップ進行
Vector3 _from, _to; public void BeginStep(Vector3 target)
{
_from = currentPos;
_to = target;
stepT = 0f;
isStepping = true;
} public void Tick(float stepSpeed, float stepHeight)
{
if (!isStepping) return;
stepT += Time.deltaTime * stepSpeed;
// 水平は補間、垂直はsinで弧を描いて足を持ち上げる
Vector3 flat = Vector3.Lerp(_from, _to, stepT);
flat.y += Mathf.Sin(stepT * Mathf.PI) * stepHeight;
currentPos = flat;
if (stepT >= 1f) { currentPos = _to; isStepping = false; }
if (ikTarget != null) ikTarget.position = currentPos;
}
}
Mathf.Sin(stepT * π) で 0→最高点→0 の弧を描き、足が地面を擦らず持ち上がります。
2.ProceduralWalk 本体 体の移動に応じて各足の目標を計算し、ズレが閾値を超え、かつ反対の足が接地中のときだけ踏み替えます(両足同時に浮かないように)。
public class ProceduralWalk : MonoBehaviour
{
[SerializeField] FootStepper left, right;
[SerializeField] float stepThreshold = 0.35f; // この距離ズレたら踏み替え
[SerializeField] float stepSpeed = 4f;
[SerializeField] float stepHeight = 0.18f;
[SerializeField] LayerMask groundMask = ~0; void Update()
{
UpdateFoot(left, right);
UpdateFoot(right, left);
left.Tick(stepSpeed, stepHeight);
right.Tick(stepSpeed, stepHeight);
} void UpdateFoot(FootStepper foot, FootStepper other)
{
// 体基準の理想接地点を地面にスナップ
Vector3 desired = transform.TransformPoint(foot.restOffset);
if (Physics.Raycast(desired + Vector3.up, Vector3.down, out var hit, 3f, groundMask))
desired = hit.point; float dist = Vector3.Distance(foot.currentPos, desired); // 自分が止まっていて、相手も止まっていて、十分ズレたら踏み替え if (!foot.isStepping && !other.isStepping && dist > stepThreshold) foot.BeginStep(desired); }
}
チューニングのコツ
- stepThreshold を小さくすると歩幅が細かく、大きくすると大股に。
- 両足が同時にステップしない条件(!other.isStepping)が崩れると、空中で滑って見えます。最重要の安全弁です。
- currentPos を②の HumanoidIKController の足IKターゲットとして渡せば、計算した足位置がそのまま反映されます。
3.重心バランス補正(BalanceController) 手続き歩行では片足立ちの瞬間があり、そのままだと上体が中央のままで不自然です。支持脚(接地している足)側へ重心(腰)を少し寄せると、人間らしい体重移動になります。
public class BalanceController : MonoBehaviour
{
[SerializeField] Transform hips;
[SerializeField] FootStepper left, right; // 接地状態を参照
[SerializeField] float shiftAmount = 0.06f;
[SerializeField] float shiftSpeed = 6f;
Vector3 _baseLocalPos; void Start() { if (hips) _baseLocalPos = hips.localPosition; } void LateUpdate() // ①と同じく、Animator適用後に最終調整
{
if (hips == null) return; // 接地している足の中点を支持点とみなす Vector3 support = SupportPoint(); Vector3 toSupport = transform.InverseTransformPoint(support); toSupport.y = 0f; Vector3 target = _baseLocalPos + Vector3.ClampMagnitude(toSupport, 1f) * shiftAmount; hips.localPosition = Vector3.Lerp(hips.localPosition, target, Time.deltaTime * shiftSpeed); } Vector3 SupportPoint()
{
bool lOn = !left.isStepping, rOn = !right.isStepping;
if (lOn && rOn) return (left.currentPos + right.currentPos) * 0.5f;
return lOn ? left.currentPos : right.currentPos;
}
}
⚠️ 腰の操作は必ず LateUpdate で。①で触れたように、Updateで動かしてもAnimatorが後から上書きします。さらに本プロジェクトでは「腰をルート真上に固定 」する処理と競合しやすいので、バランス補正は「ルート真上固定の後」に微小オフセットとして加えるのが安全です。
よくあるハマりどころ
| 症状 | 原因 |
| 足が地面を滑る | 両足が同時にステップしている(!other.isStepping条件の欠落) |
| 足が地面に刺さる/浮く | ステップ目標のレイ接地が漏れている/②のfootOffsetY未調整 |
| 体がガクガク揺れる | shiftSpeedが高すぎ、または腰を複数箇所で奪い合っている |
| 坂で足が宙に浮く | restOffsetからのレイ距離・マスクが地面に届いていない |
| 一歩が大きすぎる | stepThresholdが大きすぎる |
まとめ(シリーズ総括)
- ① CharacterControllerで移動、Animatorで歩行ブレンド、腰をLateUpdateで固定
- ② OnAnimatorIKで視線・足・手を環境に合わせて制御
- ③ ステップターゲットで足を手続き的に運び、重心を支持脚へ寄せてバランスを取る
この3つを組み合わせると、平地のアニメ歩行から、不整地でも自然に足を踏み替えるキャラまで段階的に作れます。実際のプロジェクトでは、アニメ歩行(①)をベースに、坂や段差でIK(②)と手続き要素(③)を混ぜるハイブリッドが扱いやすいです。

