Skip to content

Commit 9a436ac

Browse files
authored
Merge pull request #570 from CesiumGS/catch-em-all
Catch exceptions in `UnityPrepareRendererResources::free`
2 parents e610fb5 + 849e798 commit 9a436ac

File tree

2 files changed

+43
-34
lines changed

2 files changed

+43
-34
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
##### Fixes :wrench:
1010

1111
- Fixed a bug where credits would not display in the Game tab after entering Play Mode.
12+
- Improved stability during AppDomain reloads by catching exceptions thrown while freeing tiles.
1213

1314
## v1.15.5 - 2025-04-01
1415

native~/Runtime/src/UnityPrepareRendererResources.cpp

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,45 +1716,53 @@ void UnityPrepareRendererResources::free(
17161716
Cesium3DTilesSelection::Tile& tile,
17171717
void* pLoadThreadResult,
17181718
void* pMainThreadResult) noexcept {
1719-
if (pLoadThreadResult) {
1720-
LoadThreadResult* pTyped =
1721-
static_cast<LoadThreadResult*>(pLoadThreadResult);
1722-
for (int32_t i = 0, len = pTyped->meshes.Length(); i < len; ++i) {
1723-
CesiumForUnity::CesiumObjectPools::MeshPool().Release(pTyped->meshes[i]);
1719+
try {
1720+
if (pLoadThreadResult) {
1721+
LoadThreadResult* pTyped =
1722+
static_cast<LoadThreadResult*>(pLoadThreadResult);
1723+
for (int32_t i = 0, len = pTyped->meshes.Length(); i < len; ++i) {
1724+
CesiumForUnity::CesiumObjectPools::MeshPool().Release(
1725+
pTyped->meshes[i]);
1726+
}
1727+
delete pTyped;
17241728
}
1725-
delete pTyped;
1726-
}
17271729

1728-
if (pMainThreadResult) {
1729-
std::unique_ptr<CesiumGltfGameObject> pCesiumGameObject(
1730-
static_cast<CesiumGltfGameObject*>(pMainThreadResult));
1731-
1732-
// It's possible that the game object has already been destroyed. In which
1733-
// case Unity will throw a MissingReferenceException if we try to use it. So
1734-
// don't do that.
1735-
if (*pCesiumGameObject->pGameObject != nullptr) {
1736-
auto metadataComponent =
1737-
pCesiumGameObject->pGameObject
1738-
->GetComponentInParent<DotNet::CesiumForUnity::CesiumMetadata>();
1739-
1740-
UnityEngine::Transform parentTransform =
1741-
pCesiumGameObject->pGameObject->transform();
1742-
1743-
// Destroying primitives will remove them from the child list, so
1744-
// work backwards.
1745-
for (int32_t i = parentTransform.childCount() - 1; i >= 0; --i) {
1746-
UnityEngine::GameObject primitiveGameObject =
1747-
parentTransform.GetChild(i).gameObject();
1748-
freePrimitiveGameObject(primitiveGameObject, metadataComponent);
1749-
UnityLifetime::Destroy(primitiveGameObject);
1750-
}
1730+
if (pMainThreadResult) {
1731+
std::unique_ptr<CesiumGltfGameObject> pCesiumGameObject(
1732+
static_cast<CesiumGltfGameObject*>(pMainThreadResult));
1733+
1734+
// It's possible that the game object has already been destroyed. In which
1735+
// case Unity will throw a MissingReferenceException if we try to use it.
1736+
// So don't do that.
1737+
if (*pCesiumGameObject->pGameObject != nullptr) {
1738+
auto metadataComponent =
1739+
pCesiumGameObject->pGameObject->GetComponentInParent<
1740+
DotNet::CesiumForUnity::CesiumMetadata>();
1741+
1742+
UnityEngine::Transform parentTransform =
1743+
pCesiumGameObject->pGameObject->transform();
1744+
1745+
// Destroying primitives will remove them from the child list, so
1746+
// work backwards.
1747+
for (int32_t i = parentTransform.childCount() - 1; i >= 0; --i) {
1748+
UnityEngine::GameObject primitiveGameObject =
1749+
parentTransform.GetChild(i).gameObject();
1750+
freePrimitiveGameObject(primitiveGameObject, metadataComponent);
1751+
UnityLifetime::Destroy(primitiveGameObject);
1752+
}
17511753

1752-
if (metadataComponent == nullptr) {
1753-
freeModelMetadata(*pCesiumGameObject->pGameObject);
1754-
}
1754+
if (metadataComponent == nullptr) {
1755+
freeModelMetadata(*pCesiumGameObject->pGameObject);
1756+
}
17551757

1756-
UnityLifetime::Destroy(*pCesiumGameObject->pGameObject);
1758+
UnityLifetime::Destroy(*pCesiumGameObject->pGameObject);
1759+
}
17571760
}
1761+
} catch (...) {
1762+
// This function is a hotspot for crashes caused by AppDomain reloads.
1763+
UnityEngine::Debug::Log(
1764+
System::String("A tile was not cleaned up properly, probably due to an "
1765+
"AppDomain reload."));
17581766
}
17591767
}
17601768

0 commit comments

Comments
 (0)