Add new events for trigger + fix GetVolumeCenter

This commit is contained in:
Maxime Maurin 2023-08-04 00:19:59 +02:00
parent fbe4129df8
commit 750cd3b656
7 changed files with 57 additions and 30 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -31,7 +31,7 @@ void UPwnTrigger::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActo
if (UPwnTriggerRegister* Register = OtherActor->GetComponentByClass<UPwnTriggerRegister>()) { if (UPwnTriggerRegister* Register = OtherActor->GetComponentByClass<UPwnTriggerRegister>()) {
Register->RegisterTrigger(this); Register->RegisterTrigger(this);
OnTriggerEnter.Broadcast(OtherActor); OnTriggerEnter.Broadcast(OtherActor);
ExecuteActions(EnterActions); ExecuteActions(EnterActions, OtherActor);
} }
} }
@ -40,13 +40,15 @@ void UPwnTrigger::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor*
if (UPwnTriggerRegister* Register = OtherActor->GetComponentByClass<UPwnTriggerRegister>()) { if (UPwnTriggerRegister* Register = OtherActor->GetComponentByClass<UPwnTriggerRegister>()) {
Register->UnregisterTrigger(this); Register->UnregisterTrigger(this);
OnTriggerExit.Broadcast(OtherActor); OnTriggerExit.Broadcast(OtherActor);
ExecuteActions(ExitActions); ExecuteActions(ExitActions, OtherActor);
} }
} }
void UPwnTrigger::Activate(const bool bReset) { void UPwnTrigger::Activate(const bool bReset) {
if (bReset || ShouldActivate() == true) { if (bReset || ShouldActivate() == true) {
VolumeComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly); if (VolumeComponent) {
VolumeComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
}
SetActiveFlag(true); SetActiveFlag(true);
OnComponentActivated.Broadcast(this, bReset); OnComponentActivated.Broadcast(this, bReset);
} }
@ -54,34 +56,36 @@ void UPwnTrigger::Activate(const bool bReset) {
void UPwnTrigger::Deactivate() { void UPwnTrigger::Deactivate() {
if (ShouldActivate() == false) { if (ShouldActivate() == false) {
VolumeComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); if (VolumeComponent) {
VolumeComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
SetActiveFlag(false); SetActiveFlag(false);
OnComponentDeactivated.Broadcast(this); OnComponentDeactivated.Broadcast(this);
} }
} }
void UPwnTrigger::Interact_Implementation(const EInteractionType InteractionType) { void UPwnTrigger::Interact_Implementation(const EInteractionType InteractionType, const AActor* Interactor) {
if (InteractionType == Enable) { if (InteractionType == Enable) {
Activate(true); Activate(true);
} else if (InteractionType == Disable) { } else if (InteractionType == Disable) {
Deactivate(); Deactivate();
} else if (InteractionType == Toggle) { } else if (InteractionType == Toggle) {
ExecuteActions(ManualActions); ExecuteActions(ManualActions, Interactor);
} }
} }
FVector UPwnTrigger::GetVolumeCenter() const { FVector UPwnTrigger::GetVolumeCenter() const {
if (ensure(VolumeComponent)) { if (ensure(VolumeComponent)) {
VolumeComponent->Bounds.Origin; return VolumeComponent->Bounds.Origin;
} }
return FVector::ZeroVector; return FVector::ZeroVector;
} }
void UPwnTrigger::ExecuteActions(const FInteractableActions& InteractableActions) const { void UPwnTrigger::ExecuteActions(const FInteractableActions& InteractableActions, const AActor* Interactor) const {
for (const FInteractableAction &Action : InteractableActions.Actions) { for (const FInteractableAction &Action : InteractableActions.Actions) {
Execute_Interact(Action.Interactable.ActorReference.TryLoad(), Action.InteractionType); Execute_Interact(Action.Interactable.ActorReference.TryLoad(), Action.InteractionType, Interactor);
} }
if (InteractableActions.SelfInteract) { if (InteractableActions.SelfInteract) {
Execute_Interact(GetOwner(), InteractableActions.SelfInteractionType); Execute_Interact(GetOwner(), InteractableActions.SelfInteractionType, Interactor);
} }
} }

View File

@ -26,21 +26,32 @@ void UPwnTriggerRegister::UnregisterTrigger(UPwnTrigger* Trigger) {
RelevantTrigger = nullptr; RelevantTrigger = nullptr;
} }
} }
UE_DISABLE_OPTIMIZATION
void UPwnTriggerRegister::TickComponent(float DeltaTime, ELevelTick TickType, void UPwnTriggerRegister::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) { FActorComponentTickFunction* ThisTickFunction) {
UPwnTrigger* ClosestTrigger = nullptr; UPwnTrigger* BestTrigger = nullptr;
float ClosestDistance = TNumericLimits<float>::Max(); float LowestDot = TNumericLimits<float>::Max();
for (UPwnTrigger* PwnTrigger : Triggers) { for (UPwnTrigger* PwnTrigger : Triggers) {
const float Distance = FVector::DistSquared2D(GetOwner()->GetActorLocation(), PwnTrigger->GetVolumeCenter()); FVector2D ActorForward = FVector2D(GetOwner()->GetActorForwardVector());
if (Distance < ClosestDistance) { FVector2D ActorToTrigger = FVector2D(PwnTrigger->GetVolumeCenter() - GetOwner()->GetActorLocation()).GetSafeNormal();
ClosestDistance = Distance; const float Dot = FVector2D::DotProduct(ActorForward, ActorToTrigger);
ClosestTrigger = PwnTrigger; // Check dot product against lowest dot product and check if the actor is facing the trigger
if (Dot < LowestDot && (!PwnTrigger->MustFaceCenter || FMath::RadiansToDegrees(FMath::Acos(Dot)) < PwnTrigger->FaceAngle * 0.5f)) {
LowestDot = Dot;
BestTrigger = PwnTrigger;
} }
} }
if (ClosestTrigger != RelevantTrigger) { if (BestTrigger != RelevantTrigger) {
OnRelevantTriggerChanged.Broadcast(RelevantTrigger, ClosestTrigger); OnRelevantTriggerChanged.Broadcast(RelevantTrigger, BestTrigger);
RelevantTrigger = ClosestTrigger; if (RelevantTrigger) {
RelevantTrigger->OnTriggerUnreadyToInteract.Broadcast(GetOwner());
}
RelevantTrigger = BestTrigger;
if (RelevantTrigger) {
RelevantTrigger->OnTriggerReadyToInteract.Broadcast(GetOwner());
}
} }
} }
UE_ENABLE_OPTIMIZATION

View File

@ -21,5 +21,5 @@ class PAWN_API IPwnInteractable {
public: public:
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Interaction") UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Interaction")
void Interact(const EInteractionType InteractionType); void Interact(const EInteractionType InteractionType, const AActor* Interactor);
}; };

View File

@ -62,14 +62,14 @@ protected:
// End of Unreal Engine overrides // End of Unreal Engine overrides
public: public:
// IPwnInteractable overrides // IPwnInteractable overrides
virtual void Interact_Implementation(const EInteractionType InteractionType) override; virtual void Interact_Implementation(const EInteractionType InteractionType, const AActor* Interactor) override;
// End of IPwnInteractable overrides // End of IPwnInteractable overrides
UFUNCTION() UFUNCTION()
FVector GetVolumeCenter() const; FVector GetVolumeCenter() const;
private: private:
void ExecuteActions(const FInteractableActions &InteractableActions) const; void ExecuteActions(const FInteractableActions &InteractableActions, const AActor* Interactor) const;
public: public:
UPROPERTY(EditAnywhere, Category="Interaction") UPROPERTY(EditAnywhere, Category="Interaction")
@ -81,14 +81,26 @@ public:
UPROPERTY(EditAnywhere, Category="Interaction") UPROPERTY(EditAnywhere, Category="Interaction")
FInteractableActions ManualActions; FInteractableActions ManualActions;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Interactor", meta=(ToolTip="If true, the manual actions can only be triggered if the player is facing the center of the trigger volume."))
bool MustFaceCenter = true;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Interactor", meta=(Units="degrees", EditCondition="MustFaceCenter", ClampMin=0.0f, ClampMax=360.0f, UIMin=0.0f, UIMax=360.0f))
float FaceAngle = 60.0f;
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
FTriggerDelegate OnTriggerEnter; FTriggerDelegate OnTriggerEnter;
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
FTriggerDelegate OnTriggerExit; FTriggerDelegate OnTriggerExit;
UPROPERTY(BlueprintAssignable)
FTriggerDelegate OnTriggerReadyToInteract;
UPROPERTY(BlueprintAssignable)
FTriggerDelegate OnTriggerUnreadyToInteract;
protected: protected:
UPROPERTY(EditAnywhere, meta=(UseComponentPicker, AllowedClasses="ShapeComponent")) UPROPERTY(EditAnywhere, Category="Volume", meta=(UseComponentPicker, AllowedClasses="ShapeComponent"))
FComponentReference TriggerVolume; FComponentReference TriggerVolume;
private: private: