Skip to main content

Validation In C++

You have two main C++ extension paths.

Option 1: Subclass UEDInteractionConditionValidator

This is the best option for reusable rules that can be assigned in multiple places.

Example: Require a pawn tag

#pragma once

#include "CoreMinimal.h"
#include "Validation/EDInteractionConditionValidator.h"
#include "MyRequirePawnTagValidator.generated.h"

UCLASS(BlueprintType, EditInlineNew, DefaultToInstanced)
class UMyRequirePawnTagValidator : public UEDInteractionConditionValidator
{
GENERATED_BODY()

public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Validation")
FName RequiredTag = TEXT("CanInteract");

virtual void ValidateInteraction_Implementation(const FEDInteractionValidationContext& Context, FEDInteractionValidationResult& InOutResult) override;
};
#include "MyRequirePawnTagValidator.h"

#include "GameFramework/Pawn.h"

void UMyRequirePawnTagValidator::ValidateInteraction_Implementation(const FEDInteractionValidationContext& Context, FEDInteractionValidationResult& InOutResult)
{
Super::ValidateInteraction_Implementation(Context, InOutResult);

if (!InOutResult.bAllowInteraction)
{
return;
}

if (!IsValid(Context.InstigatorPawn) || !Context.InstigatorPawn->ActorHasTag(RequiredTag))
{
InOutResult.bAllowInteraction = false;
InOutResult.DenyReason = EEDInteractionDenyReason::SpecialCondition;
InOutResult.FailureMessage = FText::FromString(TEXT("Missing required pawn tag."));
}
}

Assign this validator in:

  • GlobalInteractionValidators
  • ValidationRules
  • ValidationRuleClasses for foliage

Option 2: Override the player component hook

Subclass UEDPlayerInteractionComponent and override:

  • ValidateInteractionSpecialConditions_Implementation(...)

This is useful for centralized rules.

void UMyPlayerInteractionComponent::ValidateInteractionSpecialConditions_Implementation(
const FEDInteractionValidationContext& Context,
FEDInteractionValidationResult& InOutResult)
{
Super::ValidateInteractionSpecialConditions_Implementation(Context, InOutResult);

if (!InOutResult.bAllowInteraction)
{
return;
}

if (bDisableAllSpecialInteractions)
{
InOutResult.bAllowInteraction = false;
InOutResult.DenyReason = EEDInteractionDenyReason::SpecialCondition;
InOutResult.FailureMessage = FText::FromString(TEXT("Interactions are currently disabled."));
}
}

Choosing between both approaches

Prefer a validator object when:

  • you want reuse
  • you want designers to assign/tune rules
  • the same rule applies to actors and foliage

Prefer the player component override when:

  • the rule is highly project-specific
  • it depends on player/controller state
  • you want one centralized decision point

Foliage support

The validation API is not actor-only.

When the target is foliage, FEDInteractionValidationContext includes:

  • bIsFoliageInstance = true
  • FoliageInstanceComponent
  • FoliageInstanceTransform
  • InteractionLocation
  • bHasFoliageData
  • FoliageData

That makes it practical to implement tool checks, progression checks, or harvesting rules for foliage instances.