I have a generic vehicle class, derived from the standard AWheeledVehiclePawn
and I would like to load and change skeletal mesh and wheels animation at runtime depending on a vehicle type enum in input.
If I spawnm cars and set these assets from the editor, everything works fine, but if I try to set them programmatically from code, only the mesh is set, the animation is not working (wheels just not spinning / steering).
So the question is: how to set these two assets at runtime (or other approach, how to have a generic animation that works for all the different vehicle models and minimize the setup from code)?
Thanks!
Here some code:
UCLASS()
class MY_API ACar : public AWheeledVehiclePawn
{
GENERATED_UCLASS_BODY()
public:
void SetEntityType(const EntityType& type);
private:
void SetMeshAndAnim();
...
}
ACar::ACar(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
meshReferenceFolders_.Add(EntityType::Car1, L"Car1");
...
meshReferenceFolders_.Add(EntityType::CarN, L"CarN");
for (auto& meshPath : meshReferenceFolders_)
{
ConstructorHelpers::FObjectFinder<USkeletalMesh> mesh(
std::wstring(L"SkeletalMesh'" + ModelFolder + meshPath.Value + L"/" + meshPath.Value + L"." + meshPath.Value + L"'").data()
);
ConstructorHelpers::FObjectFinder<USkeleton> skeleton(
std::wstring(L"Skeleton'" + ModelFolder + meshPath.Value + L"/" + meshPath.Value + L"_Skeleton." + meshPath.Value + L"_Skeleton'").data()
);
if (skeleton.Object) mesh.Object->SetSkeleton(skeleton.Object);
ConstructorHelpers::FObjectFinder<UAnimBlueprint> animation(
std::wstring(L"UAnimBlueprint'" + ModelFolder + meshPath.Value + L"/" + meshPath.Value + L"_AnimBlueprint." + meshPath.Value + L"_AnimBlueprint'").data()
);
meshes_.Add(meshPath.Key, mesh.Object);
anims_.Add(meshPath.Key, animation.Object);
}
}
void ACar::SetEntityType(const EntityType& type)
{
carType_ = type;
SetMeshAndAnim();
}
void ACar::SetMeshAndAnim()
{
GetMesh()->SetSkeletalMesh(meshes_[carType_]);
GetMesh()->SetAnimInstanceClass(anims_[carType_]->GeneratedClass);
}
caller
void UManager::UManager()
{
...
static ConstructorHelpers::FObjectFinder<UBlueprint> asset(
TEXT("Blueprint'/Game/Blueprints/BPCar.BPCar'")
);
if (asset.Object)
{
importedCarInstance= asset.Object->GeneratedClass;
}
...
}
void UManager::TickComponent(
float DeltaTime,
ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction
)
{
...
if (spawn)
{
auto car = World->SpawnActor<ACar>(importedCarInstance, location, rotation, spawnParameters);
car->SetEntityType(obj.type);
}
}
For some unknown reasons I found that there was no controller associated to the spawned actor, and then the ChaosVehicleComponent was not able to set the throttle and steering values provided. To solve this, I just added an AIController, move all the automatic movement logic there, and associated it to my car when created