Targeting Guide
Complete guide to implementing combat targeting using ElysPerceptionPlugin.
Overview
The targeting system builds on top of Perception via the UERPDomainComponent base class. UERPTargetingComponent provides eligibility validation using IERPTargetable interface and targeting rules, along with descriptor tracking.
Architecture:
- Perception: Evaluates candidates via configurable pipeline
- Domain (Targeting):
UERPTargetingComponentextendsUERPDomainComponent, validates eligibility - Presentation: Your implementation (UI indicators, lock-on camera, etc.)
Basic Setup
1. Configure Targeting Pipeline
On your PlayerController or Pawn, configure ERPPerceptionComponent:
Target Pipeline Settings:
- Channel Id:
Target - Default Sampling Range: 3000.0
- Sampler:
ERPSphereOverlapSampler- Trace Channel: Visibility
- Ignore Context Actor: check
- Filters:
ERPTargetableFilter - Scorers:
ERPDistanceScorer(normalize by range), Weight: 1.0ERPConeScorer(optional, for camera-aware targeting), Weight: 0.5
- Resolver:
ERPResolverBase(lowest score wins)
2. Add Targeting Component
Add ERPTargetingComponent to your PlayerController or Pawn:
- Channel Id:
Target(must match pipeline) - Rules: (optional instanced targeting rules)
3. Implement Targetable Interface
On target actors (enemies, NPCs, destructibles):
Blueprint:
- Class Settings -> Interfaces -> Add
ERPTargetable - Implement
Can Be Targeted By-> returntrue(or custom logic) - Optionally implement
Get Target Descriptor-> return aUERPTargetDescriptordata asset
C++:
class AYourEnemy : public ACharacter, public IERPTargetable
{
GENERATED_BODY()
public:
virtual bool CanBeTargetedBy_Implementation(AActor* TargetingActor) const override
{
return bIsAlive;
}
virtual UERPTargetDescriptor* GetTargetDescriptor_Implementation() const override
{
return TargetDescriptor; // Optional DataAsset
}
protected:
UPROPERTY(EditAnywhere) bool bIsAlive = true;
UPROPERTY(EditAnywhere) UERPTargetDescriptor* TargetDescriptor = nullptr;
};
4. Bind Events
// In BeginPlay
TargetingComponent->OnDomainCandidateChanged.AddDynamic(this, &AMyPC::OnTargetChanged);
TargetingComponent->OnDescriptorChanged.AddDynamic(this, &AMyPC::OnTargetDescriptorChanged);
Blueprint Example
Complete Targeting System
Components on PlayerController:
ERPPerceptionComponent(target pipeline configured)ERPTargetingComponent(channel: "Target")
Event Graph:
// Handle target change
Event: OnDomainCandidateChanged (Previous, New, ChannelId)
-> Set CurrentTarget = New
-> Branch: IsValid(New)
True:
-> Show Target Indicator Widget
-> Set Widget position to target actor
False:
-> Hide Target Indicator Widget
// Attack current target
Input Action: Attack
-> TargetingComp -> GetCurrentCandidate
-> IsValid?
True: -> Execute attack on target
False: -> Execute untargeted attack
Targeting Rules
Add instanced UERPTargetRule objects for composable validation:
UCLASS(Blueprintable, EditInlineNew)
class UMyTeamRule : public UERPTargetRule
{
GENERATED_BODY()
public:
virtual bool CanTarget_Implementation(AActor* Instigator, AActor* Target, FName ChannelId) const override
{
// Only target enemies (different team)
ITeamAgentInterface* InstigatorTeam = Cast<ITeamAgentInterface>(Instigator);
ITeamAgentInterface* TargetTeam = Cast<ITeamAgentInterface>(Target);
if (InstigatorTeam && TargetTeam)
{
return InstigatorTeam->GetGenericTeamId() != TargetTeam->GetGenericTeamId();
}
return true;
}
};
Pipeline Configurations
Distance-Only Targeting
Simple nearest-enemy targeting:
Sampler: ERPSphereOverlapSampler (range: 2000)
Filter: ERPTargetableFilter
Scorer: ERPDistanceScorer (weight: 1.0)
Resolver: ERPResolverBase
Camera-Aware Targeting
Prefers enemies near crosshair:
Sampler: ERPSphereOverlapSampler (range: 3000)
Filter: ERPTargetableFilter
Scorers:
- ERPDistanceScorer (weight: 1.0)
- ERPConeScorer (cone: 45 degrees, weight: 1.5)
Resolver: ERPResolverBase
Screen-Space Targeting
Lock-on to enemy nearest screen center:
Sampler: ERPSphereOverlapSampler
Filter: ERPTargetableFilter
Scorer: ERPViewportEllipseScorer (weight: 1.0)
- Enable bProvideViewportInfoWhenAvailable on PerceptionComponent
Resolver: ERPResolverBase
UERPTargetDescriptor
Target descriptors are UDataAsset-based objects that describe targeting properties:
UCLASS(BlueprintType)
class UERPTargetDescriptor : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly) FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly) TSoftObjectPtr<UTexture2D> Icon;
UPROPERTY(EditAnywhere, BlueprintReadOnly) FGameplayTagContainer TargetTags;
UPROPERTY(EditAnywhere, BlueprintReadOnly) TMap<FName, TObjectPtr<UObject>> PresentationHints;
};
Use descriptors to drive UI without coupling to specific actor types.
Widget Integration
The plugin provides UERPTargetingWidgetBase for targeting UI (reticles, lock-on indicators, info panels).
| Pattern | Description | Key Hooks |
|---|---|---|
| Target Reticle | Lock-on marker positioned on target | OnTargetActiveChanged, tick for positioning |
| Target Info Panel | Nameplate with name, icon, health | OnDescriptorUpdated, OnTargetActorChanged |
Quick wiring (presenter on your PlayerController):
Event: OnDomainCandidateChanged (Previous, New, ChannelId)
-> TargetWidget -> SetTargetActor(New)
-> TargetWidget -> SetTargetActive(IsValid(New))
Event: OnDescriptorChanged (Candidate, Descriptor, ChannelId)
-> TargetWidget -> UpdateFromDescriptor(Descriptor)
For complete step-by-step walkthroughs including screen-space positioning, descriptor-driven styling, and health bar integration, see the Widget Guide.
Compared to ChannelListenerComponent
| Feature | ERPTargetingComponent | ERPChannelListenerComponent |
|---|---|---|
| Eligibility validation | IERPTargetable + Rules | None |
| Descriptor tracking | Yes | No |
| Base class | UERPDomainComponent | UActorComponent |
| Use case | Full targeting domain | Lightweight event mirror |
Use ERPChannelListenerComponent when you only need raw perception events without eligibility checks.
Next Steps
Build your targeting UI with Widget Guide.
Set up interactions with Interaction Guide.
Create custom domains with Custom Domains.
Check complete API in API Reference.