I have been working with the Learning Agents Drive tutorial. I got it to work well with Blueprint, like it is presented. Then I went back and tried to redo it using C++. Everything has gone smoothly right up to the end. I’m finding I cannot get the LearningAgentManager to work correctly without encapsulating it in a Blueprint. However, doing so causes other problems.
Pure C++ Manager Class
Here’s the problem when I don’t have my manager wrapped in a Blueprint class:
- The
MaxAgents
property inALearningAgentsManager
is private and immutable. - It is used inside
PostInitProperties()
to allocate memory for all the agents so I understand why it is private and immutable. - It NEEDS to be set. Leaving it as the default 1 is absurd, but there seems to be no way to do this from C++.
MaxAgents
as aUPROPERTY
is markedEditDefaultsOnly
so you can set it if you derive a blueprint from your class and change the ‘class defaults’
The fact that this can be set that way means there MUST be a way to set it from C++ but it is buried in the complex and poorly documented world of the UObjct
system and FObjectInitializer
and its archetype and I can’t find a way to do this (I’m going to ask about that elsewhere).
Wrapping my C++ Manager with a Blueprint
So, I gave up on that and tried to just wrap it in a Blueprint version of my manager. From there, I can set the MaxAgents
in the class defaults as expected BUT, I get a different issue:
- The Interactor, Trainer, and Policy components on the manager (which are all written and attached via C++) fail to properly initialize when my manager is wrapped with a Blueprint.
- I am creating them all in my manager’s constructor with
CreateDefaultSubobject<>()
. - Their ‘outer’ is properly set to my custom Manager class which inherits from
ALearningAgentsManager
. - Despite this, all of these components report “Error: Agent Interactor: Must be attached to a LearningAgentsManager Actor.” when I try to run their respective Setup methods.
This error ONLY happens when the manager is wrapped in a Blueprint; my code works fine when I just add the C++ class to the scene directly. However, the C++ version has MaxAgents set to 1 and I can’t change it. Catch 22!!
My best guess for the problem with the Blueprint version was that the order of execution is somehow different (constructor vs. BeginPlay vs. calling the various component Setup funcs, etc.) but I’ve tried doing a few logs from these various functions and they seem to execute in the order expected and all the C++ versions are running too (they aren’t getting shadowed by the Blueprint versions). Furthermore, all these logs happen in the same order regardless of whether the C++ class is wrapped in a Blueprint or not.
I examined the source code for the LearningAgentsManager and found where that error message about needing to be attached to a LearningAgentsManager actor happens. All it is doing is calling GetOwner
with the template set to ALearningAgentsManager
so I tried doing that myself and ensuring it doesn’t return null and IT DOESN’T! It seems like it should pass that test, but for some reason when playing-in-editor, it fails it. This makes me think I somehow have multiple versions of these components that are attached to my LearningAgentManager and some of them are getting attached properly while others are not. And that just confuses me even more!
So that’s my situation! Could use help with either or both of these things. I’m going to post about the general “provide default value for a private, immutable parent property” separately as that is not necessarily specific to the Learning Agents plugin. But solving this particular problem with the Learning Agents in C++ is my general goal so …