UI ScrollRect mask not hiding Input Field Caret and Highlight

Hello There!

I’m working on some UI element setups and have a ScrollRect that contains an input field within its viewport. Whenever I input a bunch of text into the input field and then scroll, the text gets masked. However the caret and any highlighting bleeds through the mask. I’ve looked around and only found a post from 2015 with this issue with no answers so I’m wondering if anyone’s found a fix since then.

I’ve attached a picture showing the problem.

Thanks!

Seems that the issue is still not fixed in Unity 5.5. Issue Tracker says that it is in 5.5.0 but I just checked Unity 5.5.0f3, and the bug is still here. Maybe it’s fixed in patch releases, I don’t know. But anyway, there may be people who can’t upgrade to latest version, so, here is a workaround I found.

using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(InputField))]
public class FixInputSelectionMasking : MonoBehaviour {
    InputField _inputField;
    Transform _caret;

    public void Awake() {
        _inputField = GetComponent<InputField>();
    }

    public void Update() {
        if (!_caret) {
            _caret = _inputField.transform.Find(_inputField.transform.name + " Input Caret");
            if (_caret) {
                var graphic = _caret.GetComponent<Graphic>();
                if (!graphic)
					_caret.gameObject.AddComponent<Image>();
            }
        }
    }
}

Put this script on an InputField and the selection should be masked as expected:
87490-inputfield-fix-01.png

I’ve tested it in 5.4.4f1 and 5.5.0f3.

Some explanations

InputField on the fly creates a GameObject to render the selection and the caret. This object has a CanvasRenderer component and renders its geometry directly. I think that the issue is caused by that CanvasRenderer by itself doesn’t know anything about masking. It doesn’t update shader properties, related to masking (_ClipRect for Mask Rect 2D and _Stencil* for Mask).

The script that is shown above adds a dummy Image component to the GameObject which renders the selection. Image is a Graphic and it knows how to deal with the masking. I’m not sure, that this fix will work in all cases, I haven’t dug too much into implementation details of Image and InputField. I suppose that theoretically Image may override the selection geometry generated by InputField but, as I understand it, InputField regenerates the selection geometry each frame (in CanvasUpdate.LatePreRender handler).