Adding different classes in same or multiple arrays?

Hi,
I’m creating an RTS style game where you can select multiple units. Some of the units are derived from the character class and some are derived from the pawn class.

If I “select” multiple units and add them to an array of type “AActor” I can’t access variables that I have created in them.

Another way of doing it is to add all the units to an array that has their class as the type.
But doing it this way forces me to loop through multiple different arrays when I want to access one of their variables.

Is there another way of doing it or would I need to build the engine from source and change that original actor class?

Hi there,
You best solution is to use blueprint communication with interfaces. This workflow is class independent.

Let me see if I can find a quick tutorial (blueprints) and share it here. For c++, unfortunately, I can’t help you out.
WTF Is? Blueprint Interface - YouTube
Unreal Engine 4 C++ Tutorial - Using Interfaces - UE4 / Unreal Engine 4 Intro to C++ - YouTube

1 Like

Interfaces defining the type of functionality are what you should probably use, especially if they must have different base classes. However, if they are similar enough that you need them in a list of similar items, i’d have to question why they have different base classes to begin with?

In general, if they all share the same functionality, you would want them in a base class. If they have similar functionality that should share the same method of operation, but operate differently, then interfaces. Or, if they must be separate base classes for some reason, then interfaces also.

In either case, you’ll need to learn about Type Casting. Casting Quick Start Guide | Unreal Engine Documentation

1 Like

To expand upon this a little further – you can get where you need to be right now, using type casting. But you should also learn interfaces, as that can be a better paradigm for the situation. And I think you should consider the reasoning why some of your guys are Characters and some are Pawns. You haven’t stated any reasons for that, but it seems a bit odd, given the information we do have, so I suggest considering the reasoning for that.

Just to add another potential option, next to interfaces, is to have a shared ActorComponent. If all your actors inside the array have the same Component, you can unify the behavior from there.

That doesn’t really help you so much with the Array problem, though. Then you’d have to search each actor in the list for the component. If they do have to be different base classes, but can use the same implementation, however, making a Component that does the implementation, then having an Interface implemented in the classes that interfaces with the Component can be a good way.

what about filtering by tags? You can tag actors or components.

Is that any benefit here?

If your logic is in a, lets say SelectableUnitComponent and you can abstract your logic into this component, it works nicely. And it doesn’t matter where this component is placed, as long as the general selection logic is the same. I would probably expose events in the component that then can be registered to in the actor instances itself for custom logic based on different actors.

Hey there! Haven’t you found any solution yet?

I’m new in UE and have the same problem here: RTS has some actors (static objects - buildings, trees, etc.) and characters - units. Former of course cannot be derived (inherited) from the latter and vice versa. And having common ancester (UObject) doesn’t help here either - as Biglund wrote when storing ancestors in that array - the added functionality doesn’t work.

For example, pawns cannot move without character movement component, and characters have much of an extra components, which isn’t needed for static objects. That’s the reason for them not to be the same class. (first I thought characters can be inherited from actors, but it appeared to be false)

I created interface for the common functionality, but it cannot help with storing those in one array of the “Selected items”.

The idea here is to store/work with and trace such objects in PlayerController. It must work even for the single selected items.

Unfortunately didn’t really get the idea about creating a special component as a solution - are there any examples? As I know usually in RTS only one class of the objects is being selected - buildings, or units. But I’d like to sort out how to deal with selecting both.

Thanks in advance for any help.

Sorry for confusing everyone, I guess I rushed to write about not being able to cast both classes to their ancestor.
They both perfectly cast to UObject and back! So they can both be traversed and call the customly added methods.

So far the result is quite easy. For example:

void AMP_PlayerController::ObjectsSelectionStarted()
{
	UWorld* World = GetWorld();
	
	FHitResult HitResult;

	EmptySelectedObjectsList();

	if (GetHitResultUnderCursorByChannel(SelectionChannel, false, HitResult))
	{

		if(UObject* HitActor = Cast<UObject>(HitResult.GetActor()))
		{
			SelectedObjects.Add(HitActor);
			if (AMP_Character* HitCharacter = Cast<AMP_Character>(HitActor))
			{
				HitCharacter->ChangeSelectionState(true);
			}
			else if (AMP_StaticObject* HitObject = Cast<AMP_StaticObject>(HitActor))
			{
				HitObject->ChangeSelectionState(true);
			}
		}
		
	}

}

Hope my further constructions and code demands won’t ruin this simple principle of casting.

That’s a perfect use for an Interface, rather than casting around.