- Home /
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!
Answer by zxkne · Feb 06, 2017 at 11:46 AM
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).
I don't have enough permissions to post a comment, @zxkne, so I'll post my thanks to your solution here.
I do have one observation, though. When will _caret ever be non-null?
@onatangent, you're right, _caret usage was absolute nonsense. I've edited code in the answer. The original idea was to remember the caret so that Transform.Find() isn't called every frame (but is called if the caret was destroyed somehow). Thanks for pointing it out!
I've just tested it on Unity 5.5.2f1, this solution works perfectly! It should be marked as solution (for now).