I’d like to make it so that, if a UPrimitiveComponent that simulates physics has an AttachParent that also simulates physics, the constraint configured for the child is tied to the parent, rather than tied to world space.
I believe that the change can be made locally in BodyInstance.cpp:
DOFConstraint->PriAxis2 = Normal;
DOFConstraint->SecAxis2 = Sec;
DOFConstraint->Pos2 = TM.GetLocation();
/* BEGIN NEW CODE */
FBodyInstance *parentBody = nullptr;
UPrimitiveComponent *parentComponent = OwnerComponent.Get();
if (parentComponent != nullptr) {
parentComponent = Cast<UPrimitiveComponent>(parentComponent->GetAttachParent());
}
if (parentComponent != nullptr) {
// TODO: parentComponent is gotten from a weak pointer; how long will
// this body pointer live?
parentBody = parentComponent->GetBodyInstance();
}
/* END NEW CODE */
// Create constraint instance based on DOF
DOFConstraint->InitConstraint(this, parentBody, 1.f, OwnerComponent.Get());
However, I’m concerned that getting a pointer to a bodystate in the parent is dangerous, because the component pointer is a weak pointer!
Also, the BodyState is an inline struct in the parent component.
What do I need to do to make sure that dangling references to the parent aren’t kept around?
My initial idea is to recreate the physics state inside UPrimitiveComponent::OnAttachmentChanged(), but I don’t know if that will be enough, and I also don’t know if that will be unnecessarily heavy-handed:
void UPrimitiveComponent::OnAttachmentChanged()
{
UWorld* World = GetWorld();
if (World && World->Scene)
{
World->Scene->UpdatePrimitiveAttachment(this);
}
/* We only need to recreate physics state if we had a physical parent component
that was used for the constraint. Moving physically simulated component attachment
should be rare enough that optimizing for that shouldn't be necessary. */
RecreatePhysicsState();
}
So, advice and pointers appreciated!