I’m setting up a flight sim, with different airports set up as different sublevels. I’m running into a bit of a chicken-and-egg problem.
Here’s my setup:
I have an OriginShiftComponent on my aircraft pawn.
I have one or more player starts associated with each airport, and each playerstart has a GlobeAnchor attached to it. The player start GlobeAnchors are configured with the appropriate LLA coordinates corresponding to the airport they are associated with. PlayerStarts are not children of the sublevel.
I am using JSBSim, and have modified the UJSBSimMovementComponent to talk directly to the CesiumGeoReference (instead of syncing CesiumGeoReference tp the built-in unreal GeoReferenceSystem)
Problem:
A sub-level isn’t streamed in until the OriginShiftComponent moves near that sub-level, but if we want to spawn the pawn at that sublevel, we must know the unreal position of the player starts. As I understand it, in order to get the correct unreal position of a player start, I must translate the PlayerStart’s LLA into Unreal coordinates. In the case where I want to spawn at an airport belonging to a sublevel that isn’t loaded, I must spawn the aircraft at the player start, then on the next tick, OriginShiftComponent will detect that it should trigger the airport’s sublevel to begin loading. One or more frames later, the sublevel will finish streaming in and update the GeoReference. But by this time, the aircraft simulation has already killed itself because it detects that something about the parameters I’m sending it is invalid (usually altitude is negative).
The problem, as far as I can tell, is that the values that I’m getting from the GeoReference won’t give me 100% accurate translations between Unreal and ECEF coordinates until it’s streamed in the new sublevel and updated the GeoReference. Is that correct or am I misunderstanding?
Second problem: I could defer starting the aircraft simulation until the sublevel has finished streaming in and updated the GeoReference using the OnGeoreferenceUpdated delegate. But then I run into the second problem: if the playerstart that’s been chosen happens to be in the sublevel that is currently loaded, OnGeoreferenceUpdated won’t be triggered. So I need to figure out which sublevel is supposed to be loaded, so that I can either immediately move to the next step [if target sublevel is active] or wait for OnGeoreferenceUpdated if target sublevel isn’t active. There’s no easy way to do that right now, as far as I can find, so the road I’m about to start down is to duplicate the code in UCesiumOriginShiftComponent::TickComponent so that I can trigger it when I first spawn my aircraft, rather than waiting for tick.
It would be helpful to move the logic of UCesiumOriginShiftComponent::TickComponent into a method that could be called separately. Ideally, that logic woudl be split up into separate pieces as well - one to query whether we need to load a new sublevel, and one to actually perform the origin shift / sublevel load.
Third problem:
After activating a new sublevel, there is no notification that level streaming has completed. This seems like it would be pretty simple to add, so I’m wondering if I’m approaching this incorrectly. Any reason not to add this (and then use that notification to know when I’m ready to spawn my aircraft)?
What is the recommended way to handle my usage case? Have I going horribly astray somewhere?