new in Unreal Engine 5.4: data validation quick fixes

  • a few days ago I got a really cool change into Unreal, which allows you to add quick fixes to any data validation warning/error you emit:

    a screenshot with a validation error in it; beneath the error there’s a hint that it may be fixed automatically, coupled with a link you can click on to fix the issue

    2024-02-07
  • you can get this change in…

    2024-02-07
    • Git commit 0a6de35a5beb8534e19579cf1058460b4eb2bc79

      2024-02-07
    • Perforce changelist 31126352

      2024-02-07
  • the API revolves around the UE::DataValidation::IFixer type. fixers are pieces of code that can fix your issues given their application conditions are met

    2024-02-07
    • the interface you have to implement is:

      struct IFixer
      {
          virtual EFixApplicability GetApplicability(int32 FixIndex) const = 0;
          virtual FFixResult ApplyFix(int32 FixIndex) = 0;
      }
      
      2024-02-07
      • for the curious cats among us: FixIndex is an arbitrary number that can be passed to FFixToken, to handle multiple different fixes with one fixer

        2024-02-07
    • first, the editor calls GetApplicability to know whether the fix can be applied

      2024-02-07
      • EFixApplicability::CanBeApplied should be returned if the fix can be applied at the moment

        2024-02-07
      • EFixApplicability::Applied should be returned if the fix has been applied and can no longer be applied anymore

        2024-02-07
      • EFixApplicability::DidNotApply should be returned if the fix was not applied and can no longer be applied anymore

        2024-02-07
    • then, if GetApplicability() returns EFixApplicability::CanBeApplied, ApplyFix is called to actually run the fix

      2024-02-07
      • this function is safe to assume the caller has ensured that the fix CanBeApplied and therefore need not do any extra validity checks

        2024-02-07
      • other than that it’s free to do whatever it wants

        2024-02-07
      • after a fix is applied, the fixer returns an FFixResult which is used to display a notification to the user informing them of the changes

        2024-02-07
    • fortunately you don’t have to define a new struct for each fix, and instead can use UE::DataValidation::TLambdaFixer together with the UE::DataValidation::MakeFix function for more convenience

      2024-02-07
  • once you have a fixer, you can display it in your (FTokenizedMessage-based) validation messages using FFixToken

    2024-02-07
    • minimal example:

      auto Message = FTokenizedMessage::Create(
          EMessageSeverity::Error,
          LOCTEXT(
              "FoundNoneEntries",
              "Found None entries in ability array."
              "Please remove them, otherwise they may cause crashes during runtime."
          )
      );
      Message->AddToken(
          UE::DataValidation::MakeFix(
              [this]
              {
                  Abilities.SetNum(Algo::RemoveIf(
                      Abilities,
                      [](const UGameplayAbility* Ability) { return Ability == nullptr; }
                  ));
                  return FFixResult::Success(LOCTEXT("NoneEntriesRemoved", "None entries have been removed"));
              }
          )
          ->CreateToken(LOCTEXT("RemoveNoneEntries", "Remove the None entries"))
      );
      Context.AddMessage(MoveTemp(Message));
      
      2024-02-07
  • the user can then apply a fix by clicking on it in the Message Log message that contains it

    2024-02-07
  • fixers can be freely stacked and composed - there are a few such layers available out of the box in the engine

    2024-02-07
    • the set is quite limited at the moment, but you’re free to create your own or contribute them to mainline Unreal ralsei_love

      2024-02-07
    • UE::DataValidation::FSingleUseFixer makes it so that your fix’s applicability becomes EFixApplicability::Applied after the user applies the fix

      2024-02-07
    • UE::DataValidation::FObjectSetDependentFixer makes it so that your fix becomes DidNotApply after the specified objects are deleted from memory

      2024-02-07
    • UE::DataValidation::FAutoSavingFixer tells the user to save any assets modified by the fix after it’s applied

      2024-02-07
    • UE::DataValidation::FValidatingFixer runs data validation on any assets modified by the fix after it’s applied

      2024-02-07
    • UE::DataValidation::FMutuallyExclusiveFixSet is actually not a fixer, but a fixer builder - you give it a set of fixers, and it will make it so that when one is applied, it becomes EFixApplicability::Applied, and the rest becomes EFixApplicability::DidNotApply - thus creating a set of mutually-exclusive fixes

      2024-02-07
    • you can refer to the DataValidationFixers.h header file for more documentation

      2024-02-07
  • all of this is going to be available in Unreal 5.4 sparkles

    2024-02-07