diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Timeline/PS_Editor_TimelineSubsystem.cpp b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Timeline/PS_Editor_TimelineSubsystem.cpp index 8e6fad3..445d61d 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Timeline/PS_Editor_TimelineSubsystem.cpp +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Timeline/PS_Editor_TimelineSubsystem.cpp @@ -300,6 +300,10 @@ void UPS_Editor_TimelineSubsystem::Clear() bIsPlaying = false; LastAppliedValues.Empty(); PrePlayBaseline.Reset(); + // Drop the old ActorIds — the previous scenario's actors have been destroyed and the + // weak references are now stale. Keeping them around confuses FindActorById when the + // next scenario happens to reuse the same FGuid (it can return a stale null entry). + ActorIds.Reset(); OnTimelineChanged.Broadcast(); } @@ -570,11 +574,18 @@ FGuid UPS_Editor_TimelineSubsystem::FindActorId(AActor* Actor) const AActor* UPS_Editor_TimelineSubsystem::FindActorById(const FGuid& Id) const { if (!Id.IsValid()) return nullptr; + // Iterate every pair: the map can legitimately contain stale weak references from a + // previous scenario whose actors were destroyed. Without this check the first match on + // GUID can return a null key before we reach the live entry, giving "(missing)" after + // the second load of the same scenario. for (const TPair, FGuid>& Pair : ActorIds) { if (Pair.Value == Id) { - return Pair.Key.Get(); + if (AActor* Live = Pair.Key.Get()) + { + return Live; + } } } return nullptr; @@ -583,6 +594,16 @@ AActor* UPS_Editor_TimelineSubsystem::FindActorById(const FGuid& Id) const void UPS_Editor_TimelineSubsystem::RegisterActorId(AActor* Actor, const FGuid& Id) { if (!Actor || !Id.IsValid()) return; + // Prune any stale entries plus any previous entry holding the same GUID (the old actor + // has been destroyed and replaced by this one). Keeps the map tight and ensures + // FindActorById cannot hit a ghost key with the same GUID. + for (auto It = ActorIds.CreateIterator(); It; ++It) + { + if (!It.Key().IsValid() || It.Value() == Id) + { + It.RemoveCurrent(); + } + } ActorIds.Add(TWeakObjectPtr(Actor), Id); }