Skip to content

3.4.3 Update prevents world loading after entering a save and exit to menu #44

@ccpemily

Description

@ccpemily

Camera+ 3.4.3 can crash world generation / save loading due to Unity object access from async long event thread

Camera+ version: 3.4.3.0
RimWorld version: 1.6

After entering a world once, creating/loading another world can repeatedly fail with:

Exception from asynchronous event: UnityEngine.UnityException: ToString can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
[Ref A8B49FDA]
(wrapper managed-to-native) UnityEngine.Object.ToString(UnityEngine.Object)
at UnityEngine.Object.ToString () [0x00001]
at System.String.Format (System.String format, System.Object arg0) [0x00008]
at Verse.MaterialAllocator.Destroy (UnityEngine.Material material) [0x0000d]
at CameraPlus.MarkerCache.Remove (Verse.Pawn pawn) [0x00039]
at CameraPlus.MarkerCache.Clear () [0x0001e]
at CameraPlus.Caches.ClearMarkerState () [0x00023]
at CameraPlus.World_FinalizeInit_Patch.Postfix (RimWorld.Planet.World __instance) [0x0000b]
at RimWorld.Planet.World.FinalizeInit (System.Boolean fromLoad) [0x00017]
at RimWorld.Planet.WorldGenerator.GenerateWorld (...)
at RimWorld.Page_CreateWorldParams.b__20_0 ()
at Verse.LongEventHandler.RunEventFromAnotherThread (System.Action action)

It looks related to commit 3e195a2:
3e195a2

Below are advices by codex:
That commit added Caches.ClearMarkerState() to World_FinalizeInit_Patch.Postfix. In RimWorld, world generation/loading can run
World.FinalizeInit from an async long event thread. ClearMarkerState() reaches MarkerCache.Clear() -> MarkerCache.Remove() -> Verse.MaterialAllocator.Destroy(material), and MaterialAllocator.Destroy formats the Unity Material, which calls
UnityEngine.Object.ToString() off the main thread.

Possible fix: defer marker/material cache cleanup to the main thread, or avoid destroying Unity materials/textures from World.FinalizeInit when
it is running in an async long event thread.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions