I have an issue that I’ve been trying to fix for a while now but the math escapes me. Basically what I’m trying to do is make a modular ship game, the ship will be divided into several components with the hull, the rear, and the nose. I’ve gotten a semi-working class now, however the issue is that the CollisionSphere component grows OnConstruction and binds to the back of the ship if it moves past a certain world location, so now I want to forgo my previous method of having a separate root and simply make the CollisionSphere be the root component.
The problem now becomes that the StaticMeshComponents that make up the rear, the nose, and all in between (as the class is meant to scale for more StaticMeshes between those two), are not properly offset to adjust to the center.
The diagram shows what I’m trying to accomplish, basically I combine all the collision bounds into one and then use the center’s sphere radius to set the hull (CollisionSphere), this isn’t a problem, however getting the offset needed to put each StaticMesh component is.
This is what I have as of now:
ASpaceship::ASpaceship() {
PrimaryActorTick.bCanEverTick = true;
SetRootComponent(hull);
hull = CreateDefaultSubobject<USphereComponent>("hull");
rear = CreateDefaultSubobject<UStaticMeshComponent>("rear");
nose = CreateDefaultSubobject<UStaticMeshComponent>("nose");
hull->InitSphereRadius(0);
rear->SetupAttachment(hull);
nose->SetupAttachment(hull);
bUseControllerRotationPitch = true;
bUseControllerRotationYaw = true;
bUseControllerRotationRoll = true;
}
// Called when object is constructed or undergoes any change.
void ASpaceship::OnConstruction(const FTransform& Transform) {
FBoxSphereBounds bounds;
TArray<USceneComponent*>modules;
hull->GetChildrenComponents(false, modules);
modules.RemoveAt(modules.Find(rear));
modules.RemoveAt(modules.Find(nose));
modules.Insert(rear, 0);
modules.Add(nose);
// Setup the root collider to fit all pieces inside of it.
for (int i = 0; i < modules.Num(); i++) {
bounds = bounds + modules[i]->CalcBounds(modules[i]->GetRelativeTransform());
if (i > 0 && modules[i - 1]->DoesSocketExist("moduleslot_fore")) {
modules[i]->SetRelativeLocation(modules[i - 1]->GetSocketTransform("moduleslot_fore", RTS_Actor).GetLocation());
}
}
hull->SetSphereRadius(bounds.SphereRadius);
}