@MostHost_LA Ok, I got a working solution for now.
In my Subsystem, which inherits from GameInstanceSubsystem, I’ve added a Timer with a small delay and a Callback, to ensure that all Instances have been initialized in the game, before I’m trying to access them.
Subsystem.cpp:
void UNamelessSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
GetWorld()->GetTimerManager().SetTimer(MyTimerHandle, this, &UNamelessSubsystem::StartGettingReferences, 0.3f, false);
UE_LOG(LogTemp, Log, TEXT("Hello, I'm the nameless Subsystem"));
}
then in my callback I’m getting all hard references to the objects within my game world and let the Asset Manager get the references to my PlatoonDataAssets from the directory. Then again I’m using the Streamable Manager with async loading, (which worked pretty well last time, so I’m doing it again).
void UNamelessSubsystem::StartGettingReferences()
{
// iterate through cgf actors and store elements in an array
for (TActorIterator ActorItr((GetWorld())); ActorItr; ++ActorItr)
{
CGFArray.Add(*ActorItr);
}
UAssetManager* Manager = UAssetManager::GetIfValid();
if (Manager)
{
FPrimaryAssetType PlatoonDataType = FPrimaryAssetType(FName("PlatoonInfo"));
TArray<FPrimaryAssetId> PlatoonIdList;
Manager->GetPrimaryAssetIdList(PlatoonDataType, PlatoonIdList);
for (const FPrimaryAssetId& PlatoonID : PlatoonIdList)
{
FAssetData AssetDataToParse;
Manager->GetPrimaryAssetData(PlatoonID, AssetDataToParse);
if (AssetDataToParse.IsValid())
{
auto DataAsset = AssetDataToParse.GetAsset();
// load data asynchronously
UPlatoonInfo* platoonInfo = Cast<UPlatoonInfo>(DataAsset);
PlatoonDataInternal.Push(platoonInfo);
TArray<FSoftObjectPath> MembersToStream;
MembersToStream.AddUnique(platoonInfo->Leader.ToSoftObjectPath());
for (int32 i = 0; i < platoonInfo->Members.Num(); ++i)
{
MembersToStream.AddUnique(platoonInfo->Members[i].ToSoftObjectPath());
}
StreamableManager.RequestAsyncLoad(MembersToStream, FStreamableDelegate::CreateUObject(this, &UNamelessSubsystem::OnReferencesLoaded));
}
}
}
}
Once all soft references have been resolved, the callback from the streamable manager will handle the rest.
void UNamelessSubsystem::OnReferencesLoaded()
{
// assign necessary data to each platoon
// Get Leader Information and create Components
ACGF* LeaderUnit = nullptr;
TArray<ACGF*> PlatoonMembers;
UPlatoonInfo* platoonInfo = PlatoonDataInternal.Pop();
// determine leader
for (auto unit : CGFArray)
{
if (platoonInfo->Leader.Get()->GetName().Equals(unit->GetName()))
{
LeaderUnit = unit;
}
}
// go through object array and set information
for (auto unit : CGFArray)
{
for (int32 i = 0; i < platoonInfo->Members.Num(); ++i)
{
if (platoonInfo->Members[i].Get()->GetName().Equals(unit->GetName()))
{
int MemberIndex = i;
PlatoonMembers.Add(unit);
unit->SetPlatoonData(MemberIndex, LeaderUnit, platoonInfo);
}
}
}
LeaderUnit->OtherMembers = PlatoonMembers;
}
What I don’t like about this yet is that I have to loop through my cgf object array once to figure out the leader and once again to tell everyone else about who the leader is. Also I could remove already resolved cgf units from the object array, to make the loops for other platoons shorter.
I’m not 100% happy with this, but it works for now. Isn’t there a way to get my hard object references without having to compare names?? Maybe it’s best to just spawn the actors on the map and create a hard reference.