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
相关产品推荐
相关产品推荐

