CesiumPolygonRasterOverlay crash in native code after Remove + tile refinement (Google Photorealistic 3D Tiles, Unity)

Unity hard-crashes (no managed exception, process killed by OS) shortly after removing a CesiumPolygonRasterOverlay while a Google Photorealistic 3D Tiles tileset is loading/refining tiles. The crash is in CesiumForUnityNative.dll in C++ native code.

This might be related to the Unreal report here: Google Photorealistic 3D Tiles Cause Crashing with CesiumPolygonRasterOverlay polygons populated

That thread identified the crash location as RasterOverlayTile::~RasterOverlayTile() – the ActivatedRasterOverlay is destroyed before the last RasterOverlayTile it created completes. The cesium-native v0.55.0 changelog mentions a fix for exactly this pattern (“Fixed a bug that could cause an ActivatedRasterOverlay to be destroyed before the last RasterOverlayTile it created, leading to a crash”), but a crash is still reproducible on v0.58.0.


Steps to reproduce

A minimal reproduction project is attached: cesium_cutout_polygon_crash.zip (38.0 KB)

  1. Extract and open in Unity 6000.2.15f1
  2. Set CesiumSetup._googleApiKey to a valid key
  3. Enter Play mode
  4. Click “Set Polygon Overlay” button (or press P)
  5. Optionally rotate the camera slightly to trigger tile refinement
  6. Click “Remove Polygon Overlay” button (or press O)
  7. Optionally rotate the camera slightly
  8. Wait a few seconds – Unity hard-crashes

Sometimes it is needed to repeat steps 3 to 7 multiple times and move the camera more to reproduce.

The “Remove” implementation calls Destroy(_polygonRasterOverlay) and Destroy(_polygonObject), which is the standard Unity approach. The crash occurs during subsequent tile loading/refinement in Cesium3DTileset.Update().


Workarounds investigated

We tried several approaches, each reducing crash frequency but none fully eliminating it:

1. Clear polygons list before destroy

_polygonRasterOverlay.polygons?.Clear();
UnityEngine.Object.Destroy(_polygonRasterOverlay);

Slightly reduced frequency.

2. Disable instead of destroy

_polygonRasterOverlay.enabled = false;

Further reduced frequency.

3. Never destroy – reuse with empty spline (most stable)

// "Remove" just sets an empty polygon list instead of destroying:
SetPolygonRasterOverlay(Array.Empty<Point3d>());

The _polygonObject and _polygonRasterOverlay are created once and never destroyed. “Removing” the overlay updates the spline in-place to an empty polygon. This keeps the native ActivatedRasterOverlay alive permanently and has proven the most stable in practice, though we cannot confirm it is fully crash-free under all conditions.


Expected behavior

Removing a CesiumPolygonRasterOverlay component while a tileset is active should not crash.