Блокнот для игры / заметки игрока

В былые времена, для прохождения некоторых игр, нужно было при себе держать листок бумаги и ручку, чтобы делать важные заметки, записывать какие-то коды и прочие интересности. Настоящий хардкор! Не то что современные бродилки, где даже и думать не надо (а парой и играть вовсе), игра всё сама делает. Так вот, если вы хотите для своей игры добавить возможность игроку делать свои заметки, не на бумаге, а прямо в игре, то мы предлагаем простое и эффективное решение. Данный блокнот, позволяет сохранять и загружать набранный текст.


Для ввода текста, нам понадобится Input Field, на который вешаем скрипт:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class NotepadComponent : MonoBehaviour, IPointerClickHandler, IPointerExitHandler {

    public InputField inputField;
    private bool wasFocused;

    void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
    {
        if (!wasFocused)
        {
            inputField.caretPosition = inputField.text.Length;
            wasFocused = true;
        }
    }

    void IPointerExitHandler.OnPointerExit(PointerEventData eventData)
    {
        wasFocused = false;
    }
}
Кроме ссылки на объект ввода, этот класс нужен, чтобы сбрасывать авто выделение текста. Обратите внимание, что размер текста в InputField, должен быть такой же, как и у InputField Placeholder. Это необходимо для корректной регулировки высоты текстового поля.

Теперь, куда-нибудь вешаем скрипт:

using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;

public class Notepad : MonoBehaviour {

    public int characterLimit = 3000; // лимит на количество символов
    public ScrollRect scrollRect;
    public NotepadComponent component;
    public Button saveButton, clearButton, loadButton;
    public Text characterInfo; // осталось символов
    private Text placeholder;
    private float index = 1, height;
    private bool wasFocused;

    void Start()
    {
        placeholder = component.inputField.placeholder.GetComponent<Text>();
        component.inputField.lineType = InputField.LineType.MultiLineNewline;
        component.inputField.characterLimit = characterLimit;
        height = placeholder.preferredHeight;
        saveButton.onClick.AddListener(()=> { Write(); });
        clearButton.onClick.AddListener(() => { Clear(); });
        loadButton.onClick.AddListener(() => { Load(); });
        component.inputField.textComponent.text = string.Empty;
        component.inputField.onValueChanged.AddListener(delegate { CharInfo(); });

        if (File.Exists(FilePath()))
        {
            Load();
        }
        else
        {
            FieldSize(0);
        }
    }

    void Clear()
    {
        component.inputField.text = string.Empty;
        component.inputField.textComponent.text = string.Empty;
        index = 1;
        FieldSize(0);
    }

    void CharInfo()
    {
        characterInfo.text = "Осталось символов: " + (characterLimit - component.inputField.textComponent.text.Length);
    }

    void FieldSize(float scroll)
    {
        index++;
        scrollRect.content.sizeDelta = new Vector2(scrollRect.content.sizeDelta.x, height * index);
        scrollRect.content.anchoredPosition = Vector2.zero;
        scrollRect.verticalNormalizedPosition = scroll;
    }

    string ReplaceNewLine(string str)
    {
        return Regex.Replace(str, "\n", "<br>");
    }

    string ReplaceBR(string str)
    {
        return Regex.Replace(str, "<br>", "\n");
    }

    string FilePath()
    {
        return Application.persistentDataPath + "/Notepad.bin";
    }

    string Crypt(string text)
    {
        string result = string.Empty;
        foreach (char j in text) result += (char)((int)j ^ 47);
        return result;
    }

    void Load()
    {
        Clear();

        StreamReader reader = new StreamReader(FilePath());
        string result = string.Empty;

        while (!reader.EndOfStream)
        {
            result += Crypt(reader.ReadLine()).Trim();
        }

        reader.Close();

        index = Regex.Matches(result, "<br>").Count + 1;
        FieldSize(1);
        component.inputField.text = ReplaceBR(result);

        Debug.Log(this + " --> Загрузка файла: " + FilePath());
    }

    void Write()
    {
        if (component.inputField.textComponent.text.Trim().Length == 0)
        {
            Debug.Log(this + " --> Отсутствуют данные для записи...");
            return;
        }

        StreamWriter writer = new StreamWriter(FilePath());
        writer.WriteLine(Crypt(ReplaceNewLine(component.inputField.textComponent.text.Trim())));
        writer.Close();
        Debug.Log(this + " --> Запись файла: " + FilePath());
    }

    void CheckField()
    {
        index = Regex.Matches(component.inputField.textComponent.text, "\n").Count + 1;
        FieldSize(scrollRect.verticalNormalizedPosition);
    }

    void Update()
    {
        if (wasFocused && Input.GetKeyDown(KeyCode.Return))
        {
            FieldSize(0);
        }
        else if (wasFocused && Input.anyKeyDown)
        {
            CheckField();
        }

        wasFocused = component.inputField.isFocused;

        CharInfo();
    }
}
Здесь используется ScrollRect, чтобы была возможность прокрутки текста. Сам InputField, нужно поместить в раздел контента ScrollRect и настроить его по ширине окна прокрутки, а высота будет регулироваться в зависимости от объема текста. Более подробно можно всё посмотреть и пощупать в демо ниже...

Скачать демо проект:
https://www.patreon.com/posts/bloknot-dlia-23168197
Тестировалось на: Unity 2018.2.17
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика