【Unity】簡単なメモ帳を作る

概要

Undo(Ctrl+Z), Redo(Ctrl+Y)を備えた、簡単なメモ帳を作ってみることにします。

手順

①Input Fieldを作る(図1)

Unity2020では、Hierarchyを右クリックして”Create>UI>Input Field”です。

図1.Input Fieldを作る

②コードを書く

次のコードを”NotePad.cs”として保存。適当なオブジェクトにアタッチします(図2)。

using UnityEngine;
using UnityEngine.UI;

public class NotePad : MonoBehaviour
{
    void Start()
    {
        // 配列を初期化
        _Record_InputField = new string[limit];

        // Input Fieldを初期化
        if (!inputField) inputField = FindObjectOfType<InputField>();
    }

    void Update()
    {
        //キー入力(Escキーを割り当てるのは推奨しません。InputFieldのOnValueChangedが誤作動します。)
        if (Input.GetKeyDown(KeyCode.RightControl) && Application.platform == RuntimePlatform.WindowsEditor) Undo();
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Z)) Undo();
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Y)) Redo();

    }



    //メモ帳機能
    [SerializeField] private InputField inputField;

    private static int limit = 20;//20回までUndo可能

    [SerializeField] private string[] _Record_InputField; // 記録用の配列
    [SerializeField] int _record_Index = 0; // 読み込む(書き込む)Indexの値
    [SerializeField] int _normal_Limit = 0; // 順方向に戻せる残り回数
    [SerializeField] int _reverse_Limit = 0; // 逆方向に戻せる残り回数

    bool _StopRecording = false; //記録を停止する(InputFieldを戻した時の操作が記録されるとマズイ)

    //Redo,Undo機能
    /// <summary>
    /// 値の変化を記録する
    /// </summary>
    public void RecordInput()
    {
        if (!_StopRecording) //Redo・Undo→記録しない
        {
            _record_Index++; _record_Index %= limit; //0~[limit]の間で配列をループさせて使い回す
            _Record_InputField[_record_Index] = inputField.text;
            if (_normal_Limit < limit - 1) _normal_Limit++; //[limit]回までUndoできる。
            _reverse_Limit = 0;
            Debug.Log("Record");
        }
    }
    /// <summary>
    /// 戻る
    /// </summary>
    private void Undo()
    {
        if (_normal_Limit > 0)
        {
            _normal_Limit--;
            _record_Index += limit; _record_Index--; _record_Index %= limit;
            _StopRecording = true;
            inputField.text = _Record_InputField[_record_Index];
            _StopRecording = false;
            if (_reverse_Limit < limit - 1) _reverse_Limit++;
        }
    }
    /// <summary>
    /// 取り消し
    /// </summary>
    private void Redo()
    {
        if (_reverse_Limit > 0)
        {
            _reverse_Limit--;
            _record_Index++; _record_Index %= limit;
            _StopRecording = true;
            inputField.text = _Record_InputField[_record_Index];
            _StopRecording = false;
            if (_normal_Limit < limit - 1) _normal_Limit++;
        }
    }

}
図2.適当なオブジェクトにアタッチ

③InputField側の設定をする

さっき作ったInputFieldを選択。OnValueChangedの項目にいまアタッチしたスクリプトの”NotePad.RecordInput()”を設定します。

図3.InputFieldを設定

④動作確認

下の動画のように、入力文字に対し、”Ctrl+Z(エディタの場合は右Ctrlキー)”で戻る機能が、”CTRL+Y”でやり直す機能が動くはずです。

動画1.右Ctrlキーでやり直し

これで簡易メモ帳の完成です。(Playerprefs.SetString等を使えば保存機能も作れます。)



追記

・2022/02/07 (月)

コードを書き直しました。手順③を飛ばして手順①②だけで使えるようになりました。

using UnityEngine;
using UnityEngine.UI;

public class NotePad : MonoBehaviour
{
    void Start()
    {
        // 配列を初期化
        _Record_InputField = new string[limit];

        // Input Fieldを初期化
        if (!inputField) inputField = FindObjectOfType<InputField>();
        inputField.onValueChanged.AddListener((_) => RecordInput());
    }

    void Update()
    {
        //キー入力(Escキーを割り当てるのは推奨しません。InputFieldのOnValueChangedが誤作動します。)
        if (Input.GetKeyDown(KeyCode.RightControl) && Application.platform == RuntimePlatform.WindowsEditor) Undo();
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Z)) Undo();
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Y)) Redo();
    }



    //メモ帳機能
    [SerializeField] private InputField inputField;

    private static int limit = 20;//20回までUndo可能

    [SerializeField] private string[] _Record_InputField; // 記録用の配列
    [SerializeField] int _record_Index = 0; // 読み込む(書き込む)Indexの値
    [SerializeField] int _normal_Limit = 0; // 順方向に戻せる(Redo)残り回数
    [SerializeField] int _reverse_Limit = 0; // 逆方向に戻せる(Undo)残り回数

    //Redo,Undo機能
    /// <summary>
    /// 値の変化を記録する
    /// </summary>
    public void RecordInput()
    {
        _record_Index++; _record_Index %= limit; //0~[limit]の間で配列をループさせて使い回す
        _Record_InputField[_record_Index] = inputField.text;
        if (_normal_Limit < limit - 1) _normal_Limit++; //[limit]回までUndoできる。
        _reverse_Limit = 0;
        Debug.Log("Record");
    }
    /// <summary>
    /// 戻る
    /// </summary>
    private void Undo()
    {
        if (_normal_Limit > 0)
        {
            _normal_Limit--;
            _record_Index += limit; _record_Index--; _record_Index %= limit;
            inputField.SetTextWithoutNotify(_Record_InputField[_record_Index]);
            if (_reverse_Limit < limit - 1) _reverse_Limit++;
        }
    }
    /// <summary>
    /// 取り消し
    /// </summary>
    private void Redo()
    {
        if (_reverse_Limit > 0)
        {
            _reverse_Limit--;
            _record_Index++; _record_Index %= limit;
            inputField.SetTextWithoutNotify(_Record_InputField[_record_Index]);
            if (_normal_Limit < limit - 1) _normal_Limit++;
        }
    }
}

作成者: rarafy

2013年くらいからUnityを触っているかもしれません。 特に書くこともありませんが、趣味は部屋の掃除です。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です