【VRChat】Constraintでワールド固定ができなくて詰んだが、どうにか解決した話

Constraintが使えるようになってワールド固定できるとの情報がたくさん出てました。
しかし、いろいろな記事を読みながら何度試してもうまくいかずに困っていましたが、なんとか解決したので備忘録的に情報をまとめます。

・どうなっていたのか

まず、どういう症状に悩まされていたのかというと、アバターを移動させたときはオブジェクトが固定されていましたが、アバターの向いている方向を変えると何故かオブジェクトが吹き飛んでいました。

・原因

実装方法などは調べれば大量に出るので多くは触れません。
端的に言うと以下の箇所が原因でした。

画像1

これは、各コンポーネントのActivateボタンを押したときに入ってくる可能性があります。
ここを、すべて0にするとうまくようです。
どうもこれがずれていると回転した時の軸がずれてしまっているので想定通りの動きになりません。
Unityのドキュメントでは以下のようになってます。

画像2

_人人人人人人_
> わからん <
 ̄Y^Y^Y^Y^Y ̄


とりあえずこうなっていればいいみたいです。

もう一点気をつけなければならないのがPositionConstraintに設定するオブジェクトです。
これの座標を、アバターに対して(0,0,0)にしないといけなさそうです。

画像3

ほかにもやり方あるのかもしれませんが、ひとまずこれでうまくいってます。

・実際の実装

以下のような設定で、ワールド固定が実現できました。

1.アバター座標を(0,0,0)に移動させる
 複数アバターを同じプロジェクトで管理していると、座標をずらしがちですが、それが原因で上記のずれが発生しやすいです。
 まず、アバターを原点に移動させましょう。設定が終わった後は移動してもよさそうです。

2.Constraintの設定
 以下のようなオブジェクト構成にし、Constraintを設定しました。(アバター直下)
 Tumblrは今回ワールド固定したいオブジェクトです。

画像4

・WorldPoint・・・PositionConstraint用のオブジェクトです。
 アバターに対して(0,0,0)に設定します。

画像5

・RotationPoint・・・RotationConstraint用のオブジェクトです。
 FixItemの子に設定します。

画像6

・FixItem・・・今回のキモとなる箇所です。
 ひとまずワールド原点(≒アバターを原点にしているのでアバターに対して(0,0,0)の箇所)に移動してからConstraintを設定します。
 値に関してはいろんな記事にあるので割愛しますが、Sourceをそれぞれ別の物に変更しています。根拠はよくわからないですが、これでうまくいく。

画像7

ちなみに、ここまで設定し終えたらアバターの座標を変更しても問題ないみたいです。
たとえば、アバター座標を(0,0,0)から(1,0,0)に変更すると、FixItemは以下のようになります。

画像8

このように、オブジェクトがワールドの原点にとどまるようにTransformが変更されるはずです。
(きれいに-1じゃないのはアバターの倍率を1.11倍してるからです…)

これで、ワールド固定がうまくいくはずです。

・与太話

 そもそもなんでConstraintでワールド固定ができるの?って話です。
いくら調べてもワールド固定はこうすればいいよ!!!としか言ってなくて原理を説明してないので自己解決に時間がかかってしまったので、自分なりにまとめます。

 Constraintはそもそも、GameObjectを他のGameObjectに紐付けるコンポーネントです。
例えばParentConstraintを設定すれば、まるでInspector上でGameObjectの子に配置したかのように振る舞います。
じゃあどうやってワールド固定ができるの?というと、親との関連付けの強さを変更できるところにキモがあります。

つまり本来であれば子は親に引きづられて以下のように動く所を
 親 子
 ← ←
こう動かせばいいわけですね。
 親 子
 ← ←
   →

?????

表現が難しい…
親に引きずられて動いた子を、引きずられた分逆方向に動かしてやればいいのです。
そうすると、まるでワールドに固定されたように見える、といったことですね。

これがワールド固定の仕組みです。正確には、固定して見えるようにアバターから引き離す。パントマイムみたいなことですね。
そこで、以下のパラメータの話になります。

画像9

ちょっと図解が難しいので想像してもらいたいんですが、ワールドに固定して見えるようにするには、自分が動いた距離の半分逆方向に移動させる必要があります。
その半分に当たるのがWeightの「0.5」、逆方向に当たるのがSourcesの「-1」です。

Rotationのほうの値はちょっと理解がまだできてないです… おそらく理屈は同じなんですが、どうしてWeightとSourcesの値がPositionと異なっているのか… ここって単に乗算じゃないんですかね?知っている人いたら教えてもらいたいです。


・いかがでしたか?

これは案外アバターを毎回原点において編集してる人なら起きづらい問題だと思います。
そのためマジで情報がぜんぜん出てこなくて大変でした…
誰かの役にたったら幸いです。




サポートいただいたら日々のエナドリ代としてありがたく使わせていただきます。 もしよろしかったら〜