So I’ve been defining a lot of my base classes in C++ and then using derived Blueprint classes to work with them. I’ve run into a situation though like this as an example. A base class that has an array of actors of another base class.
UCLASS()
class ABaseActor : public AActor
{
...
};
UCLASS()
class ABaseContainer : public AActor
{
...
UPROPERTY()
TArray<TObjectPtr<ABaseActor>> Actors;
};
The reason I have it set up like this is that I need to be able to work this array of actors in various places in C++. I can then derive a Blueprint from ABaseActor called MyActor and add it to a container’s Actors array.
I also need to work with this array in Blueprint as well. The problem is that the array only gives me my actors as type ABaseActor, not MyActor. So I need to cast in order to access any variables or functions on my derived Blueprint actor. If it was just one or two casts, no problem, but I have many of these situations cropping up and it is getting out of control having to cast for almost everything now.
So my question is, is there a way, perhaps using templating to be able to get the C++ class to return my array back to me as my derived Blueprint class instead of the base ABaseActor class?
I have a few ideas, but just not sure if any of them are possible or how to go about it (i.e. syntax and such).
Being able to set the type of the array to a template class based on ABaseActor? Something like TArray<TObjectPtr<T>> for example.
Have a function in the ABaseContainer class that could return a templated version of the Actors array? Something like TArray<TObjectPtr<T>> GetActors() for example.
Have a function library that has templated functions that can take an ABaseContainer as input and return an array of Actors based on a given type? Something like TArray<TObjectPtr<T>> GetActors(ABaseContainer* container) for example.
I really don’t know if any of these ideas are even possible so just looking for some advice. I see functions like Spawn Actor of Class seem to do something similar to what I want. You can select a class type and the return pin on the node actually returns an actor of that class in Blueprint, including Blueprint classes that you have created. So clearly something can be done, I’m just not sure how.
I did not read Your whole post (middle of night and bit sleepy now).
However with C++ and blueprints problem is that C++ does not know any classes/variables you declared in blueprints.
So my solution to this is to make even dummy/empty class in C++, then inherit it in blueprints. You can then have array of such classes/actors (one you declared in C++), that array needs to be also declared in c++ variable somewhere. But then you can add blueprint inherited class, to that array just like it was pure c++.
Yes i know its annoying that C++ does not know anything from blueprints side.
But then wait for enumerators madness. (enum as byte, and that C++ does not know enum entries from blueprints side, making enums kind of worthless)
C++ can interact with Blueprint via the reflection system. You can access variables via UClass::FindPropertyByName->Get/SetPropertyValue.
But this should be seen as an opportunity to quickly solve a specific problem, and not as a basis for building an entire game.
If you are early in development, it might be worth rethinking the design principle and moving from inheritance to composition (via actor components), or at least do you need to additionally create some specialized base classes in C++.
It is also possible to integrate C++ into Blueprint via interfaces created in C++. This will eliminate the need for always casting.
Or you can just create a function library and do some C++ calculations inside it by calling the Blueprint function.
Thanks for your responses guys. All valid points I’m aware of and have been considering. I just wanted to find out first if there was something I was missing with this. This is usually pretty easy to solve using templates, but it would appear that UE doesn’t respect class templates except in certain hardcoded situations such as containers like TArray for example. Well, that’s what I’ve read anyway.
@Nawrot That’s pretty much what I’m already doing. This is what results in having to cast.
@PREDALIEN The only thing I don’t like about composition is that it requires you to get a component every time you need to access a variable. I’m trying to eliminate these superfluous “cast” and “get component” nodes all over the place. Just makes things messier than they need to be.
Just looking for a cleaner solution since we’ve been told that using Blueprint and C++ together is encouraged, I just assumed I was doing something wrong.
Had same problems. Thing is that C++ is completely unaware of code in blueprints, You cannot expose anything from blueprints to c++, but almost everything from C++ can be known on blueprints side. It is how unreal blueprints are designed.
If you don’t want to look at the cast/get component, you can wrap them in a function that will return the desired value.
Or you can create your own K2Node to get variables. Here you are almost unlimited, and can build your nodes based on Blueprint classes (using the same reflection to determine the available variables).