Collision when using attached actors

This is a fairly common question, I know, but I have not seen an answer that suggests a workaround. I have seen “this isn’t supported” stated in a few different ways.

I have multiple actors with collision shapes. They collide just fine on their own, but when they are attached to each other, collision stops working. What I have gathered from the other threads on this issue is that there is no “sweep” performed for attached actors.

I desperately need a workaround for this. Can anyone suggest anything that might work? At this point, I’ve lost over a week of work and am still stuck.

I am attaching the actors using the simplest method I know:

AttachRootComponentTo(root_actor, NAME_None, EAttachLocation::SnapToTarget);

I can post any other code that might help explain my particular situation, but there’s nothing fancy about it. It’s just a bunch of actors, each with one static mesh component, each with a custom collision shape, attached using the code above.

I am not using Physics, only the absolute basic collisions. I just need to have a method called when these attached actors collide.

I’m willing to hack around in the engine code to fix this if someone can point me to the right code. I am currently looking through USceneComponent::MoveComponent() but it isn’t very clear to me, yet, how/where the attached actors are moved.

I have a fix for this that works in my particular situation, maybe it will help someone with the same problem.

If you look at PrimitiveComponent.cpp, line 1415:

		FComponentQueryParams Params(Name_MoveComponent, Actor);
		FCollisionResponseParams ResponseParam;
		InitSweepCollisionParams(Params, ResponseParam);
		bool const bHadBlockingHit = GetWorld()->ComponentSweepMulti(Hits, this, TraceStart, TraceEnd, GetComponentRotation(), Params);

		if (Hits.Num() > 0)

This is the code used inside the MoveComponent() member of a primitive component. It sweeps the component and returns an array of hits in the “Hits” variable. So, my fix was to copy this code into my actor’s Tick() method, which is where I handle movement. Where I do the movement for the root component, I added a simple loop to perform this sweep for all attached actors:

UWorld *w = GetWorld();
TArray<FHitResult> hits;

// This is how I was already handling movement, just a simple velocity vector multiplied by the elapsed time this tick
// You may want to also set the "bSweep" parameter in MoveComponent() here, if your root actor has a collision shape
// My root actor is just an empty dummy used for attaching other things, so I do not sweep it
FVector move(velocity * delta_seconds);
RootComponent->MoveComponent(move, rotation);

// The "attached_actors" array is a TArray of AActor* that I fill as things are being attached
// There are other ways to get all attached actors if necessary
for (auto i : attached_actors)
{
    // Get the root USceneComponent of the attached actor and cast it to a UPrimitiveComponent
    UPrimitiveComponent *root = Cast<UPrimitiveComponent>(i->GetRootComponent());

    // Start of move
    FVector start(root->GetComponentLocation());

    // Some collision parameters, not sure what they do, just initialize them to defaults
    FComponentQueryParams cqparams(TEXT("sweep_params"), i);
    FCollisionResponseParams crparams;
    root->InitSweepCollisionParams(cqparams, crparams);

    // Sweep the component and fill "hits" with the results
    w->ComponentSweepMulti(hits, root, start, start + move, root->GetComponentRotation(), cqparams);

    if (hits.Num())
    {
        // You can handle the hits here or save them and deal with them later, etc...
        // You could also call DispatchBlockingHit() here if you want your actor's "on_hit" method to be called
    }
}

Keep in mind that this only handles the most simple type of collision, just “hits.” My project does not use physics, overlaps, etc, so if you want to make those work, you will need to dig deeper into the MoveComponent() code and see how they are handled for the root component and add that code to your loop.

1 Like

Thanks for the solution, but still hope UE give an official solution like you did.

it does actually work for me as well. At least I get the hit results. But how do I continue? I want the root component (where the other actor is attached) to actually “feel” that there is something blocking the path. Calling DispatchBlockingHit doesn’t seem to work.

That just depends on how you want to handle the collision. Calling DispatchBlockingHit() will just cause the standard collision handling, which means the colliding actor’s “on hit” method will be called. You can do whatever you need to do in that method. If you want some kind of physics-based reaction, that’s going to be hard.

For example, say you have a character and he’s holding a sword. By default, if you have that sword “parented” to a character, it won’t collide with anything. Now, suppose you add this code to force the child actor to register collisions. It will work and when that sword collides with another actor, you’ll get an “on_hit” for the sword actor. But if you just tell the parent to stop moving (which is what UE4 normally does for “blocking” collisions), your whole character is going to be frozen in place because it’s blocked. That’s probably not what you want. You probably want to have another animation ready where the character’s arm rebounds back away from the collision, plus some code to do damage to what the sword hit, so on and so on.

There isn’t really a “stock” action that can be used when a parented actor collides, which (I believe) is why collisions aren’t enabled for parented actors by default. UE can’t just automatically do the right thing in this situation.

Thank you for answering! I see what you mean and this is exactly what I was experiencing. Could you may have a look at my thread with the detailed problem? Plasma/Energy Shield like in Star Wars - C++ - Unreal Engine Forums

Thank you very much and sorry for reviving this question.

Problem

When you attach an actor to another actor, UE won’t automatically perform a collision sweep for the attached actor. It simply becomes a part of the parent actor’s hierarchy.

Solution

I much prefer using native collision detection than trying to do it manually. This is how I did it:

  • Create two bones for the attached object. One small just as an attachment point, and a longer one for the body of the object.

  • Create a Physics Asset with a Physics Body for each bone. If the editor complains about the attachment bone being too small to create a physics body, just set the minimum bone size parameter to 0.

  • Set the body bone to physics->simulated. Enables physics-driven collision detection.

  • Set the attachment bone to “kinematic” (i.e. physics disabled) so that it moves with the parent like a physics-disabled object instead of falling on the ground.

  • Select both Physics Bodies in the Physics Asset Editor in the skeleton list panel, right click, choose create constraint between selected bodies. Lock up all the translation and rotation, should be 6 boxes to check lock on. This anchors the simulated bone onto the kinematic bone to make the entire object rigid and kinematic in movement.

  • Click the Physics Body of the simulated bone, go to the collision section in the details panel, check Continuous Collision Detection to activate it. This is critical to enable collision.

2 Likes

Solution

I much prefer using native collision detection than trying to do it manually. This is how I did it:

Create two bones for the attached object. One small just as an attachment point, and a longer one for the body of the object.

Create a Physics Asset with a Physics Body for each bone. If the editor complains about the attachment bone being too small to create a physics body, just set the minimum bone size parameter to 0.

Set the body bone to physics->simulated. Enables physics-driven collision detection.

Set the attachment bone to “kinematic” (i.e. physics disabled) so that it moves with the parent like a physics-disabled object instead of falling on the ground.

Select both Physics Bodies in the Physics Asset Editor in the skeleton list panel, right click, choose create constraint between selected bodies. Lock up all the translation and rotation, should be 6 boxes to check lock on. This anchors the simulated bone onto the kinematic bone to make the entire object rigid and kinematic in movement.

Click the Physics Body of the simulated bone, go to the collision section in the details panel, check Continuous Collision Detection to activate it. This is critical to enable collision.

This works fantastically, you’re a lifesaver- been trying different things all day and finally found this.

You’d think “let the player hit enemies with a stick” would be trivial, but no.

Thanks so much! Saved me with this.