自定义 Modifier 与 Trigger(C++)

内置不够用时,两者都是可 C++ 定义的资产类。

自定义 Modifier

UCLASS(Blueprintable, EditInlineNew, meta=(DisplayName="Ramp Up Over Time"))
class URampUpModifier : public UInputModifier
{
    GENERATED_BODY()
public:
    UPROPERTY(EditAnywhere) float RampDuration = 1.f;

    // 输入值 → 加工后的值
    virtual FInputActionValue ModifyRawValue_Implementation(
        const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override
    {
        // 按住越久值越大(线性爬升),适合"持续开火递增"类手感
        Elapsed += DeltaTime;
        float T = FMath::Clamp(Elapsed / RampDuration, 0.f, 1.f);
        return CurrentValue.GetMagnitude() * T;
    }
};

自定义 Trigger

UCLASS(Blueprintable, EditInlineNew, meta=(DisplayName="Triple Tap"))
class UTripleTapTrigger : public UInputTrigger
{
    GENERATED_BODY()
public:
    UPROPERTY(EditAnywhere) float MaxInterval = 0.5f;

    virtual ETriggerState UpdateState_Implementation(
        const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime) override
    {
        bool bPressed = ModifiedValue.GetMagnitude() > 0.f;
        if (bPressed && !bWasPressed)   // 新按下
        {
            float Now = PlayerInput->GetWorld()->GetTimeSeconds();
            if (Now - LastTapTime <= MaxInterval) TapCount++;
            else TapCount = 1;
            LastTapTime = Now;
            if (TapCount >= 3) { TapCount = 0; return ETriggerState::Triggered; }
        }
        bWasPressed = bPressed;
        return ETriggerState::None;
    }
};

两个要点

  1. 自定义触发器/修饰器在内容浏览器可"新建"(蓝图可做子类),策划也能用;
  2. 行为推荐做成无状态可复用(用实例的 UPROPERTY 存状态时注意:每个映射行有独立实例,互不污染)。

一个常被点名的开源生态补充

社区有 "Enhanced Input Combo" 之类的插件实现"搓招"(上上下下拳),若项目有格斗类需求,可找现成或在自定义 Trigger 上扩展(原理就是上面的 UpdateState 记录序列)。

本章小结

  • Modifier 重写 ModifyRawValue_Implementation,Trigger 重写 UpdateState_Implementation。
  • 自定义资产可被蓝图再继承,策划可直接使用。
  • 搓招类需求 = 在 Trigger 里记录按键序列,社区有现成插件参考。