Unityで親子オブジェクトの切り替え変更スクリプトメモ。ゲーム実行中に親を切り替えボーンも指定できる

unity 親子 切り替え オブジェクト 変更 移動 ボーン Unity
※記事内に広告が含まれています。

バーチャル3Dクリエイター神部まゆみです(*^-^*)

この記事はUnityで親子オブジェクトの切り替え変更をするスクリプトについての記事です。

動作確認した最新バージョンは Unity 6000.3.1 です。

●PRスペース●
■PR■

現在人気商品が最大90%オフで買えるAmazonクリスマスタイムセール をやってるみたいです(2025/12/25まで)。

Amazonクリスマスタイムセール 最大90%オフ

モバイルバッテリーなど色々な商品が安くなっているので、欲しい商品はこの機会に買っておくと良いかも。

 

〇まゆみマート|BOOTH

BOOTHでVRoidテクスチャやVRChat向けオブジェクトなどを販売しています。いいねしてくれると励みになります(*^-^*)

やりたいこと:ゲーム実行中に親を切り替えたい

これをやると、アニメーションイベントでスクリプトを呼んで物を渡す…とかができるかな。

親を切り替えないと追従してくれないので不都合が出てくる。

親子関係なしにしたりもできるようなので、服を脱がせるモーションから床に置いたりとかもできるっぽい。

まぁ別オブジェクトにしないといけないから大変だけども(^_^;)

ChatGPTパイセンに聞いてみる

とりあえず彼に聞いてみます。

unity 親子 切り替え オブジェクト 変更 移動 ボーン
神部まゆみ
神部まゆみ

Unityで質問です。スクリプトで子オブジェクトの親を切り替えるってできるんでしょうか?

A親オブジェクト
 ーC子

B親オブジェクト
 ーC子

という風にゲーム実行中に切り替えたいんですが可能なのでしょうか?
ボーンの子にしたい場合のやり方もお願いします。

ChatGPT
ChatGPT

できます、全然可能です 👍
UnityではTransform の親を実行中に変更できます。
一番シンプルなのは SetParent を使う方法です。

基本的なやり方

// C(子オブジェクト)のTransform
Transform child = C.transform;

// B(新しい親オブジェクト)のTransform
Transform newParent = B.transform;

// 親を切り替える
child.SetParent(newParent);

これだけで

A
 └ C

から

B
 └ C

に実行中で切り替わります。


位置をどうするか(重要ポイント)

SetParent には第2引数があって、位置を維持するかどうかを指定できます。

child.SetParent(newParent, true);  // ワールド座標を維持(デフォルト)
child.SetParent(newParent, false); // ローカル座標を維持

よくある使い分け

  • 今の見た目の位置を変えたくない
     → true
  • 親に対する相対位置を使いたい(武器を手に持たせる等)
     → false

親を外したい場合(おまけ)

一旦どの親にも属させたくない場合は:

child.SetParent(null);

特定の子(Headボーン)を親にする場合

// HeadボーンのTransformを取得
Transform head = character.transform.Find("Armature/Hips/Spine/Chest/Neck/Head");

// C を Head の子にする
C.transform.SetParent(head, false);

これでヒエラルキー的には:

Character
 └ Armature
    └ ...
       └ Head
          └ C

になります。

false にしているのは
「Head基準のローカル位置を使いたい(装備させたい)」場合です。


ヒエラルキー内の「順番」を指定したい場合

Unityでは親を指定するだけでは順番は最後になりますが、
Sibling Index を使えば順番も制御できます。

C.transform.SetParent(head, false);

// Head の子の何番目にするか(0始まり)
C.transform.SetSiblingIndex(0);

よく使うのは:

C.transform.SetAsFirstSibling(); // 一番上
C.transform.SetAsLastSibling();  // 一番下

ボーン名が分からない/安全に取りたい場合

Find() は便利ですが、構造変更に弱いです。
実務では 参照をInspectorで持たせる のが安定します。

[SerializeField] Transform headBone;

public void AttachToHead(GameObject obj)
{
    obj.transform.SetParent(headBone, false);
}

これなら

  • モデル差し替え
  • ボーン階層変更
    にも強くなります。

Animatorがある場合の注意(超重要)

SkinnedMesh + Animator があるキャラの場合:

  • 必ずボーン(Transform)に直接ぶら下げる
  • キャラ本体(ルート)に付けるとズレやすい

武器・帽子・アクセサリ系は
👉 Head / Hand_R / Hand_L が鉄板です。

なんか普通にできるっぽいですね…。

以前やろうとしたことあったけど、ChatGPTの性能が低くて上手く動作しなかったんだったかな?(^_^;)

親を切り替えるスクリプトを実際に動かしてみる

このスクリプトで動かせるみたいです。

using UnityEngine;

public class ChangeObjectParent : MonoBehaviour
{
    [Header("親を切り替えたいオブジェクト(C)")]
    public Transform targetObject;

    [Header("切り替え先の親ボーン")]
    public Transform targetParent;

    [Header("ローカル座標を維持するか")]
    public bool keepLocalTransform = false;

    // 呼ばれた瞬間に親を切り替える
    public void ChangeParent()
    {
        if (targetObject == null)
        {
            Debug.LogWarning("切り替え対象のオブジェクトが指定されていません");
            return;
        }

        if (targetParent == null)
        {
            Debug.LogWarning("切り替え先の親ボーンが指定されていません");
            return;
        }

        targetObject.SetParent(targetParent, !keepLocalTransform);
    }

    // テスト用:再生と同時に切り替えたい場合
    /*void Start()
    {
        ChangeParent();
    }*/
}

事前準備:切り替えたい子オブジェクトを仕込んで、モデルを二体配置して動かしておく

スフィアをHeadの子に仕込んで配置しておきます。

unity 親子 切り替え オブジェクト 変更 移動 ボーン

もう一体モデルを配置して、再生すれば動くようにしておく。

ちょうどすれ違うあたりで切り替わると面白いかな…。ここにアニメーションイベントを仕込んでスクリプト発動させます。

VeryAnimationのSyncronize機能を使うと、二人以上のアニメーション同期プレビューがやりやすいです。

アニメーションイベントについてはこちら。

スクリプトの設定をする

アニメーションイベントを仕込んだモデルにスクリプトをアタッチ、ターゲットオブジェクトと移動先ボーンを指定します。

ローカル座標を保持にチェックすると良い感じに頭の上のスフィアが移りますね。

アニメーションイベントをインスペクターで編集して、ChangeParentメソッドを呼ぶ。

これで動いた!

めっちゃ良い感じで切り替えられました!Σ(゚Д゚)

これ結構色々使えそう。

確かMMDでも親を切り替えたり親なしにして、服やニーソックスを脱がせる動画を作っていた人がいたな…(;゚д゚)ゴクリ…

注意点:スクリプトならプレハブインスタンスの子でも移動できるっぽい

プレハブの子を移動させようとすると警告が出るんだけど、スクリプトだと大丈夫っぽい。

この警告を出さないようにするにはプレハブを展開(unpack)する必要があるんだけど、スクリプトならゲーム中の一時的な動作だから大丈夫みたい。

unity 親子 切り替え オブジェクト 変更 移動 ボーン

unity 親子 切り替え オブジェクト 変更 移動 ボーン
神部まゆみ
神部まゆみ

これってヒエラルキー上で親子関係をいじる場合、「プレハブインスタンスの子を移動することはできません」と言われることがあるのですが、プレハブを展開しておけば大丈夫なのでしょうか?親子関係をスクリプトでいじる場合でも展開しておかないといけないのでしょうか?

ChatGPT
ChatGPT

いいところに気づきましたね。そこ、Unityが一番ややこしい罠ポイントです…🙂
結論から言うと 「実行時にスクリプトで親子関係を変える場合、プレハブを展開しておく必要はありません」。
ただし、エディタ上でヒエラルキーを直接いじる場合とは挙動が違います。

なぜ「プレハブインスタンスの子を移動できません」と言われるのか

これは エディタ操作限定の制約です。

  • プレハブ インスタンスの中身は
    • 構造(親子関係)を勝手に変えると
    • 「元プレハブとズレる」ため
  • Unityがそれを防ぐためにロックしています

なのでヒエラルキーで
「この子を別の親にドラッグ」
みたいなことをするとエラーが出ます。


プレハブを「展開」するとどうなる?

「Prefab を展開(Unpack)」すると:

  • そのオブジェクトは ただの通常GameObject
  • プレハブとの関連が完全に切れる
  • ヒエラルキー上で自由に親子関係を変更できる

👉 エディタで手動編集したいなら Unpack が必要


じゃあスクリプトの場合は?

ここが重要です👇

✔ スクリプトでの SetParent() は制限されません

child.transform.SetParent(newParent);

これは **実行中(Play中)**なら:

  • プレハブインスタンスでも
  • Unpack してなくても
  • 問題なく動きます

理由は:

  • Play中の変更はシーンに保存されない
  • プレハブの構造を壊さない扱いになる

つまり
実行時の一時的な親子切り替えは完全にOK です。


まとめ(ここ超大事)

操作Unpack必要?
ヒエラルキーで手動で親子を変更✅ 必要
プレハブ編集モードで構造変更❌(そもそもPrefab側を編集)
実行中にスクリプトで SetParent❌ 不要

実務での考え方(おすすめ)

  • 構造が固定 → プレハブで管理
  • ゲーム中に持ち替える/移動する
     → スクリプトで SetParent(Unpack不要)
  • 恒久的に構造を変えたい
     → Prefab編集 or Unpackして通常オブジェクト化

おわりに

手軽に切り替えられて良かった。

まぁエロい用途にしか思いつかないけどもw

また何かあれば追記します(*^_^*)

タイトルとURLをコピーしました