• 阿赵UE引擎C++编程学习笔记——用户输入监听


      大家好,我是阿赵。
      作为一个游戏引擎,监听用户输入是比较常用的功能,这次学习一下怎样在UE引擎监听用户的输入。

    一、 通过输入设置指定

      这个是通过在输入设置里面指定某些操作,并映射对应的输入指令。这方面Unity引擎也是有类似的功能。UE其实比Unity更先进,除了按钮输入和轴输入的映射,还有语音输入的映射。不过语音映射我暂时没用过,这次先来看看操作映射和轴映射。
      在编辑——>项目设置里面,找到输入的页签
    在这里插入图片描述

      然后在输入的页签里面,就可以看到操作映射和轴映射的选项了:
    在这里插入图片描述

    1、 绑定操作映射

    1.设置面板的操作:

      简单来说,就是通过按某个按键,触发某个行为
    在这里插入图片描述

      点击操作映射旁边的加号,可以创建一个新的操作映射,然后需要指定

    (1) action名称

      这个action名称很重要,之后会通过这个action名称作为事件名称,来触发输入。

    (2) 输入的按键

      输入什么按钮可以触发这个action事件。可以通过右边的组合键勾选,来组合输入。
    如果一个action不止一种输入方式,可以点击action名称旁边的加号,添加多几个输入的按钮
    在这里插入图片描述

    在这里插入图片描述

      比如我这里,设置了一个叫做OnFire的按钮,可以通过键盘的F键或者R键来触发。
    在这里插入图片描述

    2. 触发事件的方式:

    (1) 蓝图触发

      在蓝图里面直接搜索刚才OnFire的action名称,就能看到这个OnFire的事件节点
    在这里插入图片描述

      节点里面可以有2个触发条件,分别是按下和松开按钮:
    在这里插入图片描述

    (2) C++触发

      绑定输入事件:
      可以在begin方法里面进行绑定

    	auto controller = this->GetWorld()->GetFirstPlayerController();
    	UInputComponent* comp = controller->InputComponent;
    comp->BindAction("OnFire", IE_Pressed, this, &ALevel1GameModeBase::OnFireAction);
    

      然后回调方法:

    int fireCount = 0;
    void ALevel1GameModeBase::OnFireAction()
    {
    	fireCount++;
    	GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White,FString::Printf( TEXT("OnFire%d"),fireCount));
    }
    

    按钮状态可选枚举比蓝图的要多,有以下这些:

    enum EInputEvent : int
    {
    	IE_Pressed              =0,
    	IE_Released             =1,
    	IE_Repeat               =2,
    	IE_DoubleClick          =3,
    	IE_Axis                 =4,
    	IE_MAX                  =5,
    };
    

    2、 绑定轴映射

    1.设置操作

      简单来说,就是类似于方向键的XY轴输入,触发某个行为。
      同样回到项目设置的输入页签,点击轴映射旁边的加号,添加轴映射事件。
      由于细节操作和上面的操作映射差不多的,所以我就不再啰嗦。这里我新增了一个叫做OnMoveX的轴映射事件,然后键盘A键会触发这个轴到-1,D键会触发这个轴到1,模拟一般FPS游戏的左右行走的输入。然后再添加了一个鼠标X的输入,这个就不需要指定-1了,因为鼠标X移动本身就是有正负的。
    在这里插入图片描述

    2.触发事件

    (1) 蓝图触发

      同样搜索刚才指定的OnMoveX的action名称,就可以看到对应的事件节点了。
    在这里插入图片描述

      这个节点和刚才的操作输入的节点不一样,它没有多种状态输出,而是一直输出的。意思是,不论我们是否输入了按键,这个轴映射都会不停的触发,只是在没有输入之前,它的value回返回0。
    在这里插入图片描述

    (2) C++ 触发

      和上面的操作映射一样,轴映射同样需要绑定

    	auto controller = this->GetWorld()->GetFirstPlayerController();
    	UInputComponent* comp = controller->InputComponent;
    comp->BindAxis("OnMoveX", this, &ALevel1GameModeBase::OnMoveX);
    

      但需要注意的是,轴映射的回调方法是有参数的,参数和上面蓝图节点是一样的,是一个Axis Value,就是这个轴当前输入的值。和蓝图一样,这个回调不论是否输入,都会回调的,只是没有输入的时候,回调值是0.

    void ALevel1GameModeBase::OnMoveX(float val)
    {
    	GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White, FString::Printf(TEXT("OnMoveX:%f"), val));	
    }
    

    值得注意的是,这种绑定了操作映射或者轴映射的操作,是存在唯一性的,比如在C++里面绑定了新的回调方法,那么本身在蓝图上的InpuAction,就不会再收到绑定的操作了。结果就是按下按键时,C++这边会收到输入事件,但蓝图那边不会响应。

    二、 监听固定按钮

      如果不想在项目设置的输入里面指定action也能得到输入监听,也是有办法的。

    1、 蓝图

    1. 使用PlayerController节点

      在使用GetPlayerController得到控制器之后,可以用Is Input Key Down之类的节点,来判断是否按下某个键。需要注意的是,这个不是一个流程方法,所以要找带有空心三角形的节点来连接流程来触发。
    在这里插入图片描述

    2. key节点

    通过Key节点,可以监听输入某个按钮。可以搜索keyboard events,或者直接输入某个键盘的键:
    在这里插入图片描述
    触发事件有按下和弹起两个状态
    在这里插入图片描述

    也可以使用Debug Key,不过这个方法是仅限开发使用的,也就是说只能用于调试,不能用于正式环境。
    在这里插入图片描述

    2、C++

    1.使用PlayerController

      类似于Unity在Update里面判断按键输入的操作,在Tick里面,先获取PlayerController,然后再通过IsInputKeyDown方法,判断是否输入了某个key

    void ALevel1GameModeBase::Tick(float deltaTime)
    {
    if(this->GetWorld()->GetFirstPlayerController()->IsInputKeyDown(EKeys::J))
    	{
    		GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White, TEXT("input:J"));
    	}
    }
    

    IsInputKeyDown是监听按钮按下,但会有重复触发的问题,也可以换成WasInputKeyJustReleased,检查按钮弹起时触发一次

    if(this->GetWorld()->GetFirstPlayerController()->WasInputKeyJustReleased(EKeys::J))
    {
    }

    2.使用iostream

      同样是在Tick里面判断按钮,但这个是C++原生的调用io的方法。估计跨平台不一定能用,但可以当做是蓝图里面的debug key方法来用吧,其实也没太大必要,用PlayerController就可以了。

    #include
    #include
    #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
    
    void ALevel1GameModeBase::Tick(float deltaTime)
    {
    	if (KEY_DOWN('Z'))
    	{
    		GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White, TEXT("input:Z"));
    	}
    }
    
  • 相关阅读:
    elasticsearch的索引库操作
    一文了解循环神经网络
    spring-boot
    【强化学习论文合集】IJCAI-2022 强化学习论文 | 2022年合集(五)
    JavaScript中迭代:For循环
    【AWS】AI 代码生成器—Amazon CodeWhisperer初体验 | 开启开挂编程之旅
    spring6-IOC容器
    c#委托、lambda、事件
    【FreeRTOS(二)】任务优先级
    MySQL基本操作和基于MySQL基本操作的综合实例项目
  • 原文地址:https://blog.csdn.net/liweizhao/article/details/139132631