It would make so much more sense to make a OnBeginOverlap and OnEndOverlap type functions or delegates and check the tag when an overlap occurs and ends. The use of the tick for something simple like a trigger is killing me inside. Now I’m too busy thinking how I’m going to change this after the course is done…
Hi,
There was a long discussion on this and I actually spoke to the instructor as to why he did it this way. His answer was that it was a nice simple solution and he felt that it didn’t need the complexities of the events.
As it happens, in this case anyway, that using a tick is the easiest solution. Given that begin and end overlap in the engine are basically ticked and calls the handler when overlap occurs or not at the appropriate time, you could almost argue having 2 events instead of a count of overlaps in the tick is less efficient in this case. In fact, the overlap also needs to track what is overlapping so it can send the end overlap when the actor leaves the trigger and also ensure that it is not overlapping already when entering. It may be that the trigger actor or component contains this logic but however it is done, this will be required.
For simplicity, you could wrap the code in a method so later you can just move the call to the overlap with a few tweaks if that is how you wish to approach the issue.
There was even folks citing best practice but unless epic comes along and says what is best practice, generally this could be considered a subjective opinion.
In the end, both methods work and the tick is the easier of the two for less experienced developers to follow.
I know he did it that way for simplicity but I went ahead and did it by binding to the delegate anyway and this is how I did mine.
I’m only showing the part I did differently, the Constructor is the same and for the most part I followed the logic with only slight changes where needed.
// Called when the game starts or when spawned
void APressurePlate::BeginPlay()
{
Super::BeginPlay();
SetReplicateMovement(true);
// Trigger Setup
TriggerShape->SetVisibility(false);
TriggerShape->SetCollisionProfileName(FName("OverlapAll"));
TriggerShape->SetGenerateOverlapEvents(true);
TriggerShape->OnComponentBeginOverlap.AddDynamic(this, &APressurePlate::OnComponentBeginOverlap);
TriggerShape->OnComponentEndOverlap.AddDynamic(this, &APressurePlate::OnComponentEndOverlap);
if (HasAuthority())
{
// Make sure that the player isn't already overlapping at game start
TArray<AActor*> OverlappingActors;
TriggerShape->GetOverlappingActors(OverlappingActors);
for (const AActor* OtherActor : OverlappingActors)
{
HandleBeginOverlappingActor(OtherActor);
if (Activated)
{
break;
}
}
}
}
// Called every frame
void APressurePlate::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void APressurePlate::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (HasAuthority())
{
HandleBeginOverlappingActor(OtherActor);
}
}
void APressurePlate::OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
if (HasAuthority() && OtherActor->ActorHasTag("TriggerActor"))
{
if (Activated)
{
Activated = false;
}
FString Msg = FString::Printf(TEXT("%s Left PressurePlate"), *OtherActor->GetName());
GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Yellow, Msg);
}
}
void APressurePlate::HandleBeginOverlappingActor(const AActor* OtherActor)
{
if (OtherActor->ActorHasTag("TriggerActor"))
{
// if (OtherActor != this)
FString Msg = FString::Printf(TEXT("%s Entered PressurePlate"), *OtherActor->GetName());
GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::White, Msg);
if (!Activated)
{
Activated = true;
}
}
}
And on the Header
private:
UFUNCTION()
void OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
UFUNCTION()
void OnComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
UFUNCTION()
void HandleBeginOverlappingActor(const AActor* OtherActor);
It’s understandable why he didn’t do it this way because there are so many parameters and for those not familiar with the Overlap outputs it can easily confuse you.
I’ve a lot of experience in Blueprints so I’m pretty familiar with that stuff.
This is the beauty of coding, you can always do things differently. Thanks for sharing.