public void initFields() { instance = this; voxelEngine = new VoxelManager(); entityEngine = new EntityManager(); Cursor.visible = false; EngineInstance = this; ChunkManagerInstance = GetComponent <ChunkManager>(); WorldName = lWorldName; UpdateWorldPath(); BlocksPath = lBlocksPath; Blocks = lBlocks; TargetFPS = lTargetFPS; MaxChunkSaves = lMaxChunkSaves; MaxChunkDataRequests = lMaxChunkDataRequests; TextureUnit = lTextureUnit; TexturePadding = lTexturePadding; GenerateColliders = lGenerateColliders; ShowBorderFaces = lShowBorderFaces; EnableMultiplayer = lEnableMultiplayer; MultiplayerTrackPosition = lMultiplayerTrackPosition; SaveVoxelData = lSaveVoxelData; GenerateMeshes = lGenerateMeshes; ChunkSpawnDistance = lChunkSpawnDistance; HeightRange = lHeightRange; ChunkDespawnDistance = lChunkDespawnDistance; SendCameraLookEvents = lSendCameraLookEvents; SendCursorEvents = lSendCursorEvents; ChunkSideLength = lChunkSideLength; SquaredSideLength = lChunkSideLength * lChunkSideLength; }
public void Update() { // don't load chunks if engine isn't initialized yet if (!MasterEngine.getInstance().Initialized || !ChunkManager.Initialized) { return; } // don't load chunks if multiplayer is enabled but the connection isn't established yet if (MasterEngine.getInstance().EnableMultiplayer) { if (!Network.isClient && !Network.isServer) { return; } } // track which chunk we're currently in. If it's different from previous frame, spawn chunks at current position. currentPos = MasterEngine.getInstance().PositionToChunkIndex(transform.position); if (currentPos.IsEqual(LastPos) == false) { ChunkManager.SpawnChunks(currentPos.x, currentPos.y, currentPos.z); // (Multiplayer) update server position if (MasterEngine.getInstance().EnableMultiplayer&& MasterEngine.getInstance().MultiplayerTrackPosition&& MasterEngine.getInstance().UniblocksNetwork != null) { UniblocksClient.UpdatePlayerPosition(currentPos); } } LastPos = currentPos; }
// ==== maintenance =========================================================================================== public void Awake() // chunk initialization (load/generate data, set position, etc.) // Set variables { ChunkIndex = new Index(transform.position); SideLength = MasterEngine.getInstance().ChunkSideLength; SquaredSideLength = SideLength * SideLength; NeighborChunks = new Chunk [6]; // 0 = up, 1 = down, 2 = right, 3 = left, 4 = forward, 5 = back MeshCreator = GetComponent <ChunkMeshCreator>(); Fresh = true; // Register chunk ChunkManager.RegisterChunk(this); // Clear the voxel data VoxelData = new ushort[SideLength * SideLength * SideLength]; // Set actual position transform.position = ChunkIndex.ToVector3() * SideLength; // multiply by scale transform.position = new Vector3(transform.position.x * transform.localScale.x, transform.position.y * transform.localScale.y, transform.position.z * transform.localScale.z); // Grab voxel data if (MasterEngine.getInstance().EnableMultiplayer&& !Network.isServer) { StartCoroutine(RequestVoxelData()); // if multiplayer, get data from server } else if (MasterEngine.getInstance().SaveVoxelData&& TryLoadVoxelData() == true) { // data is loaded through TryLoadVoxelData() } else { GenerateVoxelData(); } }
private IEnumerator SpawnMissingChunks(int originX, int originY, int originZ, int range) { int heightRange = MasterEngine.getInstance().HeightRange; ChunkUpdateQueue = new List <Chunk>(); // clear update queue - it will be repopulated again in the correct order in the following loop // flag chunks not in range for removal ChunksToDestroy = new List <Chunk>(); foreach (Chunk chunk in Chunks.Values) { if (Vector2.Distance(new Vector2(chunk.ChunkIndex.x, chunk.ChunkIndex.z), new Vector2(originX, originZ)) > range + MasterEngine.getInstance().ChunkDespawnDistance) { ChunksToDestroy.Add(chunk); } else if (Mathf.Abs(chunk.ChunkIndex.y - originY) > range + MasterEngine.getInstance().ChunkDespawnDistance) // destroy chunks outside of vertical range { ChunksToDestroy.Add(chunk); } } // main loop for (int currentLoop = 0; currentLoop <= range; currentLoop++) { for (var x = originX - currentLoop; x <= originX + currentLoop; x++) // iterate through all potential chunk indexes within range { for (var y = originY - currentLoop; y <= originY + currentLoop; y++) { for (var z = originZ - currentLoop; z <= originZ + currentLoop; z++) { if (Mathf.Abs(y) <= heightRange) // skip chunks outside of height range { if (Mathf.Abs(originX - x) + Mathf.Abs(originZ - z) < range * 1.3f) // skip corners // pause loop while the queue is not empty { while (ChunkUpdateQueue.Count > 0) { ProcessChunkQueue(); if (frameStopwatch.Elapsed.TotalSeconds >= targetFrameDuration) { yield return(new WaitForEndOfFrame()); } } Chunk currentChunk = ChunkManager.GetChunkComponent(x, y, z); // chunks that already exist but haven't had their mesh built yet should be added to the update queue if (currentChunk != null) { // chunks without meshes spawned by server should be changed to regular chunks if (currentChunk.DisableMesh || currentChunk.EnableTimeout) { currentChunk.DisableMesh = false; currentChunk.EnableTimeout = false; currentChunk.Fresh = true; } if (currentChunk.Fresh) { // spawn neighbor chunks for (int d = 0; d < 6; d++) { Index neighborIndex = currentChunk.ChunkIndex.GetAdjacentIndex((Direction)d); GameObject neighborChunk = GetChunk(neighborIndex); if (neighborChunk == null) { neighborChunk = Instantiate(ChunkObject, neighborIndex.ToVector3(), transform.rotation) as GameObject; } currentChunk.NeighborChunks[d] = neighborChunk.GetComponent <Chunk>(); // always add the neighbor to NeighborChunks, in case it's not there already // continue loop in next frame if the current frame time is exceeded if (frameStopwatch.Elapsed.TotalSeconds >= targetFrameDuration) { yield return(new WaitForEndOfFrame()); } if (StopSpawning) { EndSequence(); yield break; } } if (currentChunk != null) { currentChunk.AddToQueueWhenReady(); } } } else // if chunk doesn't exist, create new chunk (it adds itself to the update queue when its data is ready) // spawn chunk { GameObject newChunk = Instantiate(ChunkObject, new Vector3(x, y, z), transform.rotation) as GameObject; // Spawn a new chunk. currentChunk = newChunk.GetComponent <Chunk>(); // spawn neighbor chunks if they're not spawned yet for (int d = 0; d < 6; d++) { Index neighborIndex = currentChunk.ChunkIndex.GetAdjacentIndex((Direction)d); GameObject neighborChunk = GetChunk(neighborIndex); if (neighborChunk == null) { neighborChunk = Instantiate(ChunkObject, neighborIndex.ToVector3(), transform.rotation) as GameObject; } currentChunk.NeighborChunks[d] = neighborChunk.GetComponent <Chunk>(); // always add the neighbor to NeighborChunks, in case it's not there already // continue loop in next frame if the current frame time is exceeded if (frameStopwatch.Elapsed.TotalSeconds >= targetFrameDuration) { yield return(new WaitForEndOfFrame()); } if (StopSpawning) { EndSequence(); yield break; } } if (currentChunk != null) { currentChunk.AddToQueueWhenReady(); } } } } // continue loop in next frame if the current frame time is exceeded if (frameStopwatch.Elapsed.TotalSeconds >= targetFrameDuration) { yield return(new WaitForEndOfFrame()); } if (StopSpawning) { EndSequence(); yield break; } } } } } yield return(new WaitForEndOfFrame()); EndSequence(); }
private void OnDestroy() { ChunkManager.UnregisterChunk(this); }