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其实用的是最多的

相关推荐
程序猿大帅4 小时前
别再只当调包侠了:用 Spring AI 落地 Function Calling,我被大模型硬生生砸出了三个大坑
java
程序员晓琪5 小时前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly5 小时前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
众少成多积小致巨6 小时前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
东坡白菜6 小时前
破局全栈:前端开发的Java入门实战记录—JPA(2)
java·后端
SimonKing12 小时前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
用户2986985301412 小时前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
小bo波1 天前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
nanxun8862 天前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103512 天前
Day01 | Java 基础(Java SE)
java