How To Set Actor Components To Be Other Components?

I have a tank game that uses modular upgrades for your tank that do different things. The way I’m designing the modularity in blueprints is that I’m using scene components that simply get tacked on to a tank blueprint. I have a base class with all the variable declared, and the inheriting class sets them based on its diversity. How do I set these blueprints?

Gameplay will want to change what references my tank mods will hold. For example Cannon is a type of Gun Mod and there are other Gun Mods that can be plugged into this variable.

I can make it a purple class (whatever that means) instead of a blue reference, even then I still can’t find other Gun Mod types in the list to set this variable to.

I can however use the set function at runtime to achieve this with the purple class. But I can’t for whatever reason call functions from it.

There is where in code I would do this->gunMod = new Cannon(); So what is the blueprint equivalent of instantiation?

EDIT:

Other posts similar to my problem.

I guess a way to do this is to add them as legit components to the component hierarchy.

So in my parent class, Generic Tank, I have everything defined and my components contain virtual functions. So in a derived class, say Medium Tank, I want to call the Fire function from whatever type of Gun Mod my Gun Mod variable in referencing. In this case, I have Cannon that is of type Gun Mod that overrides Gun Mod’s Fire function. So if the Medium Tank want to equip a Cannon as its Gun Mod, it sets the Gun Mod to a new type of Cannon with the overridden Fire function that does a different thing form the other Gun Mods that use Fire.

I suppose I could just type cast, but I’m looking for a less hard-coded solution. When players go to customize their loadout, the Gun Mod variable needs to be able to change to whatever other type of Gun Mod the player chooses.

Well, better proceed to points:

  1. A reference is a pointer to a memory allocation. What it mean? Whenever you spawn an actor (or construct an object) you allocate a little part of the memory to keep the data of the class you spawned. All that data can be edited at runtime. The reference contain the required address to find the data. If you set a ref variable = to an other ref you DON’T obtain 2 objects, you make both the variables points to the same object.

  2. A class (purple variable) points instead to your “”“pure”"" object. For ex: You have a class called: “fruit” with a bunch of variable (color, shape, peelThickness) and child classes (banana, apple, orange). Now if I spawn a banana (default color: yellow) you can set the color of THAT banana to blue in runtime editing the variable through the reference BUT if you get the banana class default you’ll found that the color is yellow.

You can get variables from a class through “get class defaults” node but you can’t call any method (because blueprints methods aren’t statics). If you want to call a method you need to spawn that class and call object’s method through ref. If you really need to call a function without spawning an object you can create a function in a Blueprint Function Library, that functions are static and you can call them whenever and wherever you want.

“Yeah doctor, it’s all cool but how can I make my fu*king cannon to fire?”

Well if you have a method “fire” in your parent class and an overrided method foreach child class you can simply call “fire”. Ex: I’ve the generic class “GunMod” with a “fire” event with no nodes attached, then I made a “BananaShooter” class, inherit from “GunMod” with a “fire” node that spawn big banana projectile, and a class “Orangethrower” (same inherit) with a method “fire” that spawn a cone of orange juice. You don’t need to know what class your GunMod is to call “fire” event (because GunMod has a fire event), if it’s a BananaShooter the event fire’ll shoot a banana, if is an OrangeThrower will burn your enemy eyes.

EDIT: for what you are making you have to perfectly know classes, references and polymorphism. I’m ending a project similar to yours (not with tanks or other vehicles, don’t worry) and the use of classes and polimorphism is fundamental.

Okay I understand the difference between reference and class now, but I’m still confused how I would “spawn” a new reference of a class. I don’t want to “spawn” an actor in physical space, I want to instantiate a new object from a class in data.

You don’t need to know what class your GunMod is to call “fire” event (because GunMod has a fire event)

But I do need to know what class GunMod is because I want to call the method from an inherited class overriding it and not from the parent.

In my medium tank when the fire button is pressed, it calls the Fire method from the GunMod component. My question is: how do I change what type GunMod actor component is without completely replacing it?

My Medium tank inherits from Generic Tank which has all these base components already like GunMod of type GunMod. In my Medium Tank, I want to be able to change GunMod to other types of GunMods on the fly; like changing GunMod to be Cannon of type GunMod.

To instantiate an object: if the object class is inherit from actor class you have to spawn, if not you have to construct (the actor class is an object that can spawn in the scene). The node has a ref pin: that’s you reference to the instantiated actor.

If you call an overrided method from a parent ref but if the object is actually a child you’ll call the child method:

ex: I’ve in my scene 3 actors: “banana”, “apple”, “orange”, inherit from “fruit”. I use get all actor of class node to get an array with 3 references to fruit object (I don’t know which fruits are). If I get element 0 (banana) and I call the method “peel” I’ll call the overrided method of the banana class (use your hands), if instead I call the same method for element 1 (apple) that haven’t an overrided peel method I’ll call peel method in fruit (usa a knife).

Now, when you create your GunMod don’t create a GunMod object, create directly a child class (you can get the class from you savegame), then save the child ref in the GunMod variable.

So my idea with casting doesn’t work.

How the heck do you apply polymorphism to actor components?

I just tried Construct Object and that didn’t work either. Compiler says wrong class to spawn.

Now, when you create your GunMod don’t create a GunMod object, create directly a child class

But in my parent class of Generic Tank I do create a Gun Mod of type Gun Mod because it has to be something. Then in child classes of Generic Tank, they change what Gun Mod is whether it be Cannon or something else derived from Gun Mod.

My Generic Tank already has these properties defined.

Then my Medium Prototype tank inherits them.

And I want to change what the value of Gun Mod is. I don’t want it to be a reference of Gun Mod anymore at this point.

Like, what if I have a float in Generic Tank, weight for example. In base tank that can be defined as 0, but others inheriting this can change it based on what they are. How is that done with components?

Well this is super counter intuitive. I’ve been trying to find ways to instantiate an actor component and have it replace an existing component for days now and it turns out I have to “Add” a component first.

What ever Add is doing, its creating/spawning/instantiating the object I want and setting it to my gun mod variable. So now when I reference that variable to call a method from it, its called from Cannon and not Gun Mod anymore.

This was super frustrating to figure out.

My problem is not totally solved yet. I’m still having issues setting actor components to be other component of a common type.

This throws an error whenever I compile things that change the blueprint this construction script is on. It says error, but if I disconnect the nodes and reconnect them and recompile, it works as it did before. I don’t know. I need like a programmer at Epic or someone who understands the engineering of components better than I to help me solve this.

I just want a variable of a common type that can be other objects that inherit this common type! Why is object instantiation so difficult in blueprints??

In the screenshot you are calling a method in the actual blueprint (self reference). If that blueprint haven’t that method it’ll be return error, also you are calling it in constrution script (before any instantiation).

take a look at this if it can help you:

Ok I made you this quick demo that could help you, let’s me know if this is what you want to achieve.

link text

Okay then. Thanks. What was helpful. Though I noticed you didn’t use anything from the actor component class and used uobject for all the base components of car. Am I using actor components for the wrong purposes? I thought about refactoring my blueprints to just use uobject references because I can’t seem to “spawn” actor components at all.

Also what’s the difference in using Construct Object from Class and Spawn Actor and setting the return value to a variable. I get Spawn Actor actually instantiates something derived form the actor class in 3D space, but programmatically data-wise what’s the difference? Because really I just want to instantiate a thing, reference it to another thing to call functions and get data from.

Not C++ syntax, but I’m trying trying to illustrate how I’m trying to interpret blueprints.

class Tank{
   
   CannonClass cannon;
   Engine engine;

   Tank(){
      this.cannon = new BigCannon();
      this.engine = new BlueEngine();
   }

   void EquipMachineGun(){
      cannon = new HeavyMachinegun();
   }

   void OnButtonEvent(EButton btn){
      if(btn == EButton.F){
         cannon.Fire();
      }
   }
}

Also could you explain to me how Construct Object from Class works? Why does it need a reference to the “owning” blueprint if it returns a reference to the thing that was just created?

Informative, but doesn’t help my instantiation problems.

I think Add is an internal function for Actors which is what that is. This appears to be an editor bug because it totally does work.

Are Actor Components intended to be dynamic or static?

I don’t use actor components because in my project I need a more complex customization system that CAC don’t allow me, but you can use them if you prefere, this is a correct case. In the demo I’ve sent you you can delete the construction script of the car and replace it with “set class” nodes for components (and obviously replace all the pin with casted refs from your components).

In both case (construct and spawn) you allocate a part of your memory to keep the data of your object (instantiation), in construct you don’t spawn stuff in the scene. I dunno if you can construct an actor but you can try. The ref you get from the construct/spawn points to the memory allocation so you can get or set stuff. The reference you need to put in the construct node (outer) is the owner of the constructed object, until the owner exists the garbage collector will not remove the constructed object (I guess, not 100% sure, something about 90%).

Long story short:

  • if you don’t need to spawn nor run events use a class and get defaults (unless it contains refs variable such materials, curves, bp refs etc).
    -if you don’t need to spawn but you need to run events construct an object (built your BP from object class instead of actor) and save its ref into a variable (from which you can call events).
    -if you need to spawn something spawn an actor object.

If you need more info about child actor component take a look at this: Twitch

Quick update on this. I actually ended up abandoning Actor Components in favor of just spawning Actors as gun components that are purely functional and fully encapsulated and attached them to my primary actors in the level. Actor Components are super frustrating to use in my design because it feels like they were intended to be setup outside of runtime.