Fix crash when resizing navmesh capacity with crowd created for that navmesh

This commit is contained in:
Wojtek Figat
2023-12-18 21:45:27 +01:00
parent bc2e130281
commit 8a94e053a8
3 changed files with 30 additions and 24 deletions

View File

@@ -36,7 +36,7 @@ NavMeshRuntime::NavMeshRuntime(const NavMeshProperties& properties)
NavMeshRuntime::~NavMeshRuntime() NavMeshRuntime::~NavMeshRuntime()
{ {
dtFreeNavMesh(_navMesh); Dispose();
dtFreeNavMeshQuery(_navMeshQuery); dtFreeNavMeshQuery(_navMeshQuery);
} }
@@ -336,9 +336,7 @@ void NavMeshRuntime::SetTileSize(float tileSize)
// Dispose the existing mesh (its invalid) // Dispose the existing mesh (its invalid)
if (_navMesh) if (_navMesh)
{ {
dtFreeNavMesh(_navMesh); Dispose();
_navMesh = nullptr;
_tiles.Clear();
} }
_tileSize = tileSize; _tileSize = tileSize;
@@ -363,14 +361,9 @@ void NavMeshRuntime::EnsureCapacity(int32 tilesToAddCount)
// Ensure to have size assigned // Ensure to have size assigned
ASSERT(_tileSize != 0); ASSERT(_tileSize != 0);
// Fre previous data (if any) // Allocate navmesh and initialize the default query
if (_navMesh) if (!_navMesh)
{ _navMesh = dtAllocNavMesh();
dtFreeNavMesh(_navMesh);
}
// Allocate new navmesh
_navMesh = dtAllocNavMesh();
if (dtStatusFailed(_navMeshQuery->init(_navMesh, MAX_NODES))) if (dtStatusFailed(_navMeshQuery->init(_navMesh, MAX_NODES)))
{ {
LOG(Error, "Failed to initialize navmesh {0}.", Properties.Name); LOG(Error, "Failed to initialize navmesh {0}.", Properties.Name);
@@ -517,7 +510,7 @@ void NavMeshRuntime::RemoveTile(int32 x, int32 y, int32 layer)
} }
} }
void NavMeshRuntime::RemoveTiles(bool (* prediction)(const NavMeshRuntime* navMesh, const NavMeshTile& tile, void* customData), void* userData) void NavMeshRuntime::RemoveTiles(bool (*prediction)(const NavMeshRuntime* navMesh, const NavMeshTile& tile, void* customData), void* userData)
{ {
ScopeLock lock(Locker); ScopeLock lock(Locker);
ASSERT(prediction); ASSERT(prediction);

View File

@@ -208,21 +208,13 @@ dtNavMesh::dtNavMesh() :
dtNavMesh::~dtNavMesh() dtNavMesh::~dtNavMesh()
{ {
for (int i = 0; i < m_maxTiles; ++i) purge();
{
if (m_tiles[i].flags & DT_TILE_FREE_DATA)
{
dtFree(m_tiles[i].data);
m_tiles[i].data = 0;
m_tiles[i].dataSize = 0;
}
}
dtFree(m_posLookup);
dtFree(m_tiles);
} }
dtStatus dtNavMesh::init(const dtNavMeshParams* params) dtStatus dtNavMesh::init(const dtNavMeshParams* params)
{ {
if (m_tiles)
purge();
memcpy(&m_params, params, sizeof(dtNavMeshParams)); memcpy(&m_params, params, sizeof(dtNavMeshParams));
dtVcopy(m_orig, params->orig); dtVcopy(m_orig, params->orig);
m_tileWidth = params->tileWidth; m_tileWidth = params->tileWidth;
@@ -1178,6 +1170,24 @@ int dtNavMesh::getMaxTiles() const
return m_maxTiles; return m_maxTiles;
} }
void dtNavMesh::purge()
{
for (int i = 0; i < m_maxTiles; ++i)
{
if (m_tiles[i].flags & DT_TILE_FREE_DATA)
{
dtFree(m_tiles[i].data);
m_tiles[i].data = 0;
m_tiles[i].dataSize = 0;
}
}
m_maxTiles = 0;
dtFree(m_posLookup);
m_posLookup = 0;
dtFree(m_tiles);
m_tiles = 0;
}
dtMeshTile* dtNavMesh::getTile(int i) dtMeshTile* dtNavMesh::getTile(int i)
{ {
return &m_tiles[i]; return &m_tiles[i];

View File

@@ -613,6 +613,9 @@ private:
dtNavMesh(const dtNavMesh&); dtNavMesh(const dtNavMesh&);
dtNavMesh& operator=(const dtNavMesh&); dtNavMesh& operator=(const dtNavMesh&);
/// Clears all tiles from memory. Can be called before init to rebuild navigation mesh with different parameters.
void purge();
/// Returns pointer to tile in the tile array. /// Returns pointer to tile in the tile array.
dtMeshTile* getTile(int i); dtMeshTile* getTile(int i);