Unreal Engine, from C++ spawn Blueprint inherited from C++ class, very small example: Difference between revisions
(Created page with "=== Prepare Project === ==== Create Project ==== * Games / Blank ** C++ ** Desktop ** Maximum ** Starter Content: no ** Raytracing: no ** Location: your choice ** Project Name: ShowActor * Create ==== Change Map to Basic ==== When the UE-Editor is open: * File / New Level / Basic / Create * File / Save Current Level as ... / Basic01 * Edit / Project Settings / Maps & Modes / Editor Startup Map: Basic01 * Edit / Project Settings / Maps & Modes / Editor Game Default Map:...") |
m (→Test it all) |
||
(10 intermediate revisions by the same user not shown) | |||
Line 20: | Line 20: | ||
=== Create Classes === |
=== Create Classes === |
||
==== |
==== class MiniActor ==== |
||
This is the class from which we will create a blueprint which we will then spawn. |
|||
* Tools / New C++ Class |
* Tools / New C++ Class |
||
** Parent Class: Actor |
** Parent Class: Actor |
||
** Name MiniActor |
** Name: MiniActor |
||
** Create Class |
** Create Class |
||
Line 37: | Line 39: | ||
class SHOWACTOR_API AMiniActor : public AActor |
class SHOWACTOR_API AMiniActor : public AActor |
||
{ |
{ |
||
GENERATED_BODY() |
|||
public: |
public: |
||
Line 45: | Line 47: | ||
protected: |
protected: |
||
virtual void BeginPlay() override; |
|||
UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Mesh")) |
|||
UStaticMesh* m_pMesh; |
|||
UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Scene Component Root")) |
|||
USceneComponent* m_pScRoot; |
|||
UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Static Mesh Component of Root")) |
|||
UStaticMeshComponent* m_pSmcRoot; |
|||
}; |
}; |
||
</pre> |
</pre> |
||
===== Source File ===== |
|||
===== Source File: MiniActor.cpp ===== |
|||
<pre> |
<pre> |
||
#include "MiniActor.h" |
#include "MiniActor.h" |
||
Line 63: | Line 66: | ||
AMiniActor::AMiniActor() |
AMiniActor::AMiniActor() |
||
{ |
{ |
||
m_pScRoot = CreateDefaultSubobject<USceneComponent>("Root"); |
|||
RootComponent = m_pScRoot; |
|||
m_pSmcRoot = CreateDefaultSubobject<UStaticMeshComponent>("SmcRoot"); |
|||
FAttachmentTransformRules transformRule = FAttachmentTransformRules::KeepRelativeTransform; |
|||
m_pSmcRoot->AttachToComponent(RootComponent, transformRule); |
|||
PrimaryActorTick.bCanEverTick = false; |
|||
} |
} |
||
void AMiniActor::BeginPlay() |
void AMiniActor::BeginPlay() |
||
{ |
{ |
||
Super::BeginPlay(); |
|||
if (m_pMesh != nullptr) |
|||
{ |
|||
m_pSmcRoot->SetStaticMesh(m_pMesh); |
|||
} |
|||
} |
} |
||
Line 88: | Line 91: | ||
===== Build ===== |
===== Build ===== |
||
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is. |
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is. |
||
==== class Nagtc ==== |
|||
We need "something" to tell UE what blueprint we want to spawn and how many. There are many places where you can do it. This is just an example. |
|||
* Nagtc: (N)ot (a) (g)lobal (t)rash (c)an |
|||
* Tools / New C++ Class |
|||
** Parent Class: Actor |
|||
** Name: Nagtc |
|||
** Create Class |
|||
===== Header File: Nagtc.h ===== |
|||
<pre> |
|||
#pragma once |
|||
#include "CoreMinimal.h" |
|||
#include "GameFramework/Actor.h" |
|||
#include "MiniActor.h" |
|||
#include "Nagtc.generated.h" |
|||
UCLASS() |
|||
class SHOWACTOR_API ANagtc : public AActor |
|||
{ |
|||
GENERATED_BODY() |
|||
public: |
|||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Generating Test Data", Meta = (DisplayName = "Number of Test objects")) |
|||
int32 m_nNumberOfTestObjects; |
|||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Generating Test Data", Meta = (DisplayName = "MiniActor Blueprint Class for Test 1")) |
|||
TSubclassOf<AMiniActor> m_MiniActorTest1; |
|||
static void test1(UWorld* pWorld); |
|||
protected: |
|||
static ANagtc* getInstanceFromWorld(UWorld* pWorld); |
|||
void test1(); |
|||
}; |
|||
</pre> |
|||
===== Source File: Nagtc.cpp ===== |
|||
<pre> |
|||
#include "Nagtc.h" |
|||
#include "Engine/World.h" |
|||
#include "Kismet/GameplayStatics.h" |
|||
/// static |
|||
void |
|||
ANagtc::test1(UWorld* pWorld) |
|||
{ |
|||
ANagtc* pNagtc = getInstanceFromWorld(pWorld); |
|||
if (pNagtc) |
|||
{ |
|||
pNagtc->test1(); |
|||
} |
|||
} |
|||
void |
|||
ANagtc::test1() |
|||
{ |
|||
if (m_nNumberOfTestObjects > 0 && m_MiniActorTest1.Get() != nullptr) |
|||
{ |
|||
double fX = 0; |
|||
double fY = 0; |
|||
double fZ = 0; |
|||
for (int n = 0; n < m_nNumberOfTestObjects; ++n) |
|||
{ |
|||
FVector locator(fX, fY, fZ); |
|||
AActor* pActor = GetWorld()->SpawnActor(m_MiniActorTest1, &locator); |
|||
fY += 100; |
|||
fZ += 50; |
|||
} |
|||
} |
|||
} |
|||
ANagtc* |
|||
ANagtc::getInstanceFromWorld(UWorld* pWorld) |
|||
{ |
|||
TArray<AActor*> arrActorsToFind; |
|||
UGameplayStatics::GetAllActorsOfClass(pWorld, ANagtc::StaticClass(), arrActorsToFind); |
|||
if (arrActorsToFind.Num() == 1) |
|||
{ |
|||
ANagtc* pNagtc = Cast<ANagtc>(arrActorsToFind[0]); |
|||
return pNagtc; |
|||
} |
|||
return nullptr; |
|||
} |
|||
</pre> |
|||
===== Build ===== |
|||
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is, if you created MiniActor before. |
|||
==== class MyGameMode ==== |
|||
* Tools / New C++ Class |
|||
** Parent Class: GameModeBase |
|||
** Name: MyGameMode |
|||
** Create Class |
|||
===== Header File: MyGameMode.h ===== |
|||
<pre> |
|||
#pragma once |
|||
#include "CoreMinimal.h" |
|||
#include "GameFramework/GameModeBase.h" |
|||
#include "MyGameMode.generated.h" |
|||
UCLASS() |
|||
class SHOWACTOR_API AMyGameMode : public AGameModeBase |
|||
{ |
|||
GENERATED_BODY() |
|||
public: |
|||
virtual void BeginPlay() override; |
|||
}; |
|||
</pre> |
|||
===== Source File: MyGameMode.cpp ===== |
|||
<pre> |
|||
#include "MyGameMode.h" |
|||
#include "Nagtc.h" |
|||
void |
|||
AMyGameMode::BeginPlay() |
|||
{ |
|||
Super::BeginPlay(); |
|||
ANagtc::test1(GetWorld()); |
|||
} |
|||
</pre> |
|||
===== Build ===== |
|||
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is, if you created MiniActor and Nagtc before. |
|||
=== Configuring stuff inside the UE-Editor === |
|||
==== Set your GameMode as the used one ==== |
|||
* WorldSetting / Game Mode / GameMode Override: MyGameMode |
|||
==== Create Blueprint from your C++ Actor MiniActor ==== |
|||
* Content Browser / C++ Classes / MiniActor |
|||
** Right-click / Create Blueprint class based on MiniActor |
|||
*** Name: BP_MyMiniActor |
|||
If the Blueprint is not already open, open it in the UE-Editor. |
|||
* Mesh: |
|||
** Show Engine Content |
|||
** Cube, Static Mesh (100x100x100 not the 256x256x256) |
|||
* Compile |
|||
* Close |
|||
* Save the Blueprint |
|||
==== Put Nagtc actor into the world ==== |
|||
* Content Browser / C++ / Nagtc |
|||
* Drag Nagtc into the world |
|||
* Select Nagtc in the Outliner (and switch back from "World Settings" to "Details") |
|||
** Number of Test objects: 25 |
|||
** MiniActor Blueprint Class for Test 1: BP_MyMiniActor |
|||
=== Test it all === |
|||
* Change "PlayerStart" / Transform |
|||
** Location: -200 / 0 / 70 |
|||
** Rotation: 0 / 0 / 40 |
|||
* File / Save all |
|||
* Play the level |
|||
** Left click into the world and move your view around to see what you just created |
Revision as of 16:48, 6 May 2024
Prepare Project
Create Project
- Games / Blank
- C++
- Desktop
- Maximum
- Starter Content: no
- Raytracing: no
- Location: your choice
- Project Name: ShowActor
- Create
Change Map to Basic
When the UE-Editor is open:
- File / New Level / Basic / Create
- File / Save Current Level as ... / Basic01
- Edit / Project Settings / Maps & Modes / Editor Startup Map: Basic01
- Edit / Project Settings / Maps & Modes / Editor Game Default Map: Basic01
Create Classes
class MiniActor
This is the class from which we will create a blueprint which we will then spawn.
- Tools / New C++ Class
- Parent Class: Actor
- Name: MiniActor
- Create Class
Header File: MiniActor.h
#pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MiniActor.generated.h" UCLASS(Blueprintable) class SHOWACTOR_API AMiniActor : public AActor { GENERATED_BODY() public: AMiniActor(); protected: virtual void BeginPlay() override; UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Mesh")) UStaticMesh* m_pMesh; UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Scene Component Root")) USceneComponent* m_pScRoot; UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Static Mesh Component of Root")) UStaticMeshComponent* m_pSmcRoot; };
Source File: MiniActor.cpp
#include "MiniActor.h" AMiniActor::AMiniActor() { m_pScRoot = CreateDefaultSubobject<USceneComponent>("Root"); RootComponent = m_pScRoot; m_pSmcRoot = CreateDefaultSubobject<UStaticMeshComponent>("SmcRoot"); FAttachmentTransformRules transformRule = FAttachmentTransformRules::KeepRelativeTransform; m_pSmcRoot->AttachToComponent(RootComponent, transformRule); PrimaryActorTick.bCanEverTick = false; } void AMiniActor::BeginPlay() { Super::BeginPlay(); if (m_pMesh != nullptr) { m_pSmcRoot->SetStaticMesh(m_pMesh); } }
Build
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is.
class Nagtc
We need "something" to tell UE what blueprint we want to spawn and how many. There are many places where you can do it. This is just an example.
- Nagtc: (N)ot (a) (g)lobal (t)rash (c)an
- Tools / New C++ Class
- Parent Class: Actor
- Name: Nagtc
- Create Class
Header File: Nagtc.h
#pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MiniActor.h" #include "Nagtc.generated.h" UCLASS() class SHOWACTOR_API ANagtc : public AActor { GENERATED_BODY() public: UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Generating Test Data", Meta = (DisplayName = "Number of Test objects")) int32 m_nNumberOfTestObjects; UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Generating Test Data", Meta = (DisplayName = "MiniActor Blueprint Class for Test 1")) TSubclassOf<AMiniActor> m_MiniActorTest1; static void test1(UWorld* pWorld); protected: static ANagtc* getInstanceFromWorld(UWorld* pWorld); void test1(); };
Source File: Nagtc.cpp
#include "Nagtc.h" #include "Engine/World.h" #include "Kismet/GameplayStatics.h" /// static void ANagtc::test1(UWorld* pWorld) { ANagtc* pNagtc = getInstanceFromWorld(pWorld); if (pNagtc) { pNagtc->test1(); } } void ANagtc::test1() { if (m_nNumberOfTestObjects > 0 && m_MiniActorTest1.Get() != nullptr) { double fX = 0; double fY = 0; double fZ = 0; for (int n = 0; n < m_nNumberOfTestObjects; ++n) { FVector locator(fX, fY, fZ); AActor* pActor = GetWorld()->SpawnActor(m_MiniActorTest1, &locator); fY += 100; fZ += 50; } } } ANagtc* ANagtc::getInstanceFromWorld(UWorld* pWorld) { TArray<AActor*> arrActorsToFind; UGameplayStatics::GetAllActorsOfClass(pWorld, ANagtc::StaticClass(), arrActorsToFind); if (arrActorsToFind.Num() == 1) { ANagtc* pNagtc = Cast<ANagtc>(arrActorsToFind[0]); return pNagtc; } return nullptr; }
Build
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is, if you created MiniActor before.
class MyGameMode
- Tools / New C++ Class
- Parent Class: GameModeBase
- Name: MyGameMode
- Create Class
Header File: MyGameMode.h
#pragma once #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "MyGameMode.generated.h" UCLASS() class SHOWACTOR_API AMyGameMode : public AGameModeBase { GENERATED_BODY() public: virtual void BeginPlay() override; };
Source File: MyGameMode.cpp
#include "MyGameMode.h" #include "Nagtc.h" void AMyGameMode::BeginPlay() { Super::BeginPlay(); ANagtc::test1(GetWorld()); }
Build
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is, if you created MiniActor and Nagtc before.
Configuring stuff inside the UE-Editor
Set your GameMode as the used one
- WorldSetting / Game Mode / GameMode Override: MyGameMode
Create Blueprint from your C++ Actor MiniActor
- Content Browser / C++ Classes / MiniActor
- Right-click / Create Blueprint class based on MiniActor
- Name: BP_MyMiniActor
- Right-click / Create Blueprint class based on MiniActor
If the Blueprint is not already open, open it in the UE-Editor.
- Mesh:
- Show Engine Content
- Cube, Static Mesh (100x100x100 not the 256x256x256)
- Compile
- Close
- Save the Blueprint
Put Nagtc actor into the world
- Content Browser / C++ / Nagtc
- Drag Nagtc into the world
- Select Nagtc in the Outliner (and switch back from "World Settings" to "Details")
- Number of Test objects: 25
- MiniActor Blueprint Class for Test 1: BP_MyMiniActor
Test it all
- Change "PlayerStart" / Transform
- Location: -200 / 0 / 70
- Rotation: 0 / 0 / 40
- File / Save all
- Play the level
- Left click into the world and move your view around to see what you just created