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

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

ただいまの
回答率

90.32%

  • C#

    7713questions

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

  • Unity

    4428questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

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

解決済

回答 1

投稿 編集

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

kaz2zak

score 23

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

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

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

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

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

using System.Collections.Generic;

public class Switching : MonoBehaviour
{
public void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            RaycastHit hit = new RaycastHit();

            if (Physics.Raycast(ray, out hit, distance))
            {
                 Destroy(hit.collider.gameObject);
            }
        }
    }

 void ReDisplay()
    {
        List<GameObject> hideGameObject = new List<GameObject>();

        hideGameObject.Add(GameObject.Find("hit.collider.gameObject"));

        if (Input.GetMouseButtonDown(1))
        {
            hideGameObject[-1].SetActive(true);

            hideGameObject.Remove(hideGameObject.count - 1);  //countの定義が含まれていないとエラーメッセージが出る

        }


    }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+2

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

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

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


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

public class Switching : MonoBehaviour
{
    //各メソッドで使うのでクラス変数にする
    private List<GameObject> hideGameObject;

    void Start ()
    {
        //初期化は開始直後にやっておく(初期化しておかないとエラーになる)
        hideGameObject = new List<GameObject> ();
    }

    public void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            RaycastHit hit = new RaycastHit();

            if (Physics.Raycast(ray, out hit, distance))
            {
                //Destroy(hit.collider.gameObject);
                //↓差し替え
                hit.collider.gameObject.SetActive(false);

                //「消された時」に保存する
                hideGameObject.Add (hit.collider.gameObject);

                //ちなみに「GameObject.Find」は名前で検索なので
                //GameObject.Find ("hit.collider.gameObject")は
                //「hit.collider.gameObjectという名前のオブジェクトを探す」ことになってしまう。
                //そうではない筈なのでここも変える。
            }
        }
    }

    void ReDisplay()
    {
        if (Input.GetMouseButtonDown (1)) {
            //再表示するのは「一番後ろ」のオブジェクト。
            //[-1]だと「-1番目のオブジェクト」になってしまうのでこれもエラーが出る。
            //考え方は配列と一緒なので「配列の数-1」が最後尾。
            hideGameObject [hideGameObject.Count-1].SetActive (true);

            //「countの定義が含まれていない」→「Count」が正しい(頭文字が大文字)
            //予測変換を頼ったりListクラスのリファレンスを見ると分かる。
            hideGameObject.Remove (hideGameObject.Count - 1);
        }
    }
}    //ここ ] になっていたのでコピペミスかもしれませんが一応直してあります

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/25 22:38

    sakura 様
    回答ありがとうございます。
    Destoroyだったので嫌な予感はしていたのですがやはり、完全消去だったんですね。

    書き方に慣れているgameObject.SetActive(false)で非表示にすることができました。
    ありがとうございます。
    あとは、再表示ですが、これは難しそうですね。。

    配列やリストを使って非表示となったオブジェクトを一度格納して、for文を用いて、指定したキーが押された分だけ、gemeObject.SetActive(true)で戻すという流れでしょうか。
    初心者であり、配列を使って書いたことがなく、初歩的な質問となり申し訳ありません。

    キャンセル

  • 2018/04/26 15:50

    「押した順番の逆順」であればループは必要無いです。

    配列の場合:「現在ID」を作り、`配列[現在ID]`で指定のオブジェクトが取れる。非表示ボタンが押されたら現在IDを+1、戻るボタンが押されたら-1する。

    Listの場合:非表示ボタンが押されたらAdd、戻るボタンが押されたら「一番後ろ」を参照してからRemove。

    配列は最初に大きさを決める必要があるのでListの方が楽かと。
    開発においてかなり重要な要素なので色々調べつつやってみるといいと思います。

    キャンセル

  • 2018/04/26 18:58

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

    キャンセル

  • 2018/04/26 19:06

    sakura様

    ループ処理は必要ないんですね!
    指摘して頂いたように、いくつ非表示にするかは操作する人次第にしたいので、動的なListで処理をしようと思います。
    Listを使っての処理を色々と見ているのですが、初心者には複雑で頭が痛くなります。。

    右クリックをすることで再表示となるようスクリプトを書いてみたのですが、全く再表示されません。
    質問時に載せましたスクリプトを更新しましたので、見て頂ければ幸いです。

    Addの書き方が悪いため、Listに非表示となったオブジェクトが格納されていないのではないかと思うのですが…。
    また、Removeですが、エラーが出てしまいます。再表示に使用した1番最後のリストの指定の仕方はどうしたら良いでしょうか。

    重ね重ねの質問となり申し訳ありません。
    お力をお借りできませんでしょうか。何卒、よろしくお願い致します。

    キャンセル

  • 2018/04/26 19:38

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

    キャンセル

  • 2018/04/26 20:53

    kaz2zakさん
    とりあえず基本ということで、Listを使うやり方でソースコード直してみました。

    negitamaさん
    Stack知りませんでした。便利ですねー、次からは私もこっちでやります!

    キャンセル

  • 2018/04/26 23:13

    わざわざスクリプトを修正して頂き心から感謝致します。
    コメントもあり、ひとつひとつの意味が良く分かりました。

    おかげさまで、再表示することができました。
    しかし、一点だけ問題がありまして…
    Remove (hideGameObject.Count - 1)
    が”引数 1:は’int’から'Unity.Engine.GameObject'へ変換することはできません。”というエラーが出てしまいます。
    Removeができないためか、非表示にした最後のオブジェクトのみしか再表示できませんでした。

    ゴール目前なので、Stack含めあと少し頑張ってみます!!

    キャンセル

  • 2018/04/27 08:15

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

    sakura様、negitama様、ありがとうございました!

    キャンセル

  • 2018/04/27 14:36

    すみません、IDで指定する場合はRemoveではなくRemoveAtでした。
    ここを差し替えれば元コードでも動くかと思います。

    予測変換やリファレンス見ると他にも近いコードが出るので、そちらを見るようにすると質問せずに進められると思います。今後はそちらも利用してみてください。

    キャンセル

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

  • C#

    7713questions

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

  • Unity

    4428questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。