I haven’t come across objects which are not either located in the game world or attached to actors. How can I add functionality to the game without creating physical representation in the game world using C++?
For example, I would like to have all enemies controlled by a single entity which manages their projectile pooling, spawning and movement. This manager would not have a physical representation or location, it should not be despawned with world partition etc. Sort of like a global enemy AI without the AI part.
So, there could be 100 enemies spread out in the game and they should all share the same pool of 100 projectiles. For this I would need all enemies to have a pointer to the same object pool to request projectiles or some manager which tells an enemy to fire and assigns pooled resources for the projectile.
How are such entities usually created in UE5 using C++? What C++ class should such an entity be based on and where should it live? Should it be attached to the player character?
Looking into it more, subsystems seem like the best way to do what I want. A object pool managing subsystem that can be queried by any actor needing to spawn a projectile. There will be no need to have pointers or references.
Subsystems are definitely a good tool for this sort of thing. However, don’t entirely discount actors either even if they don’t need a physical location in the world.
I really like subsystems, but there are a couple of downsides to them. The first being that you can’t easily extend or configure them like you can with blueprints. You can use config and developer settings to get around this a little. Also, subsystems are kinds of always on and it’s difficult to make them narrowly optional. Like it’s easy to prevent world subsystems from running in the editor, but it’s harder to make them only run on a subset of maps.
SpecZynk suggestion for the game mode can also be good for a lot of things but you’d have to be care of making the mode do too much or ending up with a functionality you can’t easily reuse when you want it to.
A variation of their suggestion that works out pretty well is configuring on your game mode actor classes that it should spawn. This is how the game mode spawns the hud and default pawn among other actors. This has the benefit of keeping that functionality compartmentalized and even swappable because you just need to create a new gamemode for a map and swap the actor type that should be spawned. And if the game mode doesn’t need that functionality it could not have that option or you could leave the class blank.
Please look at AInfo, as it is a perfect match for your description.
Subsystems (of “global” nature like EngineSubsystem or GameInstanceSubsystems) or the GameInstance can be potential pick, but you have to remember these are not actors, so contrary to AInfo-derived classes (which are), they cannot benefit from the Entity-Component paradigm core to contemporary UE. Its enough for me not to recommend them for these purposes.
The GameInstance or subsystems can be prefered by beginners because they “save data between switches to level”.
However, beginners also typically completely gloss over the problems that come with this “data saving” property of many subsystem, in a real game. For example, if you go to your main menu and load a new level, data from certain kind of subsystems will not reset. It can be quite hard to dig yourself out of the hole you buried yourself into, by designing with a subsystem without understanding how their data is handled.
GameState and GameMode are both AInfos but obviously you can code your own . You can then create BP Function Library with a simple global getter for your new class. It will be much more robust if you design it that way.
If it’s mostly tunable parameters for enemy behavior, then you’ll probably want this to be part of GameMode.
One benefit of this is that if you want “easy mode,” “normal mode” and “hard mode,” you simply create three instances of your game mode class, with different configurations, and the rest will Just Work ™
Thank you for pointing to AInfo. It looks interesting and I will research it more. It’s annoying that I never come across these cool features by searching for functionality myself using the documentation.
For now, I went with a WorldSubsystem which works perfectly for my use-case: universal per-level single player pools. As a first working implementation, it seems to be solid for now until I run into some limitations.
You use this phrase like subsystems are some antiquated part of the engine that no one should be using any more. Subsystems were introduced relatively recently (if not 5.0 then 4.26 or 27). Subsystems have a much better workflow for required background mechanics than either having to hand place actors in a map (user error if the actor should be on every map and is forgotten) or the alternative of writing the boilerplate to manage actor spawning on the game mode/state.
While it is true that they don’t benefit from components, the systems built using subsystems rarely need components and would not benefit from them anyway. That’s all part of the software design process to determine the best way to add your system. Just another tool in the tool box along side actors, uobjects and even non-reflected types.
Also, there are a many other types of subsystems. Yes, the GameInstance subsystem can have the issues that you point out if used naively but there are also World Subsystems and Local Player Subsystems that are great tools and are destroyed/recreated with the World/Player with no bleed of data between them.
I wish we’d had them as a tool on my last game (shipped on 4.26 so 99% of development was before they were introduced).
Yeah I agree, I was just warning beginners to look into how they work and their implication first. Like you said, subsystems are very useful in countless context, personally I really like EngineSubsystems for their all-encompassing reach (they are active even during engine’s boot time).
I’m just saying AInfo is the manager class and can be used here pretty well. Using subsystem is fine until one day you need two of the thing, then you need to rework everything. And again, I’m not saying it won’t work. It will work great, its just a very monolithic approach whereas AInfo is a very modular approach.
Another detail I was thinking about is that subsystem are not parametrizeable in the editor. You need a plugin like susbystem browser to manager their fields. AInfo is just all around a very straightforward and easy to use solution. Dropping them in the world as actor is exactly as it should be. There is nothing wrong with this. It’s fully explicit and a great practice.
Also, I won’t lie, I don’t understand why you’re critiquing my language. I said Entity-Component is important in contemporary practice of UE. There is nothing wrong with that statement. If my wording is slightly weird, it’s because I am french and english is my second language. Please don’t nitpick language of strangers on the internet like that… I am just giving my advice on a public forum, you are free to ignore it.
Yeah, that can be a problem but one that is easily solved using the DeveloperSettings class built into the Engine. You don’t need an extra plugin. You can also mark them up as Config directly but that does lose the nice editing available in the Editor.
Because I felt it important to clarify the other paradigms that are just as core to UE as the Entity-Components. As I said, they’re just another tool in the UE architectural toolbox along with a number of other solutions both as part of the Engine (like subsystems) as well as those supported by C++ (like a system made up of purely functions in the functional programming style). And so components are not somehow more core of a paradigm than all the others.
Engineering discussions require precision which sometimes involves nitpicking. This has nothing to do with English as a first, second or twelfth language. One person’s use of component can make another assume UActorComponent. It’s not about correcting, but about building a shared understanding of the conversation going on so that either person one uses another word (because component has a larger UE connotation) or person two can move on with a new understanding because no UActorComponent types are involved anywhere in the discussion so there’s no confusion calling something else “component”.
And it’s a forum that will act as the foundation for those that come after us which means I think it’s important for there not to be properly nuanced advice in the posts (not that the internet is great at nuance). Invariably some other newbie comes around say “I’ve got a problem with this Actor setup X” that they’re only doing because they saw some advice like this that could be taken to imply everything thing they make should be an Actor. When really the solution to their problem is just a simple DataAsset. You might think that’s a hyperbolic and hypothetical case but I’ve had it happen plenty of times.
I don’t want to derail this thread any further since it’s sort of drifting from the original topic. Feel free to DM me if there’s anything to discuss further. Sorry if anything there (or here) felt like an attack, it was not intended as such.