Unreal Engine, from C++ spawn Blueprint inherited from C++ class, very small example: Difference between revisions

From Andreida
(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:...")
 
(3 intermediate revisions by the same user not shown)
Line 21: Line 21:
=== Create Classes ===
=== Create Classes ===
==== Actor ====
==== Actor ====
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()
GENERATED_BODY()
public:
public:
Line 45: Line 47:
protected:
protected:


virtual void BeginPlay() override;
virtual void BeginPlay() override;


UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Mesh"))
UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Mesh"))
UStaticMesh* m_pMesh;
UStaticMesh* m_pMesh;


UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Scene Component Root"))
UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Scene Component Root"))
USceneComponent* m_pScRoot;
USceneComponent* m_pScRoot;


UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Static Mesh Component of Root"))
UPROPERTY(EditAnywhere, Category = "Structure", meta = (DisplayName = "Static Mesh Component of Root"))
UStaticMeshComponent* m_pSmcRoot;
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");
m_pScRoot = CreateDefaultSubobject<USceneComponent>("Root");
RootComponent = m_pScRoot;
RootComponent = m_pScRoot;


m_pSmcRoot = CreateDefaultSubobject<UStaticMeshComponent>("SmcRoot");
m_pSmcRoot = CreateDefaultSubobject<UStaticMeshComponent>("SmcRoot");


FAttachmentTransformRules transformRule = FAttachmentTransformRules::SnapToTargetIncludingScale;
FAttachmentTransformRules transformRule = FAttachmentTransformRules::SnapToTargetIncludingScale;
m_pSmcRoot->AttachToComponent(RootComponent, transformRule);
m_pSmcRoot->AttachToComponent(RootComponent, transformRule);


PrimaryActorTick.bCanEverTick = false;
PrimaryActorTick.bCanEverTick = false;
}
}


void AMiniActor::BeginPlay()
void AMiniActor::BeginPlay()
{
{
Super::BeginPlay();
Super::BeginPlay();


if (m_pMesh != nullptr)
if (m_pMesh != nullptr)
{
{
m_pSmcRoot->SetStaticMesh(m_pMesh);
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.

==== 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.

Revision as of 13: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

Actor

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::SnapToTargetIncludingScale;
  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.

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.