Unity的InputSystem常见问题和疑惑解答

一、获取InputAction的几种方式

假设我们现在已经配置好了一个最简单的InputAction,如图1

【图1】

方法1.声明public InputActionAsset对象,通过脚本挂上去

代码如下:

csharp 复制代码
public class test1 : MonoBehaviour
{
    public InputActionAsset ass;

    private void Start()
    {
        InputActionMap map = ass.FindActionMap("map1");
        InputAction ac = map.FindAction("KM");
        ac.Enable();    //注意必须要调用Enable!

        ac.started += St;
        ac.performed += Perf;
        ac.canceled += Cancel;
    }

    private void St(CallbackContext context)
    {
        Debug.Log("Start");
    }

    private void Perf(CallbackContext context)
    {
        Debug.Log("Perform");
    }

    private void Cancel(CallbackContext context)
    {
        Debug.Log("Cancel");
    }
}

方法2.通过生成代码的方式获取

Aseets中勾选Generate C# Class,然后Apply,就会生成一个类,之后可以直接用这个类,代码如下

csharp 复制代码
public class test1 : MonoBehaviour
{
    Ac1 ac1; //使用前要先new一个对象
    private void Start()
    {
        ac1 = new Ac1();
        ac1.Enable();  //注意必须要调用Enable!
        InputAction ac = ac1.map1.KM;

        ac.started += St;
        ac.performed += Perf;
        ac.canceled += Cancel;
    }

    private void St(CallbackContext context)
    {
        Debug.Log("Start");
    }

    private void Perf(CallbackContext context)
    {
        Debug.Log("Perform");
    }

    private void Cancel(CallbackContext context)
    {
        Debug.Log("Cancel");
    }
}

关于这里为什么要将ac1放在外面声明,而不是在Start中声明对象,我测试发现,如果放在Start中声明,Ac1析构函数会被提前调用,导致报错

方法3.通过InputActionReference挂上去

csharp 复制代码
public class test1 : MonoBehaviour
{
    public InputActionReference acRef;
    private void Start()
    {
        InputAction ac = acRef.action;
        ac.Enable();  //注意必须要调用Enable!

        ac.started += St;
        ac.performed += Perf;
        ac.canceled += Cancel;
    }

    private void St(CallbackContext context)
    {
        Debug.Log("Start");
    }

    private void Perf(CallbackContext context)
    {
        Debug.Log("Perform");
    }

    private void Cancel(CallbackContext context)
    {
        Debug.Log("Cancel");
    }
}

把Assets里的某个Action拖上去就行了

总结这三种方法的区别:

方法1其实很少用到,因为他是通过字符串查找的,性能就不如其他两种方法,并且如果配置改了名字,那字符串也得跟着改

方法2和方法3的最大区别,就是对象实例的数量问题

方法2虽然需要new一个对象,但是其实全局只应该有一个map,在使用action时,其实所有地方用的都是一个action。如果另外一个地方再new了对象,并且调用Enable时,就会报错

方法3每次拖拽一个进去,都是一个新的实例,这就不会相互影响,并且他可以只考虑这个Action的逻辑,写代码时不用看到其他的Action。所以方法3其实用的是最多的

相关推荐
日月云棠1 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840822 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide2 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家2 天前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺2 天前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java
用户908324602732 天前
Spring Boot + MyBatis-Plus 多租户实战:从数据隔离到权限控制的完整方案
java·后端
桦说编程2 天前
实战分析 ConcurrentHashMap.computeIfAbsent 的锁冲突问题
java·后端·性能优化
程序员清风2 天前
用了三年AI,我总结出高效使用AI的3个习惯!
java·后端·面试
beata2 天前
Java基础-13: Java反射机制详解:原理、使用与实战示例
java·后端
用户0332126663672 天前
Java 使用 Spire.Presentation 在 PowerPoint 中添加或删除表格行与列
java