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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

9725閲覧

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

DY2peace

総合スコア20

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/05/25 09:51

編集2020/05/25 09:59

前提・実現したいこと

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

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

↓特定のボタンを押すと以下のように初期位置に戻る。
イメージ説明

試したこと

 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;
}
}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

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

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

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

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class ResetSample : MonoBehaviour 6{ 7 public Transform ParentModel; // 親オブジェクト格納用 8 private List<Vector3> originalPosList; // 元のPosition格納用 9 10 void Start() 11 { 12 // リスト生成 13 originalPosList = new List<Vector3>(); 14 15 // 子オブジェクトの初期位置をリストに格納 16 foreach (Transform child in ParentModel) 17 { 18 originalPosList.Add(child.transform.localPosition); 19 } 20 } 21 22 23 public void AllPosiReset() 24 { 25 // 子オブジェクトの位置をリセット 26 int i = 0; 27 foreach (Transform child in ParentModel) 28 { 29 child.transform.localPosition = originalPosList[i]; 30 i++; 31 } 32 } 33}

2020.09.14追記

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

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

以下サンプル

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class StateChangeSample : MonoBehaviour 6{ 7 // ルートとなるGameObject格納用 8 public GameObject rootObj; 9 10 // GameObjectのTransform類格納用(リセット処理にて利用する) 11 private Vector3[] defaultPos; 12 private Vector3[] defaultScale; 13 private Quaternion[] defaultRot; 14 private Transform[] models; 15 16 17 void Start() 18 { 19 // 全オブジェクトを表示する 20 SetActiveRecursively(rootObj, true); 21 22 // GameObject検索用に、GameObjectに独自のタグを設定する 23 // ※インスペクターから、タグを追加しておく必要あり 24 SetOriginalTag(rootObj, "Parts"); 25 26 // 開始時のTransformを保持する 27 BackUpTransform(); 28 } 29 30 31 // リセットボタン押下時処理 32 // ※こちらではボタン押下時のイベントとして設定 33 // 質問者さんの方では、右クリックメニューのイベントなどで「ResetTransform」メソッドを呼んでください 34 public void ResetBtnClick() 35 { 36 // Transformをリセットする 37 ResetTransform(); 38 } 39 40 41 // オブジェクトの表示・非表示切り替え処理 42 // ※再帰処理にて、全オブジェクトを対象とする 43 public void SetActiveRecursively(GameObject obj, bool state) 44 { 45 obj.SetActive(state); 46 foreach (Transform child in obj.transform) 47 { 48 SetActiveRecursively(child.gameObject, state); 49 } 50 } 51 52 53 // タグの追加処理 54 void SetOriginalTag(GameObject obj, string tagStr) { 55 obj.tag = tagStr; 56 foreach (Transform child in obj.transform) 57 { 58 SetOriginalTag(child.gameObject, tagStr); 59 } 60 } 61 62 63 // バックアップ処理 64 // ※開始直後のTransformを保持する 65 void BackUpTransform() 66 { 67 //Find GameObjects with Model tag 68 GameObject[] tempModels = GameObject.FindGameObjectsWithTag("Parts"); 69 70 //Create pos, scale and rot, Transform array size based on sixe of Objects found 71 defaultPos = new Vector3[tempModels.Length]; 72 defaultScale = new Vector3[tempModels.Length]; 73 defaultRot = new Quaternion[tempModels.Length]; 74 75 models = new Transform[tempModels.Length]; 76 77 //Get original the pos, scale and rot of each Object on the transform 78 for (int i = 0; i < tempModels.Length; i++) 79 { 80 models[i] = tempModels[i].GetComponent<Transform>(); 81 82 defaultPos[i] = models[i].position; 83 defaultScale[i] = models[i].localScale; 84 defaultRot[i] = models[i].rotation; 85 } 86 } 87 88 89 // リセット処理 90 // ※Transformを、開始直後の状態にリセットする 91 void ResetTransform() 92 { 93 //Restore the all the original pos, scale and rot of each GameOBject 94 for (int i = 0; i < models.Length; i++) 95 { 96 models[i].position = defaultPos[i]; 97 models[i].localScale = defaultScale[i]; 98 models[i].rotation = defaultRot[i]; 99 } 100 } 101} 102

投稿2020/05/25 13:18

編集2020/09/13 16:37
tsuki01

総合スコア1751

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DY2peace

2020/05/25 13:48

ご丁寧な解説ありがとうございます。先ほど確認して問題なくリセットすることができました。大変助かりました。ありがとうございます。
DY2peace

2020/09/13 14:56

たびたび申し訳ございません。以前質問させていただいたこちらの全パーツ位置リセットですが、子要素だけでなく、孫、ひ孫とぶら下がっている部品を全部、元の位置に戻したいと考えております。  もし何かいい方法をご存じでしたらご教示いただけると幸いです。
tsuki01

2020/09/13 16:36

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

2020/09/14 00:34

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

2020/09/14 01:27

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問