ideas on creating retro text input field?

Hey I am trying to learn how to make an input field in this style below I have gotten started on it visually but how could i begin in C# any tips ? I am using a UI image but if there is anything more effective than please let me know and thanks. I put it in a thread so we can come up with a solution for doing this in unity since I could not find an ounce of information on this topic.

3374036--264590--SNES--Secret of Evermore_May3 15_52_44.png


here’s a gif of what im trying to do.
https://gfycat.com/ShockingLeanGelada

Heck… I could think of a way to do this that would require very little C#.

Use just the UI system. Set up each character as a button, have navigation set to ‘automatic’, and then for the onClick event of the button you call a method on a script attached to the text field passing along the character for that specific button.

That script would look something like this:

[RequireComponent(typeof(Text))]
public class TextFieldInputController : MonoBehaviour
{
    public Text Text;
  
    void Awake()
    {
        if(Text == null) Text = this.GetComponent<Text>();
    }
  
    public void Append(string character)
    {
        Text.text += character;
    }
  
    public void Backspace()
    {
        var str = Text.text;
        if(str != null && str.Length > 0)
            Text.text = str.Substring(0, str.Length - 1);
    }
}

Of course your backspace button would call backspace instead of Append.

Done.

The bulk of the work is setting up the visuals.

If you don’t have a font and don’t want each button to use the text portion of it. Just put a background image of your whole thing. And over each character put an invisible button (turn off the image and text part).

1 Like

Oh, and if you want that selection cursor. Just have a script that in Update gets the current select object from the EventSystem, and position the cursor over it.

Here’s mine… though mine uses a bit more to it since I allow resizing and various easing with my tween engine. So it’s probably overkill:

using UnityEngine;
using UnityEngine.EventSystems;

using com.spacepuppy;
using com.spacepuppy.Scenario;
using com.spacepuppy.Tween;

using com.spacepuppy.Utils;

namespace com.mansion.Entities.UI.Menus
{

    public class SelectionBorder : SPComponent
    {

        #region Fields
       
        [SerializeField]
        private float _easeDur = 1f;
        [SerializeField]
        EaseStyle _ease;
        [SerializeField]
        private bool _tweenSize;

        [SerializeField]
        [UnityEngine.Serialization.FormerlySerializedAs("_onSelectionChange")]
        private Trigger _onSelectionChanged;

        [System.NonSerialized]
        private GameObject _currentSelection;

        [System.NonSerialized]
        private Tweener _tween;

        #endregion

        #region CONSTRUCTOR

        protected override void OnStartOrEnable()
        {
            base.OnStartOrEnable();

            _currentSelection = null;

            var ev = EventSystem.current;
            if (ev == null) return;
           
            this.SetCurrent(ev.currentSelectedGameObject, false, true);
        }

        #endregion

        #region Properties

        public float EaseDur
        {
            get { return _easeDur; }
            set { _easeDur = value; }
        }

        public EaseStyle Ease
        {
            get { return _ease; }
            set { _ease = value; }
        }

        public bool TweenSize
        {
            get { return _tweenSize; }
            set { _tweenSize = value; }
        }

        public GameObject CurrentSelection
        {
            get { return _currentSelection; }
        }

        public Trigger OnSelectionChanged
        {
            get { return _onSelectionChanged; }
        }

        #endregion

        #region Methods

        public void SetCurrent(GameObject go, bool animate = false, bool suppressOnChangeEvent = false)
        {
            if (go == null) return;
            if (_tween != null)
            {
                _tween.Stop();
                _tween = null;
            }
            //if (_currentSelection == go) return;

            _currentSelection = go;
            if(animate)
            {
                var twn = SPTween.Tween(this.transform)
                 .To("position", _currentSelection.transform.position, _easeDur)
                 .Ease(EaseMethods.GetEase(_ease))
                 .UseRealTime();
                if (_tweenSize)
                {
                    var trans = _currentSelection.transform as RectTransform;
                    if (trans != null)
                    {
                        twn = twn.To("sizeDelta", trans.sizeDelta, _easeDur);
                    }
                }

                _tween = twn.Play(true, this);
            }
            else
            {
                this.transform.position = _currentSelection.transform.position;
                if (_tweenSize && this.transform is RectTransform)
                {
                    var trans = _currentSelection.transform as RectTransform;
                    if (trans != null)
                    {
                        (this.transform as RectTransform).sizeDelta = trans.sizeDelta;
                    }
                }
            }

            if (!suppressOnChangeEvent && _onSelectionChanged.Count > 0) _onSelectionChanged.ActivateTrigger(this, null);
        }

        #endregion

        #region Messages

        private void Update()
        {
            if(_tween != null && _tween.IsComplete) _tween = null;

            var ev = EventSystem.current;
            if (ev == null) return;
           
            var go = ev.currentSelectedGameObject;
            if (go == null) return;

            if (_currentSelection == go)
            {
                //hack fix - sometimes the display is shaped weird on start, so this will remedy moving UI elements once the game started, but a highlight already set
                if(_tween == null && Vector3.SqrMagnitude(_currentSelection.transform.position - this.transform.position) > MathUtil.EPSILON)
                {
                    this.SetCurrent(go, false, true);
                }
                return;
            }

            this.SetCurrent(go, true, false);
        }

        #endregion

    }

}

A much simpler version that just moves towards it at a speed, and doesn’t change size, could look like this:

public class SelectionBorder : MonoBehaviour
{
   
    public float LerpSpeed = 1f;
   
    private void Update()
    {
        var ev = EventSystem.current;
        if (ev == null) return;
       
        var go = ev.currentSelectedGameObject;
        if(go == null) return;
       
        var targ = go.transform.position;
        this.transform.position = Vector3.MoveTowards(this.transform.position, targ, this.LerpSpeed * Time.deltaTime);
    }
   
}
1 Like

Excellent there it is !I am experimenting right now with this the bottom picture is a screenshot from the project so instead of just text i will set up those buttons like you are saying.