Ways to "Add Component from class"?

Hi,

I am searching for some hours now. But I find nothing so maybe some of you guys will know that. :slight_smile:

Is there any way to add a component in the same manner as we can “Spawn actor from class” by using classes?

I am currently having some blueprints derived from ActorComponent that have each different behaviors (base bloc definition and implementation + all childs with specialized behaviors).

As such. I am having a build tool that is adding new blocs to the “vehicle actor” and also deleting them (I do internal tracking).

But it seems like there is no way to have anything dynamic when it comes to Components like spawning from class or anything like that that would avoid me using something like an enum and then using the “Add Metal Bloc Component” or “Add Thruster Bloc Component” etc etc etc.

I started also digging into C++ code to maybe achieve this using TSubClassOf but I just keep having warnings such as "Static class is not part of TSubClassOf etc. (I could post the exact thing if anybody wants to know).

Thanks! :slight_smile:

I have the same problem.

Hey Intoxicat3,

as I encountered the issue, I did end up writting myself a very simple function that allows me to add new ActorComponents in C++.

You can put that in a class deriving from AActor and use it as a base to create the actors that will have the possibility to add new components.

This function does not expose the defaults parameters but it works. :slight_smile:

.h

UFUNCTION(BlueprintCallable, Category = "Component|AddComponent")
	UActorComponent* AddActorComponent(UClass* ActorComponentClass);

.cpp

UActorComponent* APhysicsActorCode::AddActorComponent(UClass* ActorComponentClass)
{
	UClass * baseClass = FindObject<UClass>(ANY_PACKAGE, TEXT("ActorComponent"));
	if (ActorComponentClass->IsChildOf(baseClass))
	{
		UActorComponent* NewComp = NewObject<UActorComponent>(this, ActorComponentClass);
		if (!NewComp)
		{
			return NULL;
		}
		//~~~~~~~~~~~~~

		NewComp->RegisterComponent();        //You must ConstructObject with a valid Outer that has world, see above	 

		return NewComp;
	}
	else
		return NULL;
}

I am using it for my project until UE4 supports it natively.

Tell me if this works or if you need any other indications.

Erio

Hi Erio - thanks for this!

…but I need to have it working in blueprints and binary version of the engine. Hope Epic will add it in 4.10 as “polishing current features” feature :wink:

As you can notice, with the UFUNCTION line, this in fact creates a node you can call in Blueprint. :wink:

EDIT: It also works with the binary version of the engine… You just have a little trick to do:

  • Create a C++ class inheriting AActor
  • Add the code I gave you, changing the name of the class
  • Compile
  • In UE4 Editor, for the actors you want to have the ability to add actor components, make their parent the new class you created.

In fact, instead of making a BP from an Actor, you will make a BP from the class you created, which is an actor but with the enhanced C++ code. :wink:

Hello!
I’m not much into C++

Can you please show full .h and .cpp solution?

I also don’t understand how to implement this.

Here’s an updated version working with 4.25, in a blueprint function library:
.h

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "ComponentHelperLibrary.generated.h"

/**
 * 
 */
UCLASS()
class ADVANCEDLOCOMOTIONSYSTEMV_API UComponentHelperLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable, Category = "Components|AddComponent")
	static UActorComponent* AddActorComponent(AActor* Owner, TSubclassOf<UActorComponent> ActorComponentClass);
};

.cpp

#include "ComponentHelperLibrary.h"

UActorComponent* UComponentHelperLibrary::AddActorComponent(AActor* Owner, TSubclassOf<UActorComponent> ActorComponentClass)
{
    UClass * baseClass = FindObject<UClass>(ANY_PACKAGE, TEXT("ActorComponent"));
    if (ActorComponentClass->IsChildOf(baseClass))
    {
        UActorComponent* NewComp = NewObject<UActorComponent>(Owner, ActorComponentClass);
        if (!NewComp)
        {
            return NULL;
        }
        //~~~~~~~~~~~~~
 
        NewComp->RegisterComponent();        //You must ConstructObject with a valid Outer that has world, see above     
 
        return NewComp;
    }
    else
        return NULL;
}

Some slightly more transparent instructions based on Hayaweh’s method if you are a noob like me. (thanks again so much for your help)

Open your project and create a new C++ Class. when selecting which class it inherits from, choose Blueprint Function Library. Make note of the name of this class and replace ###INSERTCLASSNAMEHERE### below with the class name while leaving the U before it. The proper includes and formatting will be auto generated by unreal, all you have to do is copy and paste the following at the line specified and hit rebuild.

//INSERT THIS AFTER GENERATED_BODY() in .h file:

  public:
      UFUNCTION(BlueprintCallable, Category = "Components|AddComponent")
      static UActorComponent* AddActorComponent(AActor* Owner, TSubclassOf<UActorComponent> ActorComponentClass);

//INSERT THIS AFTER INCLUDE in .cpp file:

 UActorComponent* U###INSERTCLASSNAMEHERE###::AddActorComponent(AActor* Owner, TSubclassOf<UActorComponent> ActorComponentClass)
  {
      UClass * baseClass = FindObject<UClass>(ANY_PACKAGE, TEXT("ActorComponent"));
      if (ActorComponentClass->IsChildOf(baseClass))
      {
          UActorComponent* NewComp = NewObject<UActorComponent>(Owner, ActorComponentClass);
          if (!NewComp)
          {
              return NULL;
          }
          //~~~~~~~~~~~~~
   
          NewComp->RegisterComponent();        //You must ConstructObject with a valid Outer that has world, see above     
   
          return NewComp;
      }
      else
          return NULL;
  }

Ensure that everything compiles properly, save, and exit out of and then reopen Unreal and you will see it in your blueprints. It will not show up in blueprints until you restart unreal.