質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.62%

Unity  子オブジェクトたち 初期位置へのリセット方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 883

YamaYoshi

score 12

前提・実現したいこと

Unityのゲーム画面にて、複数のオブジェクトをマウスで左ドラッグして動かした後、子オブジェクトを初期位置に戻すリセットボタンを検討しています。

↓マウスドラッグでオブジェクトをずらした状態
イメージ説明

↓特定のボタンを押すと以下のように初期位置に戻る。
![イメージ説明](09ebaa9128b31384a032ff54af1c83d4.png)

試したこと

Void Start()で、FirstPosiという名前で、最初に各子オブジェクトの初期位置を取得し、AllPosiReset()というボタンで、移動させた子オブジェクトFirstPosiで読み取った初期位置に戻そうとしました。
そうすると全部の部品が真ん中に集中して集まってしまいます。
イメージ説明

子オブジェクト全体を一斉に初期位置に戻す方法をご教示いただけると幸いです。

検討したC#コード

public Transform ParentModel;//対象の3Dモデルの親アセンブリの設定
private Vector3 FirstPosi;

void Start()
{ //位置リセット用セット
foreach(Transform child in ParentModel)
{
FirstPosi = child.transform.localPosition; 
}

void AllPosiReset()
{
foreach(Transform child in ParentModel)
{
child.transform.localPosition = FirstPosi;
}
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

実装方法は複数パターンあるかもしれませんが、以下の様な方法はいかがでしょうか。

処理概要
1、子オブジェクトのpositionを格納するためのListを宣言
2、Start()関数内で、子オブジェクトの初期位置をListに格納
3、AllPosiReset()関数実行時に、Listで保持しているpositionを子オブジェクトに再設定

気になる点
foreachで子オブジェクトを取得する際、Start()関数とAllPosiReset()関数で必ず同じ順番で取得できるかは私も分かっておりません。。
もし順番が異なることがある場合、別の子オブジェクトのpositionが適用されてしまうことがあるかもです。
なので、もしそうなった場合はコメント頂ければと思います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ResetSample : MonoBehaviour
{
    public Transform ParentModel;           // 親オブジェクト格納用
    private List<Vector3> originalPosList;  // 元のPosition格納用

    void Start()
    {
        // リスト生成
        originalPosList = new List<Vector3>();

        // 子オブジェクトの初期位置をリストに格納
        foreach (Transform child in ParentModel)
        {
            originalPosList.Add(child.transform.localPosition);
        }
    }


    public void AllPosiReset()
    {
        // 子オブジェクトの位置をリセット
        int i = 0;
        foreach (Transform child in ParentModel)
        {
            child.transform.localPosition = originalPosList[i];
            i++;
        }
    }
}

2020.09.14追記

階層構造になっているGameObjectのリセット方法はいくつかありますが、今回は こちら を利用した方法を共有させて頂きます。

大まかな手順
1、全てのGameObjcectを表示状態にする
2、対象のGameObjectに対し、独自のタグを設定する(インスペクターからあらかじめ独自のタグを追加しておく必要あり)
3、アプリ開始直後のTransformを保持する
4、右クリックメニュー内などのイベント内で(任意のイベントで)、Transformを元に戻す

以下サンプル

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StateChangeSample : MonoBehaviour
{
    // ルートとなるGameObject格納用
    public GameObject rootObj;

    // GameObjectのTransform類格納用(リセット処理にて利用する)
    private Vector3[] defaultPos;
    private Vector3[] defaultScale;
    private Quaternion[] defaultRot;
    private Transform[] models;


    void Start()
    {
        // 全オブジェクトを表示する
        SetActiveRecursively(rootObj, true);

        // GameObject検索用に、GameObjectに独自のタグを設定する
        // ※インスペクターから、タグを追加しておく必要あり
        SetOriginalTag(rootObj, "Parts");

        // 開始時のTransformを保持する
        BackUpTransform();
    }


    // リセットボタン押下時処理
    // ※こちらではボタン押下時のイベントとして設定
    // 質問者さんの方では、右クリックメニューのイベントなどで「ResetTransform」メソッドを呼んでください
    public void ResetBtnClick()
    {
        // Transformをリセットする
        ResetTransform();
    }


    // オブジェクトの表示・非表示切り替え処理
    // ※再帰処理にて、全オブジェクトを対象とする
    public void SetActiveRecursively(GameObject obj, bool state)
    {
        obj.SetActive(state);
        foreach (Transform child in obj.transform)
        {
            SetActiveRecursively(child.gameObject, state);
        }
    }


    // タグの追加処理
    void SetOriginalTag(GameObject obj, string tagStr) {
        obj.tag = tagStr;
        foreach (Transform child in obj.transform)
        {
            SetOriginalTag(child.gameObject, tagStr);
        }
    }


    // バックアップ処理
    // ※開始直後のTransformを保持する
    void BackUpTransform()
    {
        //Find GameObjects with Model tag
        GameObject[] tempModels = GameObject.FindGameObjectsWithTag("Parts");

        //Create pos, scale and rot, Transform array size based on sixe of Objects found
        defaultPos = new Vector3[tempModels.Length];
        defaultScale = new Vector3[tempModels.Length];
        defaultRot = new Quaternion[tempModels.Length];

        models = new Transform[tempModels.Length];

        //Get original the pos, scale and rot of each Object on the transform
        for (int i = 0; i < tempModels.Length; i++)
        {
            models[i] = tempModels[i].GetComponent<Transform>();

            defaultPos[i] = models[i].position;
            defaultScale[i] = models[i].localScale;
            defaultRot[i] = models[i].rotation;
        }
    }


    // リセット処理
    // ※Transformを、開始直後の状態にリセットする
    void ResetTransform()
    {
        //Restore the all the original pos, scale and rot  of each GameOBject
        for (int i = 0; i < models.Length; i++)
        {
            models[i].position = defaultPos[i];
            models[i].localScale = defaultScale[i];
            models[i].rotation = defaultRot[i];
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/14 01:36

    回答追記いたしました。
    「サンプルを読んでもよく分からない」・「使い方が分からない」などあれば、新しく質問を投稿して頂いた方がより早く回答が得られるかと思います。もしくは、別の方法の回答も得られる可能性があります。
    丁寧な回答でなく申し訳ありませんが、よろしくお願いいたします。

    キャンセル

  • 2020/09/14 09:34

    ありがとうございます。無事問題なく動かすことができました。
    またご指摘いただいた通り、今後はこのようなことがありましたら新しく質問を投げかけます。
    色々とお手数をおかけして申し訳ございませんでした。

    キャンセル

  • 2020/09/14 10:27

    早速のご確認ありがとうございました。無事に動いた様で良かったです。
    また質問をお見かけした際には、分かる範囲で回答させて頂きます。今後ともよろしくお願いします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る