sinbad / SPUD

Steve's Persistent Unreal Data library
MIT License
328 stars 47 forks source link

Compatibility With Lyra? #79

Closed dyanikoglu closed 1 week ago

dyanikoglu commented 1 month ago

When ALyraCharacter class is marked as ISpudObject and an override name is provided, in L_DefaultEditorOverview level (initial level selection map when you launch game), loading a quicksave results with player character respawning without transform being loaded.

Screenshot 2024-07-13 123739 Screenshot 2024-07-13 123800

I used B_SimpleHeroPawn for testing to keep things simple: Screenshot 2024-07-13 123821

Is this a bug with the plugin or do we need to apply additional changes to Lyra to get basic load/save functionality working with player character?

dyanikoglu commented 1 month ago

https://youtu.be/kBVMW_MZaW0

Here is video for the test I did. Just moved my pawn a little and saved/loaded game. Result is player pawn spawned in default location instead of saved transform.

sinbad commented 1 month ago

Probably a timing thing with the way Lyra initialises things. Sorry you'll have to investigate yourself, I don't use Lyra (it's way too over complicated)

dyanikoglu commented 1 month ago

Probably a timing thing with the way Lyra initialises things. Sorry you'll have to investigate yourself, I don't use Lyra (it's way too over complicated)

Does this mean I need to defer load process of SPUD subsystem for game framework actors? If so, which function is best place to do that? Lyra works based on "Game Experience" data, which is also responsible with spawning the player character after the game world loads. So, I guess SPUD is trying to load the world before player character is spawned. Can that be the issue?

sinbad commented 1 month ago

SPUD hooks into the level post-load process. This is what allows it to load actors for streaming levels. I suspect Lyra with its unnecessary over-complexity defers the whole character spawn process until later via an experience and therefore overwrites whatever SPUD has done post-load. How you fix this ordering issue is very much a "deep in Lyra" problem and I gave up on Lyra a year ago precisely because of this sort of unnecessary nonsense. Honestly unless you have a big team Lyra is overkill and just makes your life harder.

dyanikoglu commented 1 month ago

I tried to defer USpudSubsystem::OnPostLoadMap(UWorld* World) by 5 seconds just for testing, and that restored state of my player pawn 5 seconds after I initiate the quick load.

So yeah, that's definitely a timing issue :)

I can think of a proper solution for that issue though:

// Listen for the experience load to complete
AGameStateBase* GameState = GetGameStateChecked<AGameStateBase>();
ULyraExperienceManagerComponent* ExperienceComponent = GameState->FindComponentByClass<ULyraExperienceManagerComponent>();
check(ExperienceComponent);
ExperienceComponent->CallOrRegister_OnExperienceLoaded_LowPriority(FOnLyraExperienceLoaded::FDelegate::CreateUObject(this, &ThisClass::OnExperienceLoaded));

It should be possible to register SPUD subsystem to lyra experience load callback with the code block above, so you can load the game framework related data afterwards. The issue is, that creates a circular dependency, because you need to reference lyra inside SPUD plugin :/ Probably it's best to move whole source code of SPUD into project to get this working.

Edit: .. or maybe, lyra experience object can call post load from spud subsystem after it completes the load. Probably that will be more proper solution.

Dudeist commented 1 month ago

Hi I totally agree with Lyra - I tried it hard when released and I have same thoughts.

But I have few questions about SPUD system, I don't know where I can post it, one I post on Issues, I'm not sure is best place. Very short talk would be enough to all my dilemmas and it would help me a lot. The plugin seems amazing, but I have a few problems with my project. Fingers crossed!

Thanks, Paweł

dyanikoglu commented 1 week ago

My solution was to load player character separately when game starts (there is a function in spud state to load a single actor data). Since it's player character and assuming it doesn't hold ptrs to other loaded actors in world, this works pretty fine.

Closing the issue.