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 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19941 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了2 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品2 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘2 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记3 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端
糖果店的幽灵3 小时前
langgraph的 MessagesState 解读
java·开发语言·人工智能·windows·langgraph
极光代码工作室4 小时前
基于SpringBoot的在线博客系统
java·springboot·web开发·后端开发
我是唐青枫4 小时前
Java Spring Security 实战详解:从登录认证到 JWT 权限控制
java·spring
ihuyigui5 小时前
海外签收通知短信接口
android·java·开发语言·前端·数据库·后端