最终效果
代码
using System.Collections; using UnityEngine; using UnityEngine.UI; [DisallowMultipleComponent] [RequireComponent(typeof(CanvasRenderer))] [RequireComponent(typeof(RectTransform))] public class MyInputField_Caret : MonoBehaviour, ICanvasElement { private VertexHelper m_CaretVh; private Mesh m_CaretMesh; public Text m_Text; [Range(1, 5)] public int m_CaretWidth = 1; //光标宽度 public Color m_CaretColor = Color.black; //光标颜色 [Range(0f, 4f)] public float m_CaretBlinkRate = 0.85f; //光标闪烁频率, 1s闪烁多少次, 显示-隐藏, 知道下次显示前为1次闪烁 private float m_CaretBlinkStartTime; private bool m_CaretVisibleFlag = true; private Coroutine m_BlinkCo; private int m_CaretPos; //光标在哪个字符处, 光标处字符指示的是光标后面那个字符 private CanvasRenderer m_CaretRenderer; public CanvasRenderer caretRenderer { get { if (null == m_CaretRenderer) m_CaretRenderer = GetComponent<CanvasRenderer>(); return m_CaretRenderer; } } void Start() { m_CaretVh = new VertexHelper(); m_CaretMesh = new Mesh(); var renderer = this.caretRenderer; //设置材质和贴图 renderer.materialCount = 1; var caretMat = Graphic.defaultGraphicMaterial; renderer.SetMaterial(caretMat, 0); var caretTexture = Texture2D.whiteTexture; renderer.SetTexture(caretTexture); //设置顶点 PopulateCaretMesh(m_CaretVh); m_CaretVh.FillMesh(m_CaretMesh); renderer.SetMesh(m_CaretMesh); m_BlinkCo = StartCoroutine(CaretBlinkCo()); } public virtual void Rebuild(CanvasUpdate update) { switch (update) { case CanvasUpdate.LatePreRender: UpdateCaretVerts(); break; } } public void LayoutComplete() { } public void GraphicUpdateComplete() { } public bool IsDestroyed() { return (null == this); } private void UpdateCaretVerts() { var renderer = this.caretRenderer; m_CaretVh.Clear(); //设置顶点 if (m_CaretVisibleFlag) PopulateCaretMesh(m_CaretVh); m_CaretVh.FillMesh(m_CaretMesh); renderer.SetMesh(m_CaretMesh); } private void PopulateCaretMesh(VertexHelper vh) { var textGen = m_Text.cachedTextGenerator; if (textGen.characterCount <= 0) return; //光标显示在字符位置处 float minX = 0; if (m_CaretPos < textGen.characters.Count) { var chInfo = textGen.characters[m_CaretPos]; minX = chInfo.cursorPos.x; minX /= m_Text.pixelsPerUnit; } //找出光标处字符在哪一行上 var caretLine = textGen.lineCount - 1; for (int i = 1; i < textGen.lineCount; ++i) { var tLineInfo = textGen.lines[i]; if (tLineInfo.startCharIdx > m_CaretPos) { caretLine = i - 1; break; } } var lineInfo = textGen.lines[caretLine]; float maxY = lineInfo.topY / m_Text.pixelsPerUnit; float minY = maxY - lineInfo.height / m_Text.pixelsPerUnit; //这边添加一个四边形 vh.AddVert(new Vector3(minX, maxY), m_CaretColor, new Vector2(0f, 1f)); //左上 vh.AddVert(new Vector3(minX + m_CaretWidth, maxY), m_CaretColor, new Vector2(1f, 1f)); //右上 vh.AddVert(new Vector3(minX + m_CaretWidth, minY), m_CaretColor, new Vector2(1f, 0f)); //右下 vh.AddVert(new Vector3(minX, minY), m_CaretColor, new Vector2(0f, 0f)); //左下 //顺时针 vh.AddTriangle(0, 1, 2); vh.AddTriangle(0, 2, 3); } IEnumerator CaretBlinkCo() { m_CaretVisibleFlag = true; m_CaretBlinkStartTime = Time.unscaledTime; yield return null; while (m_CaretBlinkRate > 0) { float blinkFullPeriod = 1 / m_CaretBlinkRate; float blinkVisiblePeriod = blinkFullPeriod * 0.5f; //比如: 2s闪烁1次, 那[0, 1)光标是显示状态, [1, 2)光标是隐藏状态 bool visibleFlag = ((Time.unscaledTime - m_CaretBlinkStartTime) % blinkFullPeriod) < blinkVisiblePeriod; if (m_CaretVisibleFlag != visibleFlag) { m_CaretVisibleFlag = visibleFlag; UpdateCaretVerts(); } yield return null; } m_BlinkCo = null; } void Update() { if (Input.GetKeyDown(KeyCode.LeftArrow)) { if (m_CaretPos > 0) { m_CaretPos--; //光标闪烁重置(重新开始计时) m_CaretVisibleFlag = true; m_CaretBlinkStartTime = Time.unscaledTime; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); //下一帧统一更新 } } if (Input.GetKeyDown(KeyCode.RightArrow)) { if (m_CaretPos < m_Text.text.Length) { m_CaretPos++; //光标闪烁重置(重新开始计时) m_CaretVisibleFlag = true; m_CaretBlinkStartTime = Time.unscaledTime; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); //下一帧统一更新 } } } }
ugui的InputField做了,我们这边简化掉了的:
上下箭头让光标上下移动
ctrl+右箭头,移到下一行行首
ctrl+左箭头,移到当前行首或上一行行首
Home键,移到第1个字符前
End键,移到最后1个字符后
控件有焦点的情况才响应左右箭头键
标签:InputField,void,private,renderer,new,ugui,public,光标 From: https://www.cnblogs.com/sailJs/p/17587477.html