You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity自动化UI测试中输入事件未注册问题排查

问题:Unity自动化UI测试无法触发角色移动

我正在Unity中编写自动化UI测试脚本,需求是模拟鼠标点击指定位置,等待角色移动到目标点后记录位置(后续将添加断言验证角色与点击位置的距离)。测试运行无报错,但无法驱动角色移动;但在Play模式下,点击地图任意位置角色均可正常移动。

测试运行时,角色移动脚本仅持续打印"A",鼠标点击和Tab键输入均未被注册,但Play模式下这些操作都能正常触发对应日志打印。

测试脚本

[UnityTest]
public IEnumerator TestCharacterMovement()
{
    //UnityEngine.Debug.Log(Time.timeScale); //=1
    mouse = InputSystem.AddDevice<Mouse>();
    SceneManager.LoadScene("charactercontroller");
    yield return new WaitForSeconds(1f);

    character = GameObject.Find("Copy_of_JPEG_Page_22-removebg-preview");
    yield return new WaitForSeconds(1f);
    Assert.IsTrue(character != null);

    //tried 1, 10, and 100 here for difference in x
    Vector3 clickPosition = new Vector3(character.transform.position.x + 1f, character.transform.position.y, character.transform.position.z);
    Camera camera = GameObject.Find("Main Camera").GetComponent<Camera>();
    Vector3 screenpos = camera.WorldToScreenPoint(clickPosition);

    Set(mouse.position, screenpos);
    yield return new WaitForSeconds(1f);
    Click(mouse.leftButton);
    UnityEngine.Debug.Log(mouse.position.x.ReadValue());
    UnityEngine.Debug.Log(mouse.position.y.ReadValue());

    yield return new WaitForSeconds(2f);
    yield return null;
}

角色移动脚本

namespace MovementScript
{
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using UnityEngine;

    public class movement : MonoBehaviour
    {
        public float speed = 5f;
        public Vector3 target;

        void Start()
        {
            target = transform.position;
        }

        void Update()
        {
            UnityEngine.Debug.Log("A");
            if (Input.GetMouseButtonDown(0))
            {
                target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                UnityEngine.Debug.Log("B");
                target.z = transform.position.z;
                target.y = transform.position.y;
            }
            transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
            if (target.x > transform.position.x)
            {
                transform.rotation = Quaternion.Euler(new Vector3(0, 180, 0));
            }
            else if (target.x < transform.position.x)
            {
                transform.rotation = Quaternion.Euler(new Vector3(0, 0, 0));
            }

            if (Input.GetKeyDown(KeyCode.Tab))
            {
                UnityEngine.Debug.Log("tab");
            }
        }
    }
}

问题原因与解决方案

核心问题

测试脚本使用**新输入系统(Input System Package)的API模拟输入,但角色移动脚本依赖的是旧输入系统(UnityEngine.Input)**的API。两套输入系统完全独立,新输入系统的模拟信号无法触发旧输入系统的回调,导致测试中的鼠标操作无法被角色脚本识别。

解决方案1:统一使用旧输入系统模拟输入

修改测试脚本,改用旧输入系统的官方测试模拟工具(需引用UnityEditor.TestTools命名空间):

using UnityEditor.TestTools;

[UnityTest]
public IEnumerator TestCharacterMovement()
{
    SceneManager.LoadScene("charactercontroller");
    yield return new WaitForSeconds(1f);

    character = GameObject.Find("Copy_of_JPEG_Page_22-removebg-preview");
    yield return new WaitForSeconds(1f);
    Assert.IsTrue(character != null);

    Vector3 clickPosition = new Vector3(character.transform.position.x + 1f, character.transform.position.y, character.transform.position.z);
    Camera camera = GameObject.Find("Main Camera").GetComponent<Camera>();
    Vector3 screenpos = camera.WorldToScreenPoint(clickPosition);

    // 模拟鼠标移动到目标位置
    Input.SetMousePosition(screenpos.x, screenpos.y);
    yield return new WaitForEndOfFrame();

    // 模拟鼠标左键按下并抬起
    InputSimulator.Instance.MouseButtonDown(MouseButton.Left);
    yield return new WaitForEndOfFrame();
    InputSimulator.Instance.MouseButtonUp(MouseButton.Left);

    UnityEngine.Debug.Log(Input.mousePosition.x);
    UnityEngine.Debug.Log(Input.mousePosition.y);

    yield return new WaitForSeconds(2f);
}

解决方案2:统一使用新输入系统

修改角色移动脚本,适配新输入系统API:

namespace MovementScript
{
    using UnityEngine;
    using UnityEngine.InputSystem;

    public class movement : MonoBehaviour
    {
        public float speed = 5f;
        public Vector3 target;
        private Mouse mouse;
        private Keyboard keyboard;

        void Start()
        {
            target = transform.position;
            mouse = Mouse.current;
            keyboard = Keyboard.current;
        }

        void Update()
        {
            UnityEngine.Debug.Log("A");
            if (mouse.leftButton.wasPressedThisFrame)
            {
                target = Camera.main.ScreenToWorldPoint(mouse.position.ReadValue());
                UnityEngine.Debug.Log("B");
                target.z = transform.position.z;
                target.y = transform.position.y;
            }
            transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
            
            if (target.x > transform.position.x)
            {
                transform.rotation = Quaternion.Euler(new Vector3(0, 180, 0));
            }
            else if (target.x < transform.position.x)
            {
                transform.rotation = Quaternion.Euler(new Vector3(0, 0, 0));
            }

            if (keyboard.tabKey.wasPressedThisFrame)
            {
                UnityEngine.Debug.Log("tab");
            }
        }
    }
}

同时调整测试脚本,使用当前激活的鼠标设备而非手动新增设备:

[UnityTest]
public IEnumerator TestCharacterMovement()
{
    SceneManager.LoadScene("charactercontroller");
    yield return new WaitForSeconds(1f);

    character = GameObject.Find("Copy_of_JPEG_Page_22-removebg-preview");
    yield return new WaitForSeconds(1f);
    Assert.IsTrue(character != null);

    Vector3 clickPosition = new Vector3(character.transform.position.x + 1f, character.transform.position.y, character.transform.position.z);
    Camera camera = GameObject.Find("Main Camera").GetComponent<Camera>();
    Vector3 screenpos = camera.WorldToScreenPoint(clickPosition);

    var mouse = Mouse.current;
    mouse.position.SetValue(screenpos);
    yield return new WaitForSeconds(1f);
    
    mouse.leftButton.SetValue(1);
    yield return new WaitForEndOfFrame();
    mouse.leftButton.SetValue(0);

    UnityEngine.Debug.Log(mouse.position.x.ReadValue());
    UnityEngine.Debug.Log(mouse.position.y.ReadValue());

    yield return new WaitForSeconds(2f);
}

内容的提问来源于stack exchange,提问作者Bayley Sapara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:40:10