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

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

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

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

Unity

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

Q&A

解決済

1回答

741閲覧

rayの衝突により非表示にしたオブジェクトを再表示したい

kaz2zak

総合スコア36

C#

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

Unity

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

0グッド

0クリップ

投稿2018/04/25 07:35

編集2018/04/26 09:53

Raycastを用いて、rayと衝突したオブジェクトを非表示にするために
Destroy(hit.collider.gameObject);
を用いています。

上記のDestroyで非表示にしたオブジェクトを、指定したキーボタンをクリックすることで、直近に非表示にしたオブジェクトを再表示できるようにしたいのですが、見当がつきません。

例えば、複数オブジェクトがありA→B→Cの順で非表示にした場合に、戻るの入力を受けた分だけ、C→B→Aの順で再表示をしたいです。
もしくは非表示にしたオブジェクトを選択し、再表示にできるような方法がありますでしょうか。

オブジェクトそれぞれに対応するキーを振り当て、奇数回は非表示、偶数回は再表示としSetActiveを用いて表示の切り替えはできるのですが、VRでの実装をしたいのでrayでどうにか解決したいです。

以下が該当のスクリプトになります。
どのように加筆すればよいかご教示お願いいたします。
※確認をしやすいように、マウスの記述となっております。

C#

1 2using System.Collections.Generic; 3 4public class Switching : MonoBehaviour 5{ 6public void Update() 7 { 8 if (Input.GetMouseButtonDown(0)) 9 { 10 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 11 12 RaycastHit hit = new RaycastHit(); 13 14 if (Physics.Raycast(ray, out hit, distance)) 15 { 16 Destroy(hit.collider.gameObject); 17 } 18 } 19 } 20 21 void ReDisplay() 22 { 23 List<GameObject> hideGameObject = new List<GameObject>(); 24 25 hideGameObject.Add(GameObject.Find("hit.collider.gameObject")); 26 27 if (Input.GetMouseButtonDown(1)) 28 { 29 hideGameObject[-1].SetActive(true); 30 31 hideGameObject.Remove(hideGameObject.count - 1); //countの定義が含まれていないとエラーメッセージが出る 32 33 } 34 35 36 } 37 38]

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

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

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

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

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

guest

回答1

0

ベストアンサー

Destroyを使った場合、完全に消去されているのでInstantinateで再生成する他ありません。

非表示にするだけならgameObject.SetActive(false)または
描画系のコンポーネントをオフにする(例えばGetComponent<Renderer>().enabled = false;)といいかと思います。

後は配列やリストを使って「どの順番でオブジェクトが選択されたか」を記憶しておけばよいかと。


コメントを受けてソースコードを修正しました。
ちゃんと動作確認してませんのでエラー起こったら適宜修正お願いします。

C#

1public class Switching : MonoBehaviour 2{ 3 //各メソッドで使うのでクラス変数にする 4 private List<GameObject> hideGameObject; 5 6 void Start () 7 { 8 //初期化は開始直後にやっておく(初期化しておかないとエラーになる) 9 hideGameObject = new List<GameObject> (); 10 } 11 12 public void Update() 13 { 14 if (Input.GetMouseButtonDown(0)) 15 { 16 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 17 18 RaycastHit hit = new RaycastHit(); 19 20 if (Physics.Raycast(ray, out hit, distance)) 21 { 22 //Destroy(hit.collider.gameObject); 23 //↓差し替え 24 hit.collider.gameObject.SetActive(false); 25 26 //「消された時」に保存する 27 hideGameObject.Add (hit.collider.gameObject); 28 29 //ちなみに「GameObject.Find」は名前で検索なので 30 //GameObject.Find ("hit.collider.gameObject")は 31 //「hit.collider.gameObjectという名前のオブジェクトを探す」ことになってしまう。 32 //そうではない筈なのでここも変える。 33 } 34 } 35 } 36 37 void ReDisplay() 38 { 39 if (Input.GetMouseButtonDown (1)) { 40 //再表示するのは「一番後ろ」のオブジェクト。 41 //[-1]だと「-1番目のオブジェクト」になってしまうのでこれもエラーが出る。 42 //考え方は配列と一緒なので「配列の数-1」が最後尾。 43 hideGameObject [hideGameObject.Count-1].SetActive (true); 44 45 //「countの定義が含まれていない」→「Count」が正しい(頭文字が大文字) 46 //予測変換を頼ったりListクラスのリファレンスを見ると分かる。 47 hideGameObject.Remove (hideGameObject.Count - 1); 48 } 49 } 50} //ここ ] になっていたのでコピペミスかもしれませんが一応直してあります

投稿2018/04/25 08:53

編集2018/04/26 11:51
sakura_hana

総合スコア11427

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

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

kaz2zak

2018/04/25 13:38

sakura 様 回答ありがとうございます。 Destoroyだったので嫌な予感はしていたのですがやはり、完全消去だったんですね。 書き方に慣れているgameObject.SetActive(false)で非表示にすることができました。 ありがとうございます。 あとは、再表示ですが、これは難しそうですね。。 配列やリストを使って非表示となったオブジェクトを一度格納して、for文を用いて、指定したキーが押された分だけ、gemeObject.SetActive(true)で戻すという流れでしょうか。 初心者であり、配列を使って書いたことがなく、初歩的な質問となり申し訳ありません。
sakura_hana

2018/04/26 06:50

「押した順番の逆順」であればループは必要無いです。 配列の場合:「現在ID」を作り、`配列[現在ID]`で指定のオブジェクトが取れる。非表示ボタンが押されたら現在IDを+1、戻るボタンが押されたら-1する。 Listの場合:非表示ボタンが押されたらAdd、戻るボタンが押されたら「一番後ろ」を参照してからRemove。 配列は最初に大きさを決める必要があるのでListの方が楽かと。 開発においてかなり重要な要素なので色々調べつつやってみるといいと思います。
negitama

2018/04/26 09:58

質問者さんへ ABCの順に格納して、CBAの順に取り出すなら、Stackを使うのもいいかもしれませんねー。 いろいろ調べて試してみることをおすすめします。 http://indie-du.com/entry/2017/01/18/200000
kaz2zak

2018/04/26 10:06

sakura様 ループ処理は必要ないんですね! 指摘して頂いたように、いくつ非表示にするかは操作する人次第にしたいので、動的なListで処理をしようと思います。 Listを使っての処理を色々と見ているのですが、初心者には複雑で頭が痛くなります。。 右クリックをすることで再表示となるようスクリプトを書いてみたのですが、全く再表示されません。 質問時に載せましたスクリプトを更新しましたので、見て頂ければ幸いです。 Addの書き方が悪いため、Listに非表示となったオブジェクトが格納されていないのではないかと思うのですが…。 また、Removeですが、エラーが出てしまいます。再表示に使用した1番最後のリストの指定の仕方はどうしたら良いでしょうか。 重ね重ねの質問となり申し訳ありません。 お力をお借りできませんでしょうか。何卒、よろしくお願い致します。
kaz2zak

2018/04/26 10:38

negitama 様 なんて便利な、そしてまさに今したい動作のできる、Stackというのがあるんですか。 ご親切にURLまでありがとうございます。 色々と調べてみます!
sakura_hana

2018/04/26 11:53

kaz2zakさん とりあえず基本ということで、Listを使うやり方でソースコード直してみました。 negitamaさん Stack知りませんでした。便利ですねー、次からは私もこっちでやります!
kaz2zak

2018/04/26 14:13

わざわざスクリプトを修正して頂き心から感謝致します。 コメントもあり、ひとつひとつの意味が良く分かりました。 おかげさまで、再表示することができました。 しかし、一点だけ問題がありまして… Remove (hideGameObject.Count - 1) が”引数 1:は’int’から'Unity.Engine.GameObject'へ変換することはできません。”というエラーが出てしまいます。 Removeができないためか、非表示にした最後のオブジェクトのみしか再表示できませんでした。 ゴール目前なので、Stack含めあと少し頑張ってみます!!
kaz2zak

2018/04/26 23:15

おはようございます。 Removeする際に最後のリストの設定の仕方が分からず、Listを用いての解決はできませんでしたが、Stackを用いて解決することができました。 StackはPopで取り出すと、取り出したときに格納していた箱も一緒に消えてくれるので、便利ですね! sakura様、negitama様、ありがとうございました!
sakura_hana

2018/04/27 05:36

すみません、IDで指定する場合はRemoveではなくRemoveAtでした。 ここを差し替えれば元コードでも動くかと思います。 予測変換やリファレンス見ると他にも近いコードが出るので、そちらを見るようにすると質問せずに進められると思います。今後はそちらも利用してみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問