[UnityTest]按钮输入未识别但[Test]正常问题咨询
Unity InputSystem 1.4.4 协程测试输入不生效问题解决
问题核心
用[Test]属性测试Gamepad/键鼠输入全部正常,但换成[UnityTest]协程测试时,调用Set(_gamepad.rightShoulder, 1)或Press(_gamepad.rightShoulder)都无法让游戏识别到按钮按下,等待WaitForFixedUpdate后依然无效,换回普通[Test]则恢复正常。
原因分析
这是因为InputTestFixture在协程测试场景下,输入模拟状态不会自动同步到游戏的帧循环逻辑里。普通[Test]是同步执行,InputSystem的模拟状态会立刻生效;但UnityTest是基于协程的帧异步推进,默认的WaitForFixedUpdate只会推进物理帧,不会主动触发InputSystem的状态更新。
解决方法
方法1:设置输入后主动更新InputSystem
在模拟输入后调用InputSystem.Update(),强制同步输入状态,再等待帧执行:
[UnityTest] public IEnumerator Shoot() { var bullets = GameObject.FindGameObjectsWithTag("Bullet"); Assert.IsEmpty(bullets); // 模拟输入并主动同步 Set(_gamepad.rightShoulder, 1); InputSystem.Update(); // 等待一帧让游戏逻辑(比如Update/FixedUpdate)执行 yield return null; bullets = GameObject.FindGameObjectsWithTag("Bullet"); Assert.IsNotEmpty(bullets); }
方法2:使用InputTestFixture的Tick方法推进输入帧
InputTestFixture提供了Tick方法,可以直接推进InputSystem的帧更新,同时带动游戏逻辑执行:
[UnityTest] public IEnumerator Shoot() { var bullets = GameObject.FindGameObjectsWithTag("Bullet"); Assert.IsEmpty(bullets); Set(_gamepad.rightShoulder, 1); // 推进1帧InputSystem更新,等价于模拟一帧的输入流程 Tick(1); bullets = GameObject.FindGameObjectsWithTag("Bullet"); Assert.IsNotEmpty(bullets); yield return null; }
方法3:针对FixedUpdate逻辑的特殊处理
如果你的射击逻辑写在FixedUpdate里,需要同步推进物理帧:
[UnityTest] public IEnumerator Shoot() { var bullets = GameObject.FindGameObjectsWithTag("Bullet"); Assert.IsEmpty(bullets); Set(_gamepad.rightShoulder, 1); InputSystem.Update(); // 模拟一次FixedUpdate的物理模拟 Physics.Simulate(Time.fixedDeltaTime); bullets = GameObject.FindGameObjectsWithTag("Bullet"); Assert.IsNotEmpty(bullets); yield return new WaitForFixedUpdate(); }
额外注意事项
确保你的测试类正确继承了InputTestFixture,并在SetUp中初始化输入设备:
public class ShootingInputTests : InputTestFixture { private Gamepad _gamepad; [SetUp] public override void Setup() { base.Setup(); // 初始化虚拟游戏手柄 _gamepad = InputSystem.AddDevice<Gamepad>(); } }
这不是InputTestFixture的已知限制,只是协程测试时需要手动处理InputSystem的状态同步,弥补异步帧推进和输入模拟之间的衔接缺口。
内容的提问来源于stack exchange,提问作者Narc0t1CYM
相关产品推荐
相关产品推荐

