x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

ComponentBeginOverlap called twice in UE4.9

I have a simple inventory system using the Overlap event in C++. Walking over an item gives a copy to the player, and the original item disables its collision and goes to sleep. This worked as expected in 4.8

After upgrading the 4.9, the Overlap event was getting fired twice upon walking over the item. The stack trace, all parameters (`OtherActor`, OtherComponent, OtherBodyIndex, bFromSweep, and SweepResult) and this were all identical in both calls, so it's not a matter of two different components belonging to the same actor overlapping. This happens despite the overlap event disabling collision.

I added a simple fix by checking to see if collision is enabled, and aborting the event execution if not. This does solve the problem, but it's odd that the event is triggered twice all of a sudden.

Was this a deliberate change in behavior, or indeed a bug in the new release?

Product Version: UE 4.9
Tags:
more ▼

asked Sep 01 '15 at 07:36 PM in C++ Programming

avatar image

dstreb
46 14 16 20

avatar image Doug E ♦♦ STAFF Sep 01 '15 at 09:16 PM

Hey dstreb-

How are you setting you your overlap function in code? I tried to reproduce this with a simple actor where I setup the constructor:

 MyScene = CreateDefaultSubobject<USceneComponent>(TEXT("MyScene"));
     MyMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MyMesh"));
     MySphere = CreateDefaultSubobject<USphereComponent>(TEXT("MySphere"));
 
     RootComponent = MyScene;
     MyMesh->AttachTo(MyScene);
     MySphere->AttachTo(MyMesh);
     MyMesh->bGenerateOverlapEvents = true;
     MySphere->bGenerateOverlapEvents = true;

And overrode the NotifyActorBeginOverlap function:

 void AMyActor::NotifyActorBeginOverlap(AActor* OtherActor)
 {
     if (GEngine)
     {
         GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Magenta, TEXT("Hello"));
     }
     Super::NotifyActorBeginOverlap(OtherActor);
 }

In both 4.8.3 and 4.9 walking into the sphere component only printed "Hello" once.

Let me know if your setup looks different or if this setup gives you the result you're looking for.

Cheers

Doug Wilson

avatar image dstreb Sep 01 '15 at 09:32 PM

I'm using OnComponentBeginOverlap. I believe I had trouble getting NotifyActorBeginOverlap to work at all when I first started.

The colliding component is "pickupViewMesh":

 pickupViewMesh = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("InventoryPickupMesh"));
 pickupViewMesh->OnComponentBeginOverlap.AddDynamic(this, &AInventory::OnOverlapBegin);

Then the overlap function:

 void AInventory::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
 {
     bool col = pickupViewMesh->IsCollisionEnabled();
 
     //This is the condition put in to prevent the 2nd call. A breakpoint is set here, which shows 'col' as true the first time, false the second.
     if (!col)
         return;
 
     //Macro for printing to the screen. The class name was being printed twice.
     MSG(GetClass()->GetName());
 
     //GiveTo .....
 
     //This function will disable the collision
     TriggerRespawn();
 }

Collision is disabled as a result of TriggerRespawn() as follows:

         pickupViewMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
         pickupViewMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
 

This is completed by the time the 2nd overlap event is trigger, so I don't think it's any kind of threading issue.

avatar image Doug E ♦♦ STAFF Sep 02 '15 at 02:50 PM

Hey dstreb-

I changed the end of my constructor and added a function to match your setup as such:

//added at the end of the constructor MySphere->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::CallOnOverlap);

 }
 
 void AMyActor::CallOnOverlap(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
 {
     if (GEngine)
     {
         GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, TEXT("NotHello"));
     }
 }

With this setup it printed my message to the screen once in 4.8 as well as after upgrading the project to 4.9. If you are seeing your message print twice then it seems your dynamic function call is being made twice. Could you post the code class where this method is being used or send a copy of your project to test directly?

avatar image dstreb Sep 02 '15 at 03:34 PM

What's a good way to send a copy of my project? I do have a git repo, but I'm not 100% positive it's set up correctly, since I'm the only user.

avatar image Doug E ♦♦ STAFF Sep 02 '15 at 03:36 PM

If you upload the project to dropbox you can send me a private message on the forums with a link to download the project.

avatar image Doug E ♦♦ STAFF Sep 04 '15 at 09:14 PM

Hey dstreb-

Looking through the code it seems that OnOverlapBegin() calls TriggerResapwn(). TriggerRespawn() then makes a call to BecomeHidden(). Adding a return just before the call to BecomeHidden() caused the OnOverlapBegin to only trigger once. Putting a return after BecomeHidden() caused the double call effect to occur. You may want to look into how BecomeHidden() behaves to find why the OnOverlapBegin() is being called twice.

Cheers

Doug Wilson

avatar image dstreb Sep 05 '15 at 01:00 AM

I've looked into it. First, I copied BecomeHidden() into a new, identical function so I could modify the call from TriggerRespawn() and not any other source.

Currently, I have these three lines:

 pickupViewMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
 pickupViewMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
 pickupViewMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);

Commenting out all 3 of these and no other changes is enough to remove the extra OnOverlapBegin call. Leaving one or more uncommented triggers the extra call.

In other words, disabling collision is triggering a collision response. This certainly seems like a bug, and it was not happening in 4.8.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Hey dstreb-

I was able to confirm that setting collision to No Collision inside an overlap event cases the overlap to trigger twice. I have entered a bug report (UE-20848) to investigate this behavior.

Cheers

Doug Wilson

more ▼

answered Sep 08 '15 at 04:22 PM

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question