Hey guys, I am new to Unreal and using c++ with it and am finding it hard to achieve what I want to.
I have made a Prefab class, I want to create a blueprint from that class, add in render components and child actors, set variables to be the location of the child actors, and then spawn them from another LevelGenerator class, using TSubclassOf, and accessing their variables (location of child actors) to then spawn them next to each other. The problem I am having is that so far I can only access their default values but I want to access the values of the object.
How I have done this so far (I don’t know if this is the best way, please suggest improvements) is to have a function “CalledFromCpp” that the blueprint defines as setting the variables to the location of the child actors relative to the root, and this is called OnConstruction so it changes. In the editor when I create the PrefabBP, the variables do not update, but when I spawn one into the world they are listed correctly, however because the LevelGenerator only accesses defaults it does not correctly get this data.
Sorry if I have written too much I found it hard to explain, perhaps it is better to just show the code:
Prefab.h:
UCLASS()
class CIPROJECT_API APrefab : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
APrefab();
virtual void OnConstruction(const FTransform& transform) override;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere)
FVector leftConnector;
UFUNCTION(BlueprintCallable)
void setLeftConnector(FVector v);
UPROPERTY(EditAnywhere)
FVector rightConnector;
UFUNCTION(BlueprintCallable)
void setRightConnector(FVector v);
UFUNCTION(BlueprintImplementableEvent, Category = "Set")
void CalledFromCpp();
};
Prefab.cpp:
// Sets default values
APrefab::APrefab()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void APrefab::BeginPlay()
{
Super::BeginPlay();
}
void APrefab::OnConstruction(const FTransform& transform)
{
CalledFromCpp();
}
// Called every frame
void APrefab::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void APrefab::setLeftConnector(FVector v)
{
leftConnector = v;
}
void APrefab::setRightConnector(FVector v)
{
rightConnector = v;
}
LevelGenerator.h:
UCLASS()
class CIPROJECT_API ALevelGenerator : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ALevelGenerator();
UPROPERTY(EditAnywhere)
TArray<TSubclassOf<class APrefab>> Prefabs;
UPROPERTY(EditAnywhere)
int32 NumberOfRooms;
UFUNCTION(BlueprintCallable)
void Spawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
};
LevelGenerator.cpp:
// Sets default values
ALevelGenerator::ALevelGenerator()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ALevelGenerator::BeginPlay()
{
ALevelGenerator::Spawn();
}
void ALevelGenerator::Spawn()
{
FVector Shifter = Prefabs[0]->GetDefaultObject<APrefab>()->rightConnector - Prefabs[0]->GetDefaultObject<APrefab>()->leftConnector;
//FVector Shifter(580.0f, 0.0f, 0.0f);
if (Prefabs[0]!=nullptr)
{
UWorld* world = GetWorld();
if (world)
{
FVector Location(0.0f, 0.0f, 0.0f);
FRotator Rotation(0.0f, 0.0f, 0.0f);
FActorSpawnParameters SpawnInfo;
for (int i = 0; i < NumberOfRooms; i++)
{
FVector Shift = Shifter * (i);
world->SpawnActor<APrefab>(Prefabs[0], Location + (Shift), Rotation, SpawnInfo);
}
}
}
}
Any help would be appreciated, thanks a bunch.