找回密码
 立即注册
查看: 338|回复: 0

EnHanced Input

[复制链接]
发表于 2022-4-21 06:47 | 显示全部楼层 |阅读模式
EnHancedInput插件

EnHancedInout插件增加了更加复杂的输入
实现了更多的输入功能

使用EnHancedInput插件

使用EnhancedInput插件需要再编辑器插件中打开


在项目设置里找到输入(Input) =>默认类(Default Classes) 设置为EnhancedInput



主要功能

输入操作(Input Actions)

是Enhanced Input系统和项目代码之间的通信桥梁。输入操作可以是角色的任何交互操作,例如跳跃、开门。输入操作还能表示用户的输入状态,例如按住按钮让角色从行走变为奔跑状态。输入操作与原始输入(raw input)是相互独立的;输入操作无需知道是什么触发了它,但它知道其当前状态,并且最多能将输入值反应在三个维度上(三个独立浮点型数值)。例如,"拾取道具"操作可能只需要一个开/关状态,用于指示用户是否希望角色捡起某个对象,而"行走"操作可能需要两个轴来描述角色行走时的方向和速度。
创建输入操作





创建输入操作



InputAction 编辑

输入操作说明


  • Consume Input(输入穿透(是否影响更低优先级的输入))
  • Trigger when Paused(游戏暂停状态下是否触发)
  • Reserve All Mappings (输入不受高优先级的Mapping控制,需要先手动删除)
  • Value Type(输入类型)

    • Bool
    • Float
    • Vector2
    • Vector3

  • Triggers(输入触发器列表)
  • Modifiers(输入修饰符列表)
输入操作使用






  • Triggered:触发事件
  • Started:开始事件(可能也会Triggered)
  • OnGoing:处理中(需要Trigger列表有支持的Trigger)
  • Cancel:取消(需要Trigger列表有支持的Trigger)
  • Completed:完成 状态从Trigger->None
  • Action Value:(输入值,和InputAction.ValueType对应)
  • ElapsedTime:执行的时间
  • Trigger Seconds:触发的时间
  • Input Action:输入操作
输入映射上下文(Input Mapping Context)

负责将用户的输入映射成输入操作;它可以根据用户需求动态增减或调整优先级。你可以通过 增强输入本地玩家子系统(Enhanced Input Local Player Subsystem) 将一个或多个上下文应用到本地玩家身上,并调整它们的优先级,避免多个输入操作因为尝试读取同一输入而发生的冲突。一个常见情况是,某个按钮既可以用来打开场景中的门,又可以用来拾取背包中的道具。当角色靠近门时,你可以添加"开门"这个上下文。假如角色打开背包,你可以添加"选择道具"这个输入映射上下文,并且让它的优先级高于"开门"。这样,当角色站在门旁边时,仍然可以选择背包中的道具。当角色合上背包后,你可以删除"选择道具"上下文,让"开门"上下文生效。这样就能根据角色的环境来正确地解译用户的输入操作,不再需要在输入层面编写代码来区别对待开门和背包系统。
创建输入映射上下文






输入操作说明


  • Mappings(映射列表)

    • Input Action Asset(输入操作资产)
    • TArray<FEnhancedActionKeyMapping> Mappings;(按键映射列表)

      • FKey (按键绑定)
      • Triggers(输入触发器,决定是否触发Input Action(输入操作))
      • Modifiers(输入修饰符,将原始输入设备的值处理后发送到Triggers触发器)
      • IsPlayerMappable(bool值,是否公开到玩家绑定的按键?)
      • PlayerMappableOptions (上面的设置)

        • Name (名字)
        • Display Name (显示名字)
        • Display Category (分类)



  • Config

    • Description(映射列表说明)

使用输入映射




触发器(Triggers)

输入触发器决定了用户输入后是否会激活输入操作(Input Actions)
创建自己的输入触发器




输入触发器的类型


  • 显示(Explicit): 如果输入触发器成功,该类型将使输入成功。
  • 隐式(Implicit):如果输入触发器和所有其他隐式类型输入触发器成功,该类型将使输入成功。
  • 拦截器(Blocker):如果输入触发器成功,该类型将使输入失败。
输入触发器的状态

在处理用户输入后,触发器返回三种状态之一

  • 无(None):触发器状态未满足,失败
  • 进行中(OnGoing):部分满足,还在处理
  • 已触发(Triggered):全部满足
常见的触发器


  • 按下(Pressed)

    • Actuation Threshold (阈值)

  • 按住(Down)

    • Actuation Threshold

  • 抬起(Release)

    • Actuation Threshold

  • 按住多少时间(Hold)

    • Hold Time Threshold: 按住多久触发
    • Is One Shot:只触发一次?
    • Affected By Time Dilation:时间膨胀是否影响

  • 每隔一段时间触发(Pluse)

    • Trigger On Start:一开始就触发
    • Interval:间隔
    • Trigger Limit:最大次数
    • Affected By Time  Dilation:是否受时间膨胀影响
    • Actuation Threshold

  • 按住并抬起(HoldAndRelease)

    • Hold Time Threshold:多久触发
    • Affected By Time  Dilation:是否受时间膨胀影响
    • Actuation Threshold

  • 按下并快速释放(Tap)

    • Tap Release Time Threshold:按下抬起触发最长时间
    • Affected By Time  Dilation:是否受时间膨胀影响
    • Actuation Threshold

  • 其他触发器触发了触发此触发器(Chorded Action)

    • Chord Action :其他触发器
    • Actuation Threshold

  • 用户自定义触发器(Others)
输入修饰(Modifiers)

调整来自用户设备的原始输入的值。在输入映射上下文中,每个输入操作的原始输入可以绑定的任意数量的修饰符。
顾名思义,就是用来改编输入设备获取的输入值,经过一层一层的处理后,传给Trigger
创建自己的输入修饰




常见的修饰符


  • 死区(DeadZone):限制值的范围

    • 计算:取 -1~1 之间的值 (如果小于LowerThreshold 则为0)

FMath::Min(1.f, (FMath::Max(0.f, FMath::Abs(AxisVal) - LowerThreshold) / (UpperThreshold - LowerThreshold))) * FMath::Sign(AxisVal);


    • 最小阈值(Lower Threshold):低于这个值就为0 (需要比Up Threshold小)
    • 最大阈值(Up Threshold):大于Lower Threshold 的值根据 值域映射到 [0~1]
    • 类型(Type):计算类型

      • Axial:每个维度单独计算
      • Radial:合并一起计算


  • 缩放(Scalar)

    • Scalar:三维向量,每个维度的缩放比,bool类型不缩放

  • 反向(Negate)

    • X: X方向反向
    • Y: Y取反
    • Z: Z取反

  • 多帧平滑(Smooth)
FInputActionValue UInputModifierSmooth::ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime)
{
        uint8 SampleCount = 1;//KeyState->SampleCountAccumulator;        // TODO: Need access to axis sample count accumulator here.


// TODO: This could be fired multiple times if modifiers are badly set up, breaking sample count/deltatime updates.


if(AverageValue.GetMagnitudeSq() != 0.f)
{
                TotalSampleTime += DeltaTime;
                Samples += SampleCount;
}


if (DeltaTime < 0.25f)
{
if (Samples > 0 && TotalSampleTime > 0.0f)
{
// this is seconds/sample
const float AxisSamplingTime = TotalSampleTime / Samples;
check(AxisSamplingTime > 0.0f);


if (CurrentValue.GetMagnitudeSq() && SampleCount > 0)
{
                                ZeroTime = 0.0f;
if (AverageValue.GetMagnitudeSq())
{
// this isn't the first tick with non-zero mouse movement
if (DeltaTime < AxisSamplingTime * (SampleCount + 1))
{
// smooth mouse movement so samples/tick is constant
                                                CurrentValue *=  DeltaTime / (AxisSamplingTime * SampleCount);
                                                SampleCount = 1;
}
}


                                AverageValue = CurrentValue * (1.f / SampleCount);
}
else
{
// no mouse movement received
if (ZeroTime < AxisSamplingTime)
{
// zero mouse movement is possibly because less than the mouse sampling interval has passed
                                        CurrentValue = AverageValue.ConvertToType(CurrentValue) * (DeltaTime / AxisSamplingTime);
}
else
{
ClearSmoothedAxis();
}


                                ZeroTime += DeltaTime; // increment length of time we've been at zero
}
}
}
else
{
// if we had an abnormally long frame, clear everything so it doesn't distort the results
ClearSmoothedAxis();
}


// TODO: FortPlayerInput clears the sample count accumulator here!
//KeyState->SampleCountAccumulator = 0;


return CurrentValue;
}

  • 指数(Exponential)

    • 三维的指数(Curve Exponent)

      • 三个维度的指数,bool类型不参与运算


FInputActionValue UInputModifierResponseCurveExponential::ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime)
{
        FVector ResponseValue = CurrentValue.Get<FVector>();
switch (CurrentValue.GetValueType())
{
case EInputActionValueType::Axis3D:
                ResponseValue.Z = CurveExponent.Z != 1.f ? FMath::Sign(ResponseValue.Z) * FMath::Pow(FMath::Abs(ResponseValue.Z), CurveExponent.Z) : ResponseValue.Z;
//[[fallthrough]];
case EInputActionValueType::Axis2D:
                ResponseValue.Y = CurveExponent.Y != 1.f ? FMath::Sign(ResponseValue.Y) * FMath::Pow(FMath::Abs(ResponseValue.Y), CurveExponent.Y) : ResponseValue.Y;
//[[fallthrough]];
case EInputActionValueType::Axis1D:
                ResponseValue.X = CurveExponent.X != 1.f ? FMath::Sign(ResponseValue.X) * FMath::Pow(FMath::Abs(ResponseValue.X), CurveExponent.X) : ResponseValue.X;
break;
}
return ResponseValue;
};


  • 用户曲线(User Defined)

    • X曲线: X轴二维曲线资源
    • Y曲线: Y轴二维曲线资源
    • Z曲线: Z轴二维曲线资源

  • 使用FOV 缩放(FOV Scaling)

    • 缩放比例(FOVScale)
    • 类型(FOVScaling Type)

      • Standard


const float FOVAngle = PC->PlayerCameraManager ? PC->PlayerCameraManager->GetFOVAngle() : 1.f;
float Scale = FOVScale;
const float kPlayerInput_BaseFOV = 80.0f;
const float BaseHalfFOV = kPlayerInput_BaseFOV * 0.5f;
const float HalfFOV = FOVAngle * 0.5f;
const float BaseTanHalfFOV = FMath::Tan(FMath::DegreesToRadians(BaseHalfFOV));
const float TanHalfFOV = FMath::Tan(FMath::DegreesToRadians(HalfFOV));


check(BaseTanHalfFOV > 0.0f);
                        Scale *= (TanHalfFOV / BaseTanHalfFOV);
return CurrentValue * Scale;




      • UE4_BackCompat


const float FOVAngle = PC->PlayerCameraManager ? PC->PlayerCameraManager->GetFOVAngle() : 1.f;
float Scale = FOVScale;
Scale *= FOVAngle;
return CurrentValue * Scale;

  • 转到世界空间坐标 (WorldSpace)

    • 简单的把输入改成了Unreal的世界坐标空间的值 (x,y,z)=>(z,x,y)

  • 交换轴输入(SwizzleAxis)

    • YXZ: (x,y,z)=>(y,x,z)
    • ZYX: (x,y,z)=>(z,y,x)
    • XZY: (x,y,z)=>(x,z,y)
    • YZX: (x,y,z)=>(y,z,x)
    • ZXY: (x,y,z)=>(z,x,y)

  • 输入修饰集合(Collection)

    • Modifiers:输入修饰集合
    • Permit Value Type Modification:是否改变当前的输入(好像没啥软用)

  • Other:用户自定义的输入修饰,由蓝图创建出来

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-15 01:35 , Processed in 0.093461 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表