【UE5 C++ 學習日志】01. UEnhancedInput

2023-09-18 23:00:48

UE5 提供了一種對複雜輸入處理或運行時重新映射按鍵增强輸入插件。此插件向上兼容UE4的默認輸入系統,并可以實現径向死区、同时按键、上下文输入和优先级安排等多種功能。

核心概念:
(1)Input Actions:

Input Action 代表角色需要做出的任意動作,例如跳躍或攻擊等等。同時還可以代表輸入的狀態,例如按鍵按下時保持衝刺狀態。

(2)Input Mapping Contexts

Input Mapping Context将用户输入映射到输入动作,并可以动态地为每个用户添加、移除或安排优先次序。一下是UE的官方文檔介紹。

输入映射上下文(Input Mapping Context)描述一个或多个输入动作的触发规则。输入映射上下文的基本结构是一个层级结构,最上层包含一组输入动作。在输入动作层下面,是可以触发各个输入动作的用户输入,例如按键、按钮和方向轴。

底层包含各个用户输入的输入触发器和输入修饰器列表,可用于确定如何筛选或处理输入的原始值,以及它必须满足哪些限制才能驱动顶层的输入动作。

输入可以有多个输入修饰器和输入触发器。这些修饰器和触发器会按照其在列表中的顺序被计算;这对于输入修饰器尤其重要,因为修饰器将使用每个步骤的输出作为下个步骤的输入。

(3)Modifiers

Modifiers 用于修改来自用户设备的原始输入值。例如negate修改器可以改變輸入值1成爲-1.

输入修饰器是一种预处理器,能够修改UE5接收到的原始输入值,然后再将其发送给输入触发器(Input Trigger)。增强输入插件随附多种输入修饰器,可以执行各种任务,例如更改轴顺序、实现"死区"、将轴输入转换为世界空间以及其他功能。

在输入映射上下文中,每个与输入动作关联的输入,都会经历用户定义的一系列输入修饰器,然后再进入该输入的输入触发器。输入修饰器会按照其顺序依次应用,每个输入修饰器的输出值都会成为下一个修饰器的输入值。

你可以選擇使用UE提供的一系列修改器例如Negate, DeadZone 和 Swizzle Input Axis Value。也可以添加自己的modifier。

(4)Triggers

使用经过修饰器修改的输入值,或者使用其他输入动作的输出值,来确定是否激活输入动作。输入映射上下文中的输入动作,其每个输入都可以有一个或多个触发器。例如,拍摄照片时,可能需要用户按住鼠标左键约0.25秒,同时,还有一个用于控制摄像机拍照方向的输入动作处于激活状态。

使用方法:
(1)启用插件:

在编辑器中打开 编辑(Edit) 下拉菜单并选择 插件(Plugins),即可启用此插件。在插件列表的 输入(Input) 分段中,找到并启用增强输入插件,然后重启编辑器。

(2)添加(Input Actions):

我們可以在UE Content/ThirdPerson/Input/Actions 文件夾下(單擊鼠標右鍵->Input->Input Action)。

在雙擊打開創建的(Input Actions)之後,可以通過設置(Value Type)來選擇一種返回的輸入值。(例如:跳躍action選擇對應默認的bool,而移動action涉及多個方向,則使用Axis2D)

(3)添加(Input Mapping Context):

我們可以在UE Content/ThirdPerson/Input 文件夾下(單擊鼠標右鍵->Input->Input Mapping Context)。雙擊可以綁定相應的Action到按鍵。圖片提供了移動Action和衝刺Action兩個例子。

(4)C++ 添加Action和Action Mapping Context到character:
// ProjectDCharacter .h

UCLASS(config=Game)
class AProjectDCharacter : public ACharacter
{
	GENERATED_BODY()

	/** Player controller reference */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = PlayerController, meta = (AllowPrivateAccess = "true"))
	APlayerController* PlayerController;

	/** Move Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* MoveAction;
protected:

	// APawn interface
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	// To add mapping context
	virtual void BeginPlay();

	/** Called for movement input */
	void Move(const FInputActionValue& Value);
}



// ProjectDCharacter .cpp

void AProjectDCharacter::BeginPlay()
{
	// Call the base class  
	Super::BeginPlay();

	PlayerController = Cast<APlayerController>(Controller);

	if (PlayerController)
	{
		//Add Input Mapping Context
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}
}

// Input binding
void AProjectDCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	// Set up action bindings
	if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
		// Moving
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AProjectDCharacter::Move);
	}
	else
	{
		UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
	}
}

void AProjectDCharacter::Move(const FInputActionValue& Value)
{
	// input is a Vector2D
	FVector2D MovementVector = Value.Get<FVector2D>();

	if (Controller != nullptr)
	{
		const FVector ForwardDirection = FVector(0.0, 1.0, 0.0);
		const FVector RightDirection = FVector(1.0, 0.0, 0.0);

		AddMovementInput(ForwardDirection, MovementVector.X);
		AddMovementInput(RightDirection, MovementVector.Y);
	}
}
(5) 綁定到CharacterBlueprint:

由於我使用的是UE創建的Thirdperson C++項目模板,我的character是有默認的藍圖的,因此只需要在藍圖中添加Input Action 指向的實例。

更多推荐

软件测试面试题 —— 整理与解析(3)

😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。📡主页地址:【Austin_zhai】🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。阅读目录1.接上回2.题目解析2.1请介

day14 02-Shell控制条件与循环详解

文章目录1.9.条件控制1.9.1.if条件语句-单分支1.9.2.if条件语句-多分支1.9.3.case1.10.循环1.10.1.for循环1.10.2.while循环1.9.条件控制1.9.1.if条件语句-单分支if-else语句,是非常简单,也是非常基础的条件语句。在Java中我们已经非常熟悉它的逻辑了,在

乒乓球廉价底板和套胶对比分析

手机最近没办法写微博,在火车上没事,折腾了下,升级后可以了,我近期又打了很多套胶,我还录了段粘拍的视频一会分享。这次我还是说几款底板和套胶的感受,最近买了dj200不带A底板,paliocc和银河cn2,套胶方面用的更多一一解读。首先说为什么买dj200底板,作为我这种低端用户来说,我认为dj200就是我的天花板,这个

前后端分离毕设项目之基于springboot+vue的笔记记录分享网站设计与实现(内含源码+文档+部署教程)

博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久,选择我们就是选择放心、选择安心毕业✌🍅由于篇幅限制,想要获取完整文章或者源码,或者代做,拉到文章底部即可看到个人VX。🍅2023年-2024年最新计算机毕业设计本科选题大全汇总感兴趣的可以先收藏

Docker 的使用

一、Docker的作用和优势软件集装箱化平台,可让开发者构建应用程序时,将它与环境一起打包到一个容器中,发布应用到任意平台中。能在单台机器上运行多个Docker微容器,而每个微容器里都有一个微服务或独立应用,如:Tomcat运行在一个Docker,MySQL运行在另外一个Docker,两者可以运行在同一个服务器。1.1

QT实现qq登录

1、登录界面头文件#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>#include<QMessageBox>#include<QDebug>#include"second.h"//第二个界面头文件#include"third.h"//注册界面头文件#

go语言常用标准库(Time)

go语言常用标准库(Time)1、Time时间和日期是我们编程中经常会用到的,本文主要介绍了Go语言内置的time包的基本用法。1.1.1.time包time包提供了时间的显示和测量用的函数。日历的计算采用的是公历。1.1.2.时间类型time.Time类型表示时间。我们可以通过time.Now()函数获取当前的时间对

stable diffusion的微调和lora微调代码版本

目前业界主流的sd训练基本都是基于diffusers和ldm的,这是huggingface的训练库,后者是stabilityai在compvis等机构的基础上完善的,我目前工作上推理一般采用webui架构,训练采用diffusers,因此需要把webui的ckpt或者safetensors转成huggingface形式

RabbitMQ消息可靠性(二)-- 消费者消息确认

一、消费者消息确认是什么?在这种机制下,消费者在接收到消息后,需要向RabbitMQ发送确认信息,告知RabbitMQ已经接收到该消息,并已经处理完毕。如果RabbitMQ没有接收到确认信息,则会将该消息重新加入队列,等待其他消费者继续处理。消费者消息确认机制能够保证消息不会因为消费者宕机或其他原因而丢失,从而保证了消

Polygon ID架构

1.引言身份分类:1)物理身份:如驾照、身份证等。2)数字身份:又分为:2.1)中心化数字身份:如传统的中心化web2网站账号密码登录。2.2)联邦身份:如通过facebook或谷歌账号授权登录不同网站或应用。2.3)去中心化自治身份:自己持有并管理数据。可有选择的公开或证明,具备隐私属性。PolygonID架构中主要

大模型应用发展的方向|代理 Agent 的兴起及其未来(上)

“介绍了人工智能代理的历史渊源与演进,接着探讨了大型语言模型(LLMs)的发展,以及它们在知识获取、指令理解、泛化、规划和推理等方面所展现出的强大潜力。在此基础上,提出了一个以大型语言模型为核心的智能代理概念框架,该框架包括大脑、感知和行动这三个主要组成部分。”01—长期以来人工智能领域一直追求与人类水平相当甚至超越人

热文推荐