メインコンテンツまでスキップ

2025-05-02 Parent Constraint の「Activate」ボタンについて

注記

このページは AI(Claude)によって翻訳されています。翻訳に誤りが含まれる可能性があります。

Skinned Mesh Constraint を開発している最中に、奇妙なことに気づいたので、 どこかに記録しておきたいと思いました。

Skinned Mesh Constraint は、メッシュのスキニングによって頂点が動くのと同じように、Parent Constraint を動かすためのツールです。

アプローチ #1:ボーンを対象にした Constraint を Activate する​

私はこれまで、Parent Constraint の Activate ボタンを押すと、GameObject が、レストポーズからの相対的なウェイトの割合に応じて、 ソースの Transform に追従するようになるものだと思っていました。

このため、Skinned Mesh Constraint コンポーネントを作ろうとしたとき、最初のアプローチは、メッシュにペイントされたウェイトを収集し、 対応する Parent Constraint のソースを設定してから、リフレクションを使って(VRC 以外のプロジェクトで)Activate ボタンを押すというものでした。

ところが、ボーンを動かすと、Parent Constraint の動きがメッシュのスキニングと同じになりません(行き過ぎてしまいます)。

アプローチ #2:ボーン内に置いた新しいオフセット用 Transform を対象にした Constraint を Activate する​

次に、レスト時に Position Constraint と同じ位置になるようオフセットした新しい Transform を、ボーンの内側に作ってみました。

この方法はうまくいきました。つまり、Parent Constraint が内部でどう動作するのかについて、私は何か勘違いしていたのです。これらの観察結果をもとに、 2 つの Discord サーバーで助けを求めました。

すると Sacred さんという方から、私のアプローチ #2 がメッシュのスキニングに対する正しいアプローチだと教えてもらいました(Sacred さんはこのアプローチを Voxian さんという別の方の功績としていたので、 私は再発見しただけです)。また、複数の Constraint(ボーン 1 つにつき Parent Constraint 1 つ)を使う、それより劣る別の方法もあるとのことでした。

この方法には Constraint の数が少なくて済むという利点がありますが、Transform の参照がより多く必要になります。

この Discord でのやり取りをきっかけに、3 つ目のアプローチの調査を始めました。

アプローチ #3:オフセットの Transform を手動で計算する​

Activate ボタンをクリックすると、Parent Constraint は、レスト時の Constraint ソースに対する相対オフセットの情報を保存します。

アプローチ #1 では、これらのオフセットに何らかの値が入っています。

アプローチ #2 では、これらのオフセットはすべてゼロです。

この新しいアプローチでは、先ほど作った、ボーン内のオフセット用 Transform の位置と回転を、これらのオフセットにコピーしてみました。 Constraint は、それらのオフセット用 Transform ではなく、ボーンを直接対象にしています。

結果として、これらのオフセットを手で書き込むことで問題が解決しました。追加の Transform を参照する必要もないため、 これが Skinned Mesh Constraint で採用している方法です。

オフセットは、回転については (Quaternion.inverse(sourceTransform.rotation) * constraint.rotation).eulerAngles を使って計算し、 平行移動のオフセットについては sourceTransform.InverseTransformPoint(constraint.position) こちらの回答を参考にしています。

では、Constraint の Activate ボタンは何をしているのか?​

Constraint の Activate ボタンがどう動作するのか、私にはわかりません。

このボタンが何をしているのかを可視化してみましたが、奇妙です。Activate をクリックすると、脚のボーンのオフセットが、予想外の位置を指しています。

Unity_lThgeTtkJV.png

上の画像では、赤い線の先端がオフセットのワールド空間での位置を指していますが、Constraint の対象となっているオブジェクトはレスト状態です。

メッシュのスキニングに従うように Parent Constraint を設定した場合、レスト位置そのものがオフセットなので、赤い線はまったく表示されないはずです。

これ以上のことは私にもわかりませんが、 これは、Constraint の Activate ボタンを押した場合の挙動が、 オフセットを手で計算した場合とは異なることを意味します。

2025-05-03 更新: Activate ボタンの仕組みについて新しい情報を知ることができたので、 この記事は、製品のアップデートとともに、後ほど更新する予定です。