【Unity】Non-Uniform Scalingな親GameObjectを持つと子は苦労するかもしれない
Non-Uniform Scalingとは
X, Y, Z軸のスケール値が同一でないものを指します。
日本語では「不均等スケール」というような表現をします。
反対に、X, Y, Z軸のスケール値が全て同じであるものを、Uniform Scaling/均等スケールと言います。
Non-Uniform Scalingで起こる問題
実験用のシーンを作りました。
クリアキューブの中にUnityちゃんが入っており、親子関係になるようにしています。
初期状態では全てScale1に設定しています。
Non-Uniform Scaling状態生成
キューブのScaleをY軸方向2倍に変更します。
子階層にあるUnityちゃん含め縦長になりました。
これでキューブがNon-Uniform Scalingの状態となりました。
子GameObjectを回転
この状態で、UnityちゃんをZ軸で-90度回転してみます。
…あれ、Unityちゃんなんか太った…?
見比べるために、UnityちゃんのRotationを元に戻し、キューブの方をZ軸で-90度回転してみます。
うん、身長2倍状態。
UnityちゃんのRotationを変更した場合もこの見た目になることを期待していたんだけど…。
Unityちゃんの方のRotationを変更して身長2倍を実現するには
Scaleを以下のように設定すれば同じ見た目になります。
回転角度が90の倍数の場合はこのように帳尻を合わせることができますが、例えば45度回転では変形したUnityちゃんを元に戻すことはできません。[1]
何が起こっているのか
2D画面で改めて状況を確認してみます。
今度はクリアキューブの中に緑色のキューブを入れました。
緑キューブはScale0.5に設定しています。
子GameObject回転
緑キューブをZ軸で90度回転しました。
回転したのに見た目が同じです。
ローカル軸の向きは変わっているので、確かに回転はされています。
次は、緑キューブをZ軸で45度回転しました。
すると、緑キューブが縦長の菱形に変形しました。
緑キューブは回転しても常に縦方向に長いです。
つまり、子GameObjectの向きに関わらず、親GameObjectの軸でスケーリングされてしまっています。
子GameObjectのScale変更はどうなる?
因みに、緑キューブをZ軸で90度回転した状態で、緑キューブのScaleをY軸方向に2倍にすると、横に伸びます。
ということは、子GameObjectのLocalScaleは子GameObjectの軸でスケールされているようです。
サポート外とのこと
UnityのTransformのマニュアルに説明がありました。
(日本語版は少し訳がわかりにくいので英語の方を引用します)
For performance reasons, a child object of a non-uniformly scaled parent will not have its scale automatically updated when it rotates.
子GameObjectが回転しても、スケール方向は回転前の状態の軸(つまり親GameObjectの軸)となるということのようです。
このため、Non-Uniform Scalingな親を持つ子GameObjectは任意の方向に拡大縮小させることができません。
上記のマニュアルによると、その他にもサポート外となるものが複数あります。
また、今回の実験シーンでは確認できませんでしたが、親をNon-Uniform Scalingにしただけでフレームレートがガタ落ちしたという情報も見かけました。
対応策
サポート外なのでどうしようもない、というところではあるのですが、ヒエラルキーの構造を工夫することで避けられる場面も多いと思います。
- スケール変更が不要なモデルを準備する。
- Non-Uniform ScalingにしたGameObjectには子階層を作らない。
- 2Dの場合はX, Y軸のスケール値を変更したらZ軸にも同じ値を入れるようにする。
ということを気にしながらヒエラルキーを構成していくとちょっぴり幸せになれるかもしれません。
-
シェーダーを使えば何とかできるとは思いますが、シェーダーなら元に戻すより回転自体をシェーダーで行った方が良いですよね。 ↩︎
大阪で小規模なITエンジニアリングを行っています。 技術領域: C言語, C#, SQL, Windowsアプリ, Unity etc. YouTube配信始めました! youtube.com/@lilytech-lab
Discussion