【Unity UGUI】InputField 输入框全解

文章目录

    • [0. 效果预览](#0. 效果预览)
    • [1. 需求分析](#1. 需求分析)
    • [2. Hierarchy 搭建](#2. Hierarchy 搭建)
    • [3. 核心组件配置](#3. 核心组件配置)
      • [3.1 TMP_InputField 组件面板](#3.1 TMP_InputField 组件面板)
      • [3.2 Content Type 详解](#3.2 Content Type 详解)
      • [3.3 Line Type 三种模式](#3.3 Line Type 三种模式)
      • [3.4 RectTransform 建议](#3.4 RectTransform 建议)
    • [4. 完整代码](#4. 完整代码)
      • [4.1 InputFieldDemo.cs](#4.1 InputFieldDemo.cs)
      • [4.2 聊天输入的进阶:Shift+Enter 换行](#4.2 聊天输入的进阶:Shift+Enter 换行)
    • [5. 使用方法](#5. 使用方法)
      • [5.1 基础 InputField](#5.1 基础 InputField)
      • [5.2 密码输入框](#5.2 密码输入框)
      • [5.3 聊天输入框](#5.3 聊天输入框)
    • [6. 参数说明](#6. 参数说明)
      • [InputFieldDemo.cs 可调参数](#InputFieldDemo.cs 可调参数)
    • [7. 变体与扩展](#7. 变体与扩展)
      • [7.1 正则表达式校验](#7.1 正则表达式校验)
      • [7.2 数值输入 + 范围限制](#7.2 数值输入 + 范围限制)
      • [7.3 输入框聚焦时弹出自定义面板](#7.3 输入框聚焦时弹出自定义面板)
    • [8. 常见问题](#8. 常见问题)
    • [9. 附:遇到 Legacy InputField 怎么迁移](#9. 附:遇到 Legacy InputField 怎么迁移)
    • [10. 性能 / 适配建议](#10. 性能 / 适配建议)

0. 效果预览


InputField 是 UGUI 的文本输入组件,覆盖登录注册、聊天输入、搜索栏、数值编辑等场景。看似简单,但移动端键盘适配、输入校验、TMP 版差异这些坑,踩一次就够喝一壶。


1. 需求分析

核心思路:InputField = 一个可编辑的 Text + 光标 + 选中高亮 + 事件回调,搞清楚它的组成结构和事件时机就够应付 90% 的场景。

典型使用场景:

  • 登录/注册界面的账号密码输入
  • 游戏内聊天输入栏
  • 搜索框 / 筛选框
  • Inspector 风格的数值编辑字段
  • 控制台 / 指令输入

需要实现的功能点:

  • 单行输入与多行输入
  • 密码遮挡模式
  • 输入类型限制(纯数字、字母、自定义正则)
  • 字符数量限制
  • 占位文本(Placeholder)
  • 事件回调:内容变化、提交、选中/失焦
  • 移动端软键盘适配

前置知识:建议先阅读本系列 文章 1(总领篇),了解 Canvas、RectTransform、EventSystem 的基本概念。


2. Hierarchy 搭建

原生 InputField 和 TMP 版的层级略有不同,这里以推荐的 TMP_InputField 为准:

复制代码
Canvas
└── InputField (TMP)                 ← Image(背景)+ TMP_InputField 组件
    └── Text Area(RectMask2D)       ← 裁剪区域,防止文字溢出输入框
        ├── Placeholder(TMP_Text)   ← 占位提示文字
        └── Tmp_Content(TMP_Text)   ← 实际输入内容
  • InputField (TMP) :父对象,挂 Image(背景)和 TMP_InputField 组件

  • Text Area :挂 RectMask2D,作用是裁剪超出输入框范围的文字。输入内容很长时,文字只在这个区域内可见,不会画到外面去。不要删除这个组件

    复制代码
    Q:为什么原生 InputField 没有 RectMask2D 也不会溢出?
    A:两者的裁剪机制不同。
        -- 原生 Text 组件在生成网格阶段就按 RectTransform 范围裁掉了超出的字符------顶点根本没生成,自然画不出去。
        -- 而 TMP 会把所有字符的网格都生成出来,裁剪交给渲染阶段处理,所以需要 RectMask2D在 Shader 层面丢弃超出区域的像素。代价是多一个组件,好处是能支持更灵活的文字滚动和溢出省略号等高级功能。
  • Placeholder:占位提示文字,输入内容为空时显示(如"请输入用户名...")

  • Tmp_Content:真正显示用户输入内容的文本组件

快捷创建:在 Hierarchy 右键 → UI → InputField - TextMeshPro,Unity 会自动帮你搭好这套结构(含 Text Area)。原生版选 UI → InputField,层级少一层 Text Area,但渲染质量不如 TMP。


3. 核心组件配置

3.1 TMP_InputField 组件面板

参数 说明
Text Component 拖入子对象 Tmp_Content(TMP_Text),用于显示输入内容
Text 当前输入内容(运行时读写)
Character Limit 最大字符数,0 = 不限制
Content Type 输入类型预设(Standard / Integer / Decimal / Alphanumeric / Password 等)
Line Type 单行 / 多行自动换行 / 多行带回车提交
Placeholder 拖入子对象 Placeholder(TMP_Text)
Caret Blink Rate 光标闪烁频率(0 = 不闪)
Caret Width 光标像素宽度
Caret Color 光标颜色
Selection Color 选中文字的高亮背景色
Hide Mobile Input 移动端是否隐藏原生输入框(iOS 顶部横条)
Rich Text 是否支持富文本标签(TMP 独有)
Read Only 只读模式,可选中复制但不能编辑

3.2 Content Type 详解

Content Type 是最常用的配置项,它本质上是一组预设,控制了三个底层属性的组合:

Content Type Input Type Keyboard Type Character Validation
Standard Standard Default None
Autocorrected AutoCorrect Default None
Integer Number Standard NumberPad Integer
Decimal Number Standard NumbersAndPunctuation Decimal
Alphanumeric Standard Default Alphanumeric
Name Standard Default Name(首字母自动大写)
Email Address Standard EmailAddress EmailAddress
Password Password Default None
Pin Password NumberPad Integer
Custom 手动选 手动选 手动选

选 Custom 的时机:当预设不满足需求时------比如你想要"数字键盘 + 密码遮挡",就得选 Custom 自己组合。

3.3 Line Type 三种模式

Line Type 行为 回车键效果
Single Line 只能输入一行,回车 = 提交 触发 onEndEdit / onSubmit
Multi Line Submit 可以显示多行,但回车仍 = 提交 触发 onEndEdit / onSubmit
Multi Line Newline 回车 = 换行,不会触发提交 插入 \n

聊天输入框通常用 Single LineMulti Line Submit (回车发送消息)。备注/日志输入框用 Multi Line Newline

3.4 RectTransform 建议

对象 锚点 建议尺寸
InputField (TMP) 按需求定位 宽 200-400,高 30-40(单行)
Text Area Stretch All(四角拉满) 跟随父对象,四边各留 10px padding
Placeholder Stretch All(四角拉满) 跟随 Text Area
Tmp_Content Stretch All(四角拉满) 跟随 Text Area

Text Area 的 RectTransform 四边留 10px padding(通过 Left/Right/Top/Bottom 偏移实现),Placeholder 和 Tmp_Content 拉满 Text Area 即可。


4. 完整代码

以下脚本演示 InputField 的常用操作:事件监听、输入校验、密码框切换、聊天提交。

4.1 InputFieldDemo.cs

csharp 复制代码
using UnityEngine;
using UnityEngine.UI;  // Toggle 仍在此命名空间
using TMPro;           // TMP_InputField、TMP_Text

/// <summary>
/// TMP_InputField 基础用法演示:事件监听、字符校验、密码框切换
/// </summary>
public class InputFieldDemo : MonoBehaviour
{
    // ===== Inspector 引用 =====
    [Header("输入框引用")]
    [SerializeField] private TMP_InputField usernameInput;   // 用户名输入框
    [SerializeField] private TMP_InputField passwordInput;   // 密码输入框
    [SerializeField] private TMP_InputField chatInput;       // 聊天输入框

    [Header("UI 反馈")]
    [SerializeField] private TMP_Text feedbackText;          // 校验提示文本
    [SerializeField] private Toggle showPasswordToggle;      // 显示/隐藏密码的 Toggle

    [Header("校验规则")]
    [SerializeField] private int minUsernameLength = 3;      // 用户名最短长度
    [SerializeField] private int maxUsernameLength = 16;     // 用户名最长长度

    // ===== 生命周期 =====
    private void Start()
    {
        // 监听用户名输入变化------每输入一个字符都会触发
        usernameInput.onValueChanged.AddListener(OnUsernameChanged);

        // 监听用户名输入结束(失焦或回车)
        usernameInput.onEndEdit.AddListener(OnUsernameEndEdit);

        // 监听聊天输入框提交(回车)
        chatInput.onEndEdit.AddListener(OnChatSubmit);

        // 监听密码显示/隐藏切换
        if (showPasswordToggle != null)
            showPasswordToggle.onValueChanged.AddListener(OnTogglePasswordVisibility);

        // 自定义字符校验:用户名只允许字母、数字、下划线
        usernameInput.onValidateInput += ValidateUsernameChar;

        // 设置初始状态
        SetupInputFields();
    }

    private void OnDestroy()
    {
        // 移除监听,防止内存泄漏
        usernameInput.onValueChanged.RemoveListener(OnUsernameChanged);
        usernameInput.onEndEdit.RemoveListener(OnUsernameEndEdit);
        chatInput.onEndEdit.RemoveListener(OnChatSubmit);

        if (showPasswordToggle != null)
            showPasswordToggle.onValueChanged.RemoveListener(OnTogglePasswordVisibility);

        usernameInput.onValidateInput -= ValidateUsernameChar;
    }

    // ===== 初始化 =====
    private void SetupInputFields()
    {
        // 用户名:字母数字,限制长度
        usernameInput.characterLimit = maxUsernameLength;
        usernameInput.contentType = TMP_InputField.ContentType.Custom;
        usernameInput.inputType = TMP_InputField.InputType.Standard;
        usernameInput.keyboardType = TouchScreenKeyboardType.Default;

        // 密码:默认遮挡模式
        passwordInput.contentType = TMP_InputField.ContentType.Password;
        passwordInput.characterLimit = 20;

        // 聊天:单行,回车提交
        chatInput.lineType = TMP_InputField.LineType.SingleLine;
    }

    // ===== 事件回调 =====

    /// <summary>
    /// 用户名每次输入变化时的实时反馈
    /// </summary>
    private void OnUsernameChanged(string value)
    {
        if (value.Length < minUsernameLength)
        {
            feedbackText.text = $"至少输入 {minUsernameLength} 个字符";
            feedbackText.color = Color.yellow;
        }
        else
        {
            feedbackText.text = "✓ 用户名格式正确";
            feedbackText.color = Color.green;
        }
    }

    /// <summary>
    /// 用户名输入结束时的完整校验
    /// </summary>
    private void OnUsernameEndEdit(string value)
    {
        // 注意:按 Esc 取消也会触发 onEndEdit
        // 通过 wasCanceled 区分是提交还是取消
        if (usernameInput.wasCanceled)
        {
            Debug.Log("用户取消了输入");
            return;
        }

        if (value.Length < minUsernameLength)
        {
            feedbackText.text = $"用户名至少 {minUsernameLength} 个字符";
            feedbackText.color = Color.red;
        }
        else
        {
            Debug.Log($"用户名确认: {value}");
        }
    }

    /// <summary>
    /// 聊天输入框回车提交
    /// </summary>
    private void OnChatSubmit(string message)
    {
        // 忽略空消息和取消操作
        if (chatInput.wasCanceled || string.IsNullOrWhiteSpace(message))
            return;

        Debug.Log($"发送消息: {message}");

        // 清空输入框并重新聚焦,方便连续输入
        chatInput.text = "";
        chatInput.ActivateInputField();
    }

    /// <summary>
    /// 切换密码可见性
    /// </summary>
    private void OnTogglePasswordVisibility(bool showPassword)
    {
        // 记住当前内容
        string currentText = passwordInput.text;

        if (showPassword)
        {
            // 明文显示
            passwordInput.contentType = TMP_InputField.ContentType.Standard;
        }
        else
        {
            // 密码遮挡
            passwordInput.contentType = TMP_InputField.ContentType.Password;
        }

        // 切换 contentType 后必须调用 ForceLabelUpdate 才能立即刷新显示
        passwordInput.text = currentText;
        passwordInput.ForceLabelUpdate();
    }

    // ===== 自定义字符校验 =====

    /// <summary>
    /// 逐字符校验:只允许字母、数字、下划线
    /// 返回 '\0' 表示拒绝该字符
    /// </summary>
    private char ValidateUsernameChar(string text, int charIndex, char addedChar)
    {
        // 字母
        if (char.IsLetterOrDigit(addedChar))
            return addedChar;

        // 下划线
        if (addedChar == '_')
            return addedChar;

        // 其他字符一律拒绝
        return '\0';
    }
}

4.2 聊天输入的进阶:Shift+Enter 换行

如果希望聊天输入框支持 Shift+Enter 换行、单独 Enter 发送,需要自己处理按键逻辑:

csharp 复制代码
using UnityEngine;
using UnityEngine.EventSystems;
using TMPro;

/// <summary>
/// 聊天输入框:Enter 发送,Shift+Enter 换行
/// </summary>
public class ChatInputHandler : MonoBehaviour, ISubmitHandler
{
    [SerializeField] private TMP_InputField chatInput;

    private void Start()
    {
        // 多行模式才能插入换行符
        chatInput.lineType = TMP_InputField.LineType.MultiLineNewline;
    }

    private void Update()
    {
        // 只在输入框聚焦时处理
        if (!chatInput.isFocused) return;

        // Enter 按下(不含 Shift)= 发送
        if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
        {
            bool shiftHeld = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);

            if (!shiftHeld)
            {
                // 发送消息
                SendChatMessage(chatInput.text);
            }
            // Shift+Enter 由 InputField 自身的 MultiLineNewline 模式处理换行,不需要额外代码
        }
    }

    private void SendChatMessage(string message)
    {
        if (string.IsNullOrWhiteSpace(message)) return;

        // 去掉末尾可能多出的换行符
        message = message.TrimEnd('\n', '\r');

        Debug.Log($"发送: {message}");

        chatInput.text = "";
        chatInput.ActivateInputField();
    }

    // ISubmitHandler 接口------防止默认的 Submit 行为
    public void OnSubmit(BaseEventData eventData)
    {
        // 留空,阻止默认行为
    }
}

5. 使用方法

5.1 基础 InputField

  1. Hierarchy 右键 → UI → InputField - TextMeshPro 创建输入框
  2. 选中 InputField (TMP) 对象,在 Inspector 中设置:
    • Content TypeStandard(通用文本)
    • Character Limit16(最大字符数)
    • 展开子对象 Text Area → Placeholder,修改文字为 "请输入用户名..."
  3. 创建空物体 InputFieldDemo ,挂载 InputFieldDemo.cs
  4. 把 InputField (TMP) 拖入 usernameInput 字段
  5. 创建一个 TextMeshPro 文本(UI → Text - TextMeshPro)用于显示校验反馈,拖入 feedbackText
  6. 运行,输入字符观察实时校验反馈

5.2 密码输入框

  1. 再创建一个 InputField - TextMeshPro,Content TypePassword
  2. 拖入 passwordInput 字段
  3. (可选)创建 Toggle 控制密码显示/隐藏,拖入 showPasswordToggle
  4. 运行,输入密码看到星号遮挡;勾选 Toggle 切换明文

5.3 聊天输入框

  1. 再创建一个 InputField - TextMeshPro,Line TypeSingle Line
  2. 展开子对象 Text Area → Placeholder,修改文字为 "按 Enter 发送..."
  3. 拖入 chatInput 字段
  4. 运行,输入内容后按 Enter,查看 Console 的发送日志
  5. 确认发送后输入框自动清空并重新聚焦

6. 参数说明

InputFieldDemo.cs 可调参数

参数 类型 默认值 说明
usernameInput TMP_InputField --- 用户名输入框引用
passwordInput TMP_InputField --- 密码输入框引用
chatInput TMP_InputField --- 聊天输入框引用
feedbackText TMP_Text --- 校验反馈文本引用
showPasswordToggle Toggle --- 密码明文切换 Toggle
minUsernameLength int 3 用户名最短长度
maxUsernameLength int 16 用户名最长长度

7. 变体与扩展

7.1 正则表达式校验

onValidateInput 是逐字符校验,有时需要对完整输入做正则校验(比如邮箱格式)。这种情况在 onEndEdit 中做:

csharp 复制代码
using System.Text.RegularExpressions;

private void OnEmailEndEdit(string value)
{
    // 简单的邮箱正则
    string pattern = @"^[\w\.-]+@[\w\.-]+\.\w+$";

    if (!Regex.IsMatch(value, pattern))
    {
        feedbackText.text = "邮箱格式不正确";
        feedbackText.color = Color.red;
    }
}

onValidateInput 管"每个字符能不能输入",onEndEdit 管"最终结果是否合法"。两者配合使用。

7.2 数值输入 + 范围限制

Content Type 设为 Integer / Decimal 只能限制输入字符类型,无法限制数值范围。范围限制在 onEndEdit 里做:

csharp 复制代码
[SerializeField] private TMP_InputField hpInput;

private void OnHpEndEdit(string value)
{
    if (int.TryParse(value, out int hp))
    {
        // 限制在 0-9999
        hp = Mathf.Clamp(hp, 0, 9999);
        hpInput.text = hp.ToString();
    }
    else
    {
        hpInput.text = "0";
    }
}

7.3 输入框聚焦时弹出自定义面板

有些场景不用系统键盘,而是弹出自定义的虚拟键盘或选择面板:

csharp 复制代码
[SerializeField] private TMP_InputField codeInput;
[SerializeField] private GameObject customKeyboard; // 自定义键盘面板

private void Start()
{
    // 监听选中事件
    codeInput.onSelect.AddListener(OnInputSelected);
    codeInput.onDeselect.AddListener(OnInputDeselected);
}

private void OnInputSelected(string value)
{
    customKeyboard.SetActive(true);
}

private void OnInputDeselected(string value)
{
    customKeyboard.SetActive(false);
}

8. 常见问题

Q1: onEndEdit 为什么点击空白处也会触发?

onEndEdit 在输入框失去焦点时 触发,不管是回车提交还是点击了别处。用 inputField.wasCanceled 区分:

csharp 复制代码
private void OnEndEdit(string value)
{
    if (usernameInput.wasCanceled)
    {
        // 用户按 Esc 或点击了别处
        return;
    }
    // 正常提交逻辑
}

注意:点击别处导致的失焦,wasCanceled 在不同 Unity 版本行为略有差异。如果需要严格区分"回车提交",可以用 onSubmit(仅回车触发)替代。


Q2: 切换 Content Type 后显示没变化?

切换 contentType 后必须手动刷新。最可靠的做法:

csharp 复制代码
string temp = inputField.text;
inputField.contentType = TMP_InputField.ContentType.Password;
inputField.text = temp;
inputField.ForceLabelUpdate(); // 强制刷新显示

只改 contentType 不调 ForceLabelUpdate(),文本显示不会立即更新。


Q3: 移动端软键盘遮挡了输入框怎么办?

iOS / Android 弹出软键盘时,输入框可能被键盘遮住。常见解决方案:

csharp 复制代码
private void Update()
{
    // 软键盘可见时,将 Canvas 上移
    if (TouchScreenKeyboard.visible)
    {
        float keyboardHeight = GetKeyboardHeight();
        // 将输入框所在区域上移 keyboardHeight
        inputArea.anchoredPosition = new Vector2(0, keyboardHeight);
    }
    else
    {
        inputArea.anchoredPosition = Vector2.zero;
    }
}

/// <summary>
/// 获取软键盘高度(像素)
/// </summary>
private float GetKeyboardHeight()
{
#if UNITY_ANDROID
    using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    {
        var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        var view = activity.Call<AndroidJavaObject>("getWindow")
                          .Call<AndroidJavaObject>("getDecorView");
        var rect = new AndroidJavaObject("android.graphics.Rect");
        view.Call("getWindowVisibleDisplayFrame", rect);
        int screenHeight = Screen.height;
        int visibleHeight = rect.Call<int>("height");
        return screenHeight - visibleHeight;
    }
#elif UNITY_IOS
    return (float)TouchScreenKeyboard.area.height;
#else
    return 0;
#endif
}

另一个思路:把输入框放在屏幕上半区域,大多数情况下键盘不会遮到。


Q4: InputField 中文输入法(IME)组合输入时 onValueChanged 触发异常?

中文输入法在组合拼音阶段会不断触发 onValueChanged,拼音确认前的内容可能是半成品。解决方案:

  • 不要在 onValueChanged 中做重量级操作(如网络请求、数据库查询)
  • 把"搜索"之类的操作放到 onEndEdit 或加一个延迟(用户停止输入 0.3s 后再触发)
csharp 复制代码
private Coroutine _debounceCoroutine;

private void OnSearchValueChanged(string value)
{
    // 每次输入变化,重置延迟计时
    if (_debounceCoroutine != null)
        StopCoroutine(_debounceCoroutine);

    _debounceCoroutine = StartCoroutine(DebounceSearch(value, 0.3f));
}

private System.Collections.IEnumerator DebounceSearch(string query, float delay)
{
    yield return new WaitForSeconds(delay);
    // 延迟后才真正执行搜索
    Debug.Log($"搜索: {query}");
}

Q5: InputField 和 TMP_InputField 用哪个?

详见下一节。简短回答:新项目用 TMP_InputField,除非你有特殊理由坚持用原生 Text。


9. 附:遇到 Legacy InputField 怎么迁移

本文全部代码基于 TMP_InputField。如果你在老项目中遇到了原生 InputField(Legacy),以下是两者的差异和迁移要点:

对比项 InputField(Legacy) TMP_InputField(本文使用)
文字渲染 位图字体,缩放模糊 SDF 字体,任意缩放清晰
富文本 基础 <b><i><color> 完整富文本标签体系
命名空间 UnityEngine.UI TMPro
组件引用 InputFieldText TMP_InputFieldTMP_Text
创建方式 UI → InputField UI → InputField - TextMeshPro
Hierarchy 没有 Text Area 层 多一层 Text Area(RectMask2D)
性能 字符多时顶点数暴增 顶点数更可控,大段文本更优

迁移只需要改三样东西

csharp 复制代码
// Legacy 版
using UnityEngine.UI;
InputField input;
Text text;

// TMP 版------改 using、改类型,API 几乎一样
using TMPro;
TMP_InputField input;
TMP_Text text;

两者的事件签名一致:onValueChangedonEndEditonSelectonDeselectonValidateInput。迁移时基本只需要换 using 声明、字段类型、枚举前缀(InputField.ContentTypeTMP_InputField.ContentType)。


10. 性能 / 适配建议

  1. 不要在 onValueChanged 里做重操作 。每输入一个字符都会触发,如果里面有字符串拼接、网络请求或大量 UI 更新,帧率直接起飞(往下飞)。加 debounce 或把逻辑移到 onEndEdit

  2. 中文输入场景优先用 TMP_InputField。原生 Text 的中文渲染在高 DPI 屏幕上容易糊,TMP 的 SDF 渲染清晰度好得多。

  3. Raycast Target 只开在需要交互的对象上。InputField 的 Placeholder 和 Text 子对象默认开启 Raycast Target,但它们不需要接收射线。关掉可以减少 GraphicRaycaster 的遍历开销。

  4. 移动端注意 Hide Mobile Input 。iOS 默认会在屏幕顶部显示一个原生输入条,勾选 Hide Mobile Input 可以隐藏它,但部分旧 iOS 版本上可能导致中文输入异常。建议在目标设备上实测。

  5. 多个输入框的 Tab 切换。Unity 原生不支持 Tab 键在 InputField 之间切换焦点。如果需要(登录表单场景很常见),自己写一个简单的 Tab 导航:

csharp 复制代码
[SerializeField] private Selectable[] tabOrder; // 按顺序拖入各输入框

private void Update()
{
    if (Input.GetKeyDown(KeyCode.Tab))
    {
        // 找到当前聚焦的对象
        GameObject current = EventSystem.current.currentSelectedGameObject;
        for (int i = 0; i < tabOrder.Length; i++)
        {
            if (tabOrder[i].gameObject == current)
            {
                // 跳到下一个
                int next = (i + 1) % tabOrder.Length;
                tabOrder[next].Select();
                // 如果目标是 TMP_InputField,激活它
                var inputField = tabOrder[next].GetComponent<TMP_InputField>();
                if (inputField != null)
                    inputField.ActivateInputField();
                break;
            }
        }
    }
}
相关推荐
南無忘码至尊2 小时前
Unity学习90天-第3天-认识触屏输入(手游基础)并完成手机点击屏幕,物体向点击位置移动
学习·unity·c#·游戏引擎·游戏开发
南無忘码至尊2 小时前
Unity学习90天-第3天-认识C# 集合与常用类并实现生成随机位置的 10 个立方体
学习·unity·c#
mxwin12 小时前
Unity URP 下抓取当前屏幕内容实现扭曲、镜子与全局模糊效果
unity·游戏引擎·shader
南無忘码至尊17 小时前
Unity学习90天-第2天-认识Unity生命周期函数并用 Update 控制物体移动,FixedUpdate 控制物理
学习·unity·游戏引擎
小林up21 小时前
【Unity URP源码阅读1】ColorGradingLUT
unity·游戏引擎
风酥糖1 天前
Godot游戏练习01-第27节-升级选项选择生效
游戏·游戏引擎·godot
郝学胜-神的一滴1 天前
[简化版 GAMES 101] 计算机图形学 04:二维变换上
c++·算法·unity·godot·图形渲染·unreal engine·cesium
南無忘码至尊1 天前
Unity学习90天-第2天-认识键盘 / 鼠标输入(PC)并实现WASD 移动,鼠标控制物体转向
学习·unity·c#·游戏开发
星夜泊客1 天前
unity 海底海洋资源OceanEnviromentPackUrp材质丢失修正
unity·游戏引擎·材质