きっかけ
普段クレーンゲームで遊ぶことはありませんが、ショッピングモールでその複雑な動きを観察しているうちに、「以前触ったサーボモーターや3Dプリンターの知識を活かして、Unityでシミュレーションできないか?」と思い立ちました。
現在学習中の Gemini Robotics-ER(ロボティクス学習)の参考も兼ねて、あえて一般的な「ゲーム用クレーン」ではなく、「産業用ロボット風」のデザインでクレーンゲームを制作してみます。
クレーンゲームの3Dモデル制作
玩具売り場の実機を参考にしつつ、Blenderでインダストリアルな外観のモデルを制作しました。
Unityへの持ち込みを考慮した設計
指先の爪の部分は、面が垂直になる角度を0度として設計しています。
理由: Unityに取り込んだ際、Box Collider をアタッチしたときに爪の面とコライダーがピタッと一致するためです。
動作範囲: -20度(min)〜 10度(max)に設定。
Unity上での物理ジョイント構築
1. なぜ「すべて」物理駆動にするのか
実験の結果、クレーンを動かす際に Transform の値を直接書き換える(IsKinematic = true)手法では、爪がワーク(掴む対象)に触れた際の摩擦力や反発力が正しく計算されないことが分かりました。
ワークをしっかり「掴む」ためには、全可動部をジョイント(Joint)で接続し、IsKinematic = false の状態で物理演算によって駆動させる必要があります。
2. Configurable Joint による直線移動
アームの水平(XZ軸)および垂直(Y軸)の動きには、Configurable Joint を使用しました。FixedUpdate 内で connectedAnchor の値を更新することで、物理的な制約を保ったまま移動させています。
void FixedUpdate()
{
if (Keyboard.current == null) return;
// スライダー(X軸移動)
if (sliderJoint != null)
{
var anchor = sliderJoint.connectedAnchor;
if (Keyboard.current.aKey.isPressed) anchor.x -= speed * Time.deltaTime;
else if (Keyboard.current.dKey.isPressed) anchor.x += speed * Time.deltaTime;
sliderJoint.connectedAnchor = anchor;
}
// アーム(Y軸移動:上下)
if (armJoint != null)
{
var anchor = armJoint.connectedAnchor;
if (Keyboard.current.wKey.isPressed) anchor.y -= speed * Time.deltaTime; // 下降
else if (Keyboard.current.sKey.isPressed) anchor.y += speed * Time.deltaTime; // 上昇
armJoint.connectedAnchor = anchor;
}
// ハンド(Z軸移動:前後)
if (handJoint != null)
{
var anchor = handJoint.connectedAnchor;
if (Keyboard.current.upArrowKey.isPressed) anchor.z += speed * Time.deltaTime;
else if (Keyboard.current.downArrowKey.isPressed) anchor.z -= speed * Time.deltaTime;
handJoint.connectedAnchor = anchor;
}
:
}
指の開閉と「揺れ」の克服
Hinge Joint と Motor の活用
指の開閉には、サーボモーターの動作を模倣できる Hinge Joint の Motor 機能を利用します。
課題:持ち上げ時の「ブランコ現象」
物理演算のみで掴むと、ワークを持ち上げて横に移動する際、慣性や重力によって指がブランコのように揺れてしまい、安定しません。
解決策:Limits を動的に制御する
Hinge Joint の Limits(Min/Max) をハック的に利用することで解決しました。
Max値: 指のターゲット角度を設定。
Min値: Max - 1 程度の値に設定。
この「わずか1度の遊び」の中で駆動させると、Hinge Jointの Spring機能やMotor機能を使わずとも、指定した角度へヒンジを強制的に回転させることが出来ました(適当に色々と試していたら、この方法であれば、望む動作を実現出来ることが偶然分かりました)。
注意点: この方法は指を強引に固定するため、値を誤ると指がワークを貫通(めり込み)してしまい、反動でワークを弾き飛ばしてしまうことがあります。
次のステップ:把持力の最適化
「物理的に固定する」だけでなく、実際のロボットのように「指先がワークを押す力をセンサーで検知し、適切な力で止める」ことはできないでしょうか?
次回の記事では、擬似的な圧力センサーを実装し、ワークの形状や硬さに合わせた最適な「把持力」を実現する実験について紹介します。
(2025/12/27 追記)HingeJoint の Limits で角度を設定する方法は簡単だが、この記事を書いた後、Unityでは、ロボティクス専用に ArticulationBodyというコンポーネントが準備されていることを知った。次回は HingeJoint による手法を紹介し、その後、ArticulationBodyによる手法にチャレンジし、どちらの手法が物理学に沿った摩擦係数をリアルにシミュレーション出来るか比較してみたい。
本記事で紹介した制作物
以下のGitHubプロジェクトで公開します。






