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

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

ただいまの
回答率

87.92%

Unity プレハブ(GameObject)の参照を保存(永続化)し、ロードする方法

受付中

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 5,868

score 60

例えばUnityのインスペクターで、Prefabへの参照をドラッグアンドドロップやピッカーでセットすることがありますが
そのインスペクターの欄にセットされているプレハブが、ゲーム中に変更されるものとします。

オブジェクトそのものではなく、そこの欄になんのPrefabがセットされているかという参照を保存したいのですがどうすればいいでしょうか。

また、永続化したその参照データをロードした後、インスタンスを生成する方法はありますでしょうか。

![イメージ説明](853f3055c1683a7047858f73aa3dda10.png)

うまく言葉で説明できませんが、Unity GUI上でやっているように、
インスペクターに参照をセットしたら、スクリプトからFindやResorcesを使わなくてもプロパティでアクセスできてインスタンス生成ができるので、それと同じことをやりたいです。

上記画像のように、インスペクターにセットされているアセットからのプレハブの参照をデータ保存して、復元をするためにはどうすればいいのでしょうか。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+2

ちょっと気になるご質問だったので調べてみましたが、すみませんがこれだという情報は得られませんでした...

エディタ上での制作中にはAssets内の好きなプレハブへの参照をセットすることができますが、ビルドしたプログラムにおいては、使いたい各種プレハブはResources内に仕込んでおいたり、アセットバンドルとして供給したり、あるいはシーン上にあらかじめ全種類こっそり配置しておくなど工夫してやらないと、そもそもプレハブが存在せずアクセスできないかと思います。

Resourcesを使わない...という制限は破ってしまいましたが、下記のようにResourcesへのアクセスをメソッド内に隠してしまい、メソッドを使う側からは直接プレハブ参照を保存・復元しているように見せかけるのはどうでしょうか?

using System.Collections;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public GameObject FruitPrefab;

    // 「SavePrefab」という名前だが、実際には...
    private static void SavePrefab(GameObject prefab)
    {
        // ...与えられたプレハブの名前だけをPlayerPrefsに保存する
        var prefabName = prefab == null ? string.Empty : prefab.name;
        PlayerPrefs.SetString("PrefabName", prefabName);
        PlayerPrefs.Save();
    }

    // 「LoadPrefab」という名前だが、実際には...
    private static GameObject LoadPrefab()
    {
        // PlayerPrefsに保存されている名前と同名のプレハブをResourcesからロードして返す
        var prefabName = PlayerPrefs.GetString("PrefabName");
        return string.IsNullOrEmpty(prefabName) ? null : Resources.Load<GameObject>("Prefabs/" + prefabName);
    }

    private void OnApplicationQuit()
    {
        SavePrefab(this.FruitPrefab);
    }

    private IEnumerator Start()
    {
        this.FruitPrefab = LoadPrefab();
        while (true)
        {
            yield return new WaitWhile(() => this.FruitPrefab == null);

            var fruit = Instantiate(
                this.FruitPrefab,
                this.transform.position,
                Quaternion.Euler(0.0f, 0.0f, Random.value * 360.0f));
            fruit.name = this.FruitPrefab.name;
            Destroy(fruit, 10.0f);
            yield return new WaitForSeconds(3.0f);
        }
    }
}

ご質問者さんのご要望の通りの動作ではなくて申し訳ないですが、使いたいプレハブはAssets/Resources/Prefabsに入れておいて...

Assets

終了時にプレハブ名を保存して、次回起動時にその名前のプレハブをロードしてセットすれば、プレハブへの参照を保存しているかのように見えませんかね...?

プレビュー

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/18 11:47

    サンプルまで作成していただきご丁寧にありがとうございます。
    私も英語で「unity save prefab reference」等で調べてみたりもしたのですがわからず、質問してみました。
    やはりResourcesを使うしか方法はないようですね。

    キャンセル

0

プレハブが完全に動的に生成してるものだとダメですが、パターンが決まっている場合(例えば10種の内1種とか)であれば、そいつを配列に入れておくことで何とかなるかもしれません。

public GameObject[] prefabs;←こいつは永続。Project内のプレハブを複数入れておく。
public int prefabId;←どのプレハブを使うか。ここの値を変えたり保存したりする。
player = prefabs[prefabId];←呼び出し時。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

-1

GameObject型の変数を作ってそこに、インスペクターで設定したGameObjectを代入するだけでいいんではないでしょうか。
何か違う風にとらえていたらすいませんが。GameObject.Findという言葉も出てきていたので、そんな感じなのではないかと考えました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/18 11:52

    そのインスペクターで設定されている参照を保存し、復元したいということでした。
    FindやResourceを使うのはインスペクター上で参照をセットしていない場合ですよね。
    スクリプトで、その作業を経由せず参照自体を得る方法はないのかなと思いまして。

    キャンセル

  • 2018/08/18 13:38

    あなたのしたいことは、Inspectorで指定しないということでしょうか。
    質問なのですが、FindやResourceを使わない理由はなんですか。
    もしかすると役に立てるかもしれません。

    キャンセル

  • 2018/08/18 23:39

    それらの方法は知っています。知ってることはわざわざ質問しません。

    キャンセル

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

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

関連した質問

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