Categories: Unity

【Unity】ゲームオブジェクトを子要素にしたら位置、回転、スケールが変わってしまう…

この記事では、ゲームオブジェクトを子要素にしても位置や回転、スケールが変わらないようにする方法を解説します。

この前、Instantiate()で生成したゲームオブジェクトをあるゲームオブジェクトの子要素にしたら位置や回転、スケールが勝手に変更され、想定通りの配置にならなかった。

その時のコードは以下のような感じです。

[SerializeField]
private GameObject prefab;

private void Awake()
{
    Transform child = Instantiate(prefab).transform;
    // 親を変更
    child.parent = gameObject.transform;
}

それでは、なぜ想定通りの配置にならなかったのか原因と解決策を見ていきましょう!

配置がずれる原因

先程のコードでは、子要素のparentに直で親を代入していました。

child.parent = gameObject.transform;

parentに直接親を代入するとワールド空間を保ったまま子要素にしてしまいます。

つまりは、子要素にするゲームオブジェクトに設定されている位置や回転、スケールになるように親のトランスフォームから相対的に計算された値が渡されるようになっています。

そのような理由から想定外の配置になってしまうことがあります。

解決策

ワールド空間ではなくローカル空間を基準に子要素にすることでトランスフォームを変更することなく親を設定することができます。

ローカル空間を基準に子要素にするには、Transform.SetParent()を使います。

public void SetParent (Transform p);
public void SetParent (Transform parent, bool worldPositionStays);

このメソッドは、第一引数で指定したトランスフォームを親として設定できます。また、第二引数にtrueを指定することでワールド空間を保ったまま子要素にすることができます。

ローカル空間を基準に子要素にしたい場合は、第二引数に false を指定します。ちなみに、第二引数が省略された場合は、ワールド空間を保ちます。

ということで最初のコードは、以下のように書き直すことで位置やスケールを変更されずに子要素にすることができます。

[SerializeField]
private GameObject prefab;

private void Awake()
{
    Transform child = Instantiate(prefab).transform;
    // 親を変更
    child.SetParent(gameObject.transform, false);
}

簡単ですね!

ゆうまる

独学でプログラミングを勉強しているおじさん。いろんな言語を勉強したが浅く広くなためあまり仕事につながらない。また忘れっぽいため自分のブログを備忘録としても使っている。産まれてこのかたずっとネコを飼ってる生粋のネコ派。最近お腹が出てきて筋トレに奮闘中!

Recent Posts

【Dart】コンストラクタのデフォルト引数について

Dartのコンストラクタのデフォルト引数…

2週間 ago

【Unity】有料アセットを無料で手に入れる方法

この記事では、Unityの有料アセットを…

4か月 ago

【Python】任意の秒数だけ処理を一時停止する方法【sleep()関数】

この記事では、Pythonで任意の秒数だ…

1年 ago

【Python】Wordの文書の新規作成と読み書き

この記事では、Pythonを使ってWor…

1年 ago

【Python】メタクラスって結局なんなの?

この記事では、Pythonのメタクラスに…

1年 ago