public void ClearChunk(int x, int y, int z) { int a = (x >> (size - 1)) & 1; int b = (y >> (size - 1)) & 1; int c = (z >> (size - 1)) & 1; int index = a * 2 * 2 + b * 2 + c; if (IsNull(index)) { return; } if (size == 1) { Chunk chunk = children[index] as Chunk; #if UNITY_EDITOR if (Application.isPlaying) { GameObject.Destroy(chunk.gameObject); } else { GameObject.DestroyImmediate(chunk.gameObject); } #else GameObject.Destroy(chunk.gameObject); #endif children[index] = null; } else { BlockGroup group = children[index] as BlockGroup; group.ClearChunk(x, y, z); if (group.IsEmpty()) { children[index] = null; } } }
public void UnloadDistantChunks(int x, int y, int z, int radius) { float groupRadius = 1 << (size - 1); float rootTwo = 1.414213562373095f; float r = radius * rootTwo; float r2 = r * r; float c2 = (0.5f * rootTwo) * (0.5f * rootTwo); Vector3 pos = new Vector3(); pos.x = this.x + groupRadius; pos.y = this.y + groupRadius; pos.z = this.z + groupRadius; Vector3 center = new Vector3(); center.x = x + 0.5f; center.y = y + 0.5f; center.z = z + 0.5f; // If group is completely outside radius, unload it float unloadRadius = groupRadius * rootTwo * groupRadius * rootTwo; if ((pos - center).sqrMagnitude >= r2 + unloadRadius) { Clear(); return; } // If group is completely inside radius, ignore it if ((pos - center).magnitude + groupRadius * rootTwo <= r) { return; } // Check children for (int i = 0; i < 8; i++) { if (IsNull(i)) { continue; } if (size == 1) { Chunk c = children[i] as Chunk; pos.x = c.chunkX + 0.5f; pos.y = c.chunkY + 0.5f; pos.z = c.chunkZ + 0.5f; // If chunk is completely outside radius, unload it if ((pos - center).sqrMagnitude >= r2 + c2) { #if UNITY_EDITOR if (Application.isPlaying) { GameObject.Destroy(c.gameObject); } else { GameObject.DestroyImmediate(c.gameObject); } #else GameObject.Destroy(c.gameObject); #endif children[i] = null; } } else { BlockGroup group = children[i] as BlockGroup; group.UnloadDistantChunks(x, y, z, radius); if (group.IsEmpty()) { children[i] = null; } } } }