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.
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:
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).