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

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

ただいまの
回答率

90.61%

  • C#

    6849questions

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

  • Unity

    3804questions

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

作成したインスタンスの個別認識について

解決済

回答 1

投稿

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

BitCoin

score 45

実現したいこと

作成したインプットフィールドに値を入力する際、個別に認識し
それをセーブし次回アプリを起動した際に個別に読み込む。

問題点

Instantiateでインスタンスを作成しているため、個別に値を変数に代入する方法がわからず全ての作成したインスタンスにセーブした値が適応されてしまう。

inputinstance[i].onEndEdit.AddListener(OnSubmit);で 
入力された値(value)をPlayerPrefs.SetString(key,value);でkeyに保存しているがこれを個別の配列に対応させ、inputfuieldclone.GetComponentInChildren<Text> ().text = PlayerPrefs.GetString (key);
をする際それぞれのインプットフィールドインスタンスにセーブしたい。
よろしくお願いします。

イメージ説明

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class sample2 : MonoBehaviour {

    [SerializeField]
    private GameObject inputfuield;  
    //インスタンス表示数
    const int inputfuield_count = 6;

    public InputField[] inputinstance = new InputField[10];

    [SerializeField]
    public RectTransform parent;

    public string key;

    void Start ()
    {


        for (int i = 0; i < inputfuield_count; i++)
        {
            int no = i;
            //インプットフィールド生成
            GameObject inputfuieldclone = (GameObject)Instantiate(inputfuield);
            //できたインスタンスをContentの子に設定
            inputfuieldclone.transform.SetParent(parent, false);

            inputinstance[i] =  inputfuieldclone.GetComponent<InputField> ();

            inputinstance[i].onEndEdit.AddListener(OnSubmit);

            inputfuieldclone.GetComponentInChildren<Text> ().text = PlayerPrefs.GetString (key);
        }

    }


    public void OnSubmit(string value)
    {
        PlayerPrefs.SetString(key,value);

        Debug.Log("Submit value is " + value);

    }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

保存時のキーが1つであるなら、当然1つのデータしかセーブされません。
逆に言えばキーを増やせばその分個別に保存されることになります。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class sample2 : MonoBehaviour {

    [SerializeField]
    private GameObject inputfuield;  
    //インスタンス表示数
    const int inputfuield_count = 6;

    public InputField[] inputinstance = new InputField[10];

    [SerializeField]
    public RectTransform parent;

    public string key;

    void Start ()
    {


        for (int i = 0; i < inputfuield_count; i++)
        {
            int no = i;
            //インプットフィールド生成
            GameObject inputfuieldclone = (GameObject)Instantiate(inputfuield);
            //できたインスタンスをContentの子に設定
            inputfuieldclone.transform.SetParent(parent, false);

            //※代入する
            InputField field = inputfuieldclone.GetComponent<InputField> ();
            inputinstance[i] = field;

            //※InputFieldを引数に持つメソッドを登録する(inputinstance[i]を引数にすると何故かエラーになる)
            inputinstance[i].onEndEdit.AddListener(delegate{OnSubmit(field);});

            //※キー名を変更
            inputfuieldclone.GetComponentInChildren<Text> ().text = PlayerPrefs.GetString (key+"_id"+i);
        }

    }

    //※引数をInputFieldに変更
    public void OnSubmit(InputField input)
    {
        //※何番目の要素か?
        int id = 0;
        for (int i = 0; i < inputinstance.Length; i++) {
        if (inputinstance[i] == input) id = i;
    }

        //※キー名と値を変更
        PlayerPrefs.SetString(key+"_id"+id,input.text);

        Debug.Log("Submit value is " + input.text);

    }

}


※が付いている部分が変更したところです。

やり方の一例です。
OnSubmit時に入力された値ではなくInputFieldそのものを渡し、保存済みのリストと照会して何番目か判断、保存時のキーとします。
(key = "hoge" だとしたら、"hoge_id1","hoge_id2"...という形で保存されます)
あまりスマートではないので、分かりやすいように変更してご利用ください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/15 14:52

    回答ありがとうございます。
    教えていただいた通り書いてみたのですが
    コンパイルは通るのですが
    インプットフィールドに値を入力しエンターなどを押してOnSubmitメソッドが呼び出すタイミングで
    エラーが出てしまいました。
    恐らく配列の範囲外ということだと思うのですが、どの配列がなぜ配列の範囲外になるかわかりませんでした・・・
    エラーの(at Assets/Scenes/test/sample2.cs:34)の34行目はinputinstance[i].onEndEdit.AddListener(delegate{OnSubmit(inputinstance[i]);});
    です。
    解決策などありますでしょうか。


    IndexOutOfRangeException: Array index is out of range.
    sample2+<Start>c__AnonStorey0.<>m__0 (System.String ) (at Assets/Scenes/test/sample2.cs:34)
    UnityEngine.Events.InvokableCall`1[System.String].Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:189)
    UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:637)
    UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:773)
    UnityEngine.Events.UnityEvent`1[T0].Invoke (.T0 arg0) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_1.cs:53)
    UnityEngine.UI.InputField.SendOnSubmit () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/InputField.cs:1582)
    UnityEngine.UI.InputField.DeactivateInputField () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/InputField.cs:2303)
    UnityEngine.UI.InputField.OnDeselect (UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/InputField.cs:2313)
    UnityEngine.EventSystems.ExecuteEvents.Execute (IDeselectHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:113)
    UnityEngine.EventSystems.ExecuteEvents.Execute[IDeselectHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:261)
    UnityEngine.EventSystems.EventSystem:Update()

    キャンセル

  • 2017/09/15 15:41

    提示のプログラムを修正しました。

    なぜかOnSubmit(inputinstance[i])にするとinputにNullが渡されてしまう為、変数を間に挟んでいます。
    Debug.Logで確認しましたが「==」でチェックしても同一のものと出るし、何故こうなるのか原因はさっぱり分かりませんが、一応動作は確認しました。
    (ついでにテスト用にPlayerPrefs.SetStringをコメントアウトしてしまっていたので外しました)

    キャンセル

  • 2017/09/15 23:34 編集

    ありがとございます!できました!
    作成したクローンのインプットフィールドをinputinstance[i]に格納し、それをfieldに格納し
    onEndEditのデリゲードOnSubmitメソッドの引数に取ったわけですね。
    全くこの方法は思いつきませんでした。
    デリゲードって波カッコの中にメソッドを入れても実行できるんですね。
    2つ疑問に思ったことがあるのですがいいでしょうか。
    このデリゲードの書き方を始めてみたのですが、このように書き方の仕様?について説明してるサイトや書籍などあるのでしょうか?

    2つ目なのですがonEndEdit.AddListenerに登録するメソッドの引数が配列の場合nullになってしまうのはunityのバグ?仕様ミス?なのでしょうか。
    よろしくお願いします。

    キャンセル

  • 2017/09/16 16:53

    >疑問1つ目
    今回はリファレンス(https://docs.unity3d.com/ja/530/ScriptReference/UI.InputField-onEndEdit.html)を参考にしました。
    デリゲードの基本的な考え方は「unity デリゲード」で出て来たサイトを見て学びました。
    (あと丁度先日このメソッドについて回答・調査していたというのもあります→https://teratail.com/questions/90988)

    >疑問2つ目
    「参照」の関係だとは思うのですが、よく分かりません。
    バグレポートでは見付からなかったので、バグに近い仕様なのかな?と思います。

    キャンセル

  • 2017/09/16 23:54

    なるほど。もやもやが解決しました。
    ありがとうございました。

    キャンセル

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

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

関連した質問

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

  • C#

    6849questions

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

  • Unity

    3804questions

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