public void Update() { // Right mouse button. if (Input.GetMouseButtonDown(1)) { // The unity physics way if (CubicTerrain.GetInstance().useMeshColliders) { // Get ready to perform the raycast. RaycastHit hitInfo = new RaycastHit(); Ray cameraRay = this.playerCamera.GetComponent <Camera>().ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)); Debug.DrawRay(cameraRay.origin, cameraRay.direction, Color.red, 100.0f); // Perform the raycast if (Physics.Raycast(cameraRay, out hitInfo, 50, this.detectionMask.value)) { if (hitInfo.collider == null) { return; } // get collider parent Transform chunkTransform = hitInfo.collider.transform.parent; if (chunkTransform != null) { // Chunk hit? CubicTerrainChunk chunk = chunkTransform.GetComponent <CubicTerrainChunk>(); if (chunk != null && !chunk.isDirty) { // Yes, chunk hit! // Delete the clicked block Vector3 block = chunk.GetBlockPosition(hitInfo, -0.5f); chunk.chunkData.SetVoxel((int)block.x, (int)block.y, (int)block.z, -1); } } } } else { // Cubic World Physics way CubicRaycastHitInfo hitInfo = new CubicRaycastHitInfo(); if (CubicPhysics.TerrainRaycastUnprecise(this.playerCamera.GetComponent <Camera>().ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)), 5.0f, out hitInfo)) { // Debug.Log ("Hit: " + hitInfo.hitPoint + ", Block: " + hitInfo.blockHit + ", Face: " + hitInfo.faceHit); // Hit block CubicTerrain.GetInstance().SetBlock((int)hitInfo.blockHit.x, (int)hitInfo.blockHit.y, (int)hitInfo.blockHit.z, -1); } } } }
/// <summary> /// Performs a raycast with the current terrain data. /// Raycasts are performed very simple, this function will move along your ray by adding direction*stepWidth every step. /// In every step it will check if it hit a block and if true it will stop and return the data. /// /// TODO: Implement a better way (more precise!) for raycasting /// </summary> /// <returns><c>true</c>, if the raycast hit a block, <c>false</c> otherwise.</returns> /// <param name="worldspaceStartpoint">Worldspace startpoint.</param> /// <param name="direction">Direction.</param> /// <param name="stepWidth">The step width you want to use for raycasting. the lower this is the more precise the result and slower the calculation will be.</param> /// <param name="length">The length of the ray.</param> /// <param name="hitInfo">The raycast hit info.</param> /// <param name="calculateHitFace">hitFace will only get set if this is true.</param> public static bool TerrainRaycast(Vector3 worldspaceStartpoint, Vector3 direction, float stepWidth, float length, out CubicRaycastHitInfo hitInfo, bool calculateHitFace) { // Initialize bool blockHit = false; float distanceTraveled = 0; Vector3 currentPos = worldspaceStartpoint; hitInfo = new CubicRaycastHitInfo(); Vector3 blockPos = Vector3.zero; CubicTerrain terrain = CubicTerrain.GetInstance(); // Search for blocks on the ray while (!blockHit && distanceTraveled < length) { // Calculate current step data currentPos += direction * stepWidth; distanceTraveled += stepWidth; blockPos = terrain.GetBlockPosition(currentPos); // Check if there is a block at this position if (terrain.HasBlock(blockPos)) { blockHit = true; hitInfo.blockHit = blockPos; hitInfo.hitPoint = currentPos; if (calculateHitFace) { // Get hit face /*LEFT = 0, * RIGHT = 1, * TOP = 2, * BOTTOM = 3, * FRONT = 4, * BACK = 5*/ // Back and forward flipped Vector3[] faceNormals = new Vector3[] { Vector3.left, Vector3.right, Vector3.up, Vector3.down, Vector3.forward, Vector3.back }; // Get block center position Vector3 blockCenterPosition = blockPos + new Vector3(0.5f, 0.5f, 0.5f); // Get shortest distance face. float shortestDistance = stepWidth + 10; int shortestFace = -1; for (int i = 0; i < faceNormals.Length; i++) { // Get distance from hit point to the current normal + blockcenter Vector3 blockNormalPosition = blockCenterPosition + faceNormals[i]; float distance = Vector3.Distance(currentPos, blockNormalPosition); if (shortestDistance > distance) { shortestDistance = distance; shortestFace = i; } } // Get face hitInfo.faceHit = (BlockFace)shortestFace; } } } return(blockHit); }
public void FixedUpdate() { CubicTerrain terrainInstance = CubicTerrain.GetInstance(); // Initialize Vector3 currentPosition = this.transform.position; Vector3 newPosition = this.transform.position; // Add gravity to current velocity this.velocity += this.gravity * Time.deltaTime; // Move based on velocity newPosition += this.velocity * Time.deltaTime; Vector3 realNewPosition = newPosition; Vector3 blockSpaceNewPosition = terrainInstance.GetBlockPosition(newPosition); bool newPositionValid = true; blockSpaceNewPosition.y -= (float)this.characterHeight / 2.0f; newPosition.y = blockSpaceNewPosition.y; // New position valid? for (int i = 0; i < this.characterHeight && newPositionValid; i++) { if (terrainInstance.HasBlock(blockSpaceNewPosition)) { newPositionValid = false; } // Check left, right, front and back Vector3[] checkPositions = new Vector3[] { Vector3.left * 0.5f, Vector3.right * 0.5f, Vector3.forward * 0.5f, Vector3.back * 0.5f }; // Check all directions foreach (Vector3 checkPosition in checkPositions) { Vector3 checkPos = checkPosition + newPosition; if (terrainInstance.HasBlock(terrainInstance.GetBlockPosition(checkPos))) { newPositionValid = false; } } blockSpaceNewPosition.y++; newPosition.y = blockSpaceNewPosition.y; } if (newPositionValid) { this.transform.position = realNewPosition; this.velocity -= this.velocity / 2; } else { this.velocity = Vector3.zero; } }
public void Update() { // Right mouse button. if (Input.GetMouseButtonDown(0)) { // Unity physics if (CubicTerrain.GetInstance().useMeshColliders) { // Get ready to perform the raycast. RaycastHit hitInfo = new RaycastHit(); Ray cameraRay = this.playerCamera.GetComponent <Camera>().ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)); Debug.DrawRay(cameraRay.origin, cameraRay.direction, Color.red, 100.0f); // Perform the raycast if (Physics.Raycast(cameraRay, out hitInfo, 5, this.detectionMask.value)) { if (hitInfo.collider == null) { return; } // get collider parent Transform chunkTransform = hitInfo.collider.transform.parent; if (chunkTransform != null) { // Chunk hit? CubicTerrainChunk chunk = chunkTransform.GetComponent <CubicTerrainChunk>(); if (chunk != null && !chunk.isDirty) { // Yes, chunk hit! BlockHitInfo blockHitInfo = chunk.GetBlockHitInfo(hitInfo); int x = (int)blockHitInfo.hitBlock.x; int y = (int)blockHitInfo.hitBlock.y; int z = (int)blockHitInfo.hitBlock.z; // Which face was hit? calculate target position for the new block switch (blockHitInfo.hitFace) { case BlockFace.LEFT: x -= 1; break; case BlockFace.RIGHT: x += 1; break; case BlockFace.TOP: y += 1; break; case BlockFace.BOTTOM: y -= 1; break; case BlockFace.FRONT: z += 1; break; case BlockFace.BACK: z -= 1; break; } Vector3 chunkPos = chunk.chunkPosition; // Get chunk we want to place the block on if (x < 0) { chunkPos.x -= 1; x = chunk.master.chunkWidth - 1; } if (x >= chunk.master.chunkWidth) { chunkPos.x += 1; x = 0; } if (y < 0) { chunkPos.y -= 1; y = chunk.master.chunkDepth - 1; } if (z >= chunk.master.chunkHeight) { chunkPos.y += 1; y = 0; } if (z < 0) { chunkPos.z -= 1; z = chunk.master.chunkDepth - 1; } if (z >= chunk.master.chunkDepth) { chunkPos.z += 1; z = 0; } // Finally place the object GameObject chunkObject = chunk.master.GetChunkObject((int)chunkPos.x, (int)chunkPos.y, (int)chunkPos.z); chunkObject.GetComponent <CubicTerrainChunk>().chunkData.SetVoxel(x, y, z, (short)this.blockId); } } } } else { // Cubic physics CubicRaycastHitInfo hitInfo = new CubicRaycastHitInfo(); if (CubicPhysics.TerrainRaycastPrecise(this.playerCamera.GetComponent <Camera>().ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)), 5.0f, out hitInfo)) { Debug.Log("Hit: " + hitInfo.hitPoint + ", Block: " + hitInfo.blockHit + ", Face: " + hitInfo.faceHit); // Get block to place position int x = (int)hitInfo.blockHit.x; int y = (int)hitInfo.blockHit.y; int z = (int)hitInfo.blockHit.z; // Which face was hit? calculate target position for the new block switch (hitInfo.faceHit) { case BlockFace.LEFT: x -= 1; break; case BlockFace.RIGHT: x += 1; break; case BlockFace.TOP: y += 1; break; case BlockFace.BOTTOM: y -= 1; break; case BlockFace.FRONT: z += 1; break; case BlockFace.BACK: z -= 1; break; } CubicTerrain.GetInstance().SetBlock(x, y, z, (short)this.blockId); } } } }
public void Update() { bool firstPoint = Input.GetKeyDown(KeyCode.P); bool lastPoint = Input.GetKeyDown(KeyCode.L); bool definePoint = firstPoint || lastPoint; if (this.path != null) { if (this.path.isReady) { Debug.Log("Path found in " + path.runtime + " milliseconds!"); foreach (Vector3 blockPos in this.path.pathData) { CubicTerrain.GetInstance().SetBlock((int)blockPos.x, (int)blockPos.y - 1, (int)blockPos.z, -1); } this.path = null; } else if (!this.path.foundPath) { Debug.Log("Path not found :-( after search for " + path.runtime + " milliseconds!"); } } // Right mouse button. if (definePoint) { if (CubicTerrain.GetInstance().useMeshColliders) { // Get ready to perform the raycast. RaycastHit hitInfo = new RaycastHit(); Ray cameraRay = this.playerCamera.GetComponent <Camera>().ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)); Debug.DrawRay(cameraRay.origin, cameraRay.direction, Color.red, 100.0f); // Perform the raycast if (Physics.Raycast(cameraRay, out hitInfo, 5, this.detectionMask.value)) { if (hitInfo.collider == null) { return; } // get collider parent Transform chunkTransform = hitInfo.collider.transform.parent; if (chunkTransform != null) { // Chunk hit? CubicTerrainChunk chunk = chunkTransform.GetComponent <CubicTerrainChunk>(); if (chunk != null && !chunk.isDirty) { // Yes, chunk hit! BlockHitInfo blockHitInfo = chunk.GetBlockHitInfo(hitInfo); int x = (int)blockHitInfo.hitBlock.x; int y = (int)blockHitInfo.hitBlock.y; int z = (int)blockHitInfo.hitBlock.z; // Which face was hit? calculate target position for the new block switch (blockHitInfo.hitFace) { case BlockFace.LEFT: x -= 1; break; case BlockFace.RIGHT: x += 1; break; case BlockFace.TOP: y += 1; break; case BlockFace.BOTTOM: y -= 1; break; case BlockFace.FRONT: z += 1; break; case BlockFace.BACK: z -= 1; break; } Vector3 chunkPos = chunk.chunkPosition; // Get chunk we want to place the block on if (x < 0) { chunkPos.x -= 1; x = chunk.master.chunkWidth - 1; } if (x >= chunk.master.chunkWidth) { chunkPos.x += 1; x = 0; } if (z < 0) { chunkPos.z -= 1; z = chunk.master.chunkDepth - 1; } if (z >= chunk.master.chunkDepth) { chunkPos.z += 1; z = 0; } // Finally place the object GameObject chunkObject = chunk.master.GetChunkObject((int)chunkPos.x, (int)chunkPos.y, (int)chunkPos.z); chunk = chunkObject.GetComponent <CubicTerrainChunk>(); // Get absolute position Vector3 absoluteVoxelspace = chunk.GetAbsolutePosition(new Vector3(x, y, z)); Debug.Log("Point: " + absoluteVoxelspace); if (firstPoint) { startPoint = absoluteVoxelspace; } else if (lastPoint) { goalPoint = absoluteVoxelspace; } } } } } else { // Cubic World Physics way CubicRaycastHitInfo hitInfo = new CubicRaycastHitInfo(); if (CubicPhysics.TerrainRaycastUnprecise(this.playerCamera.GetComponent <Camera>().ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2)), 5.0f, out hitInfo)) { // Debug.Log ("Hit: " + hitInfo.hitPoint + ", Block: " + hitInfo.blockHit + ", Face: " + hitInfo.faceHit); // Hit block Vector3 topBlock = hitInfo.blockHit + Vector3.up; Debug.Log("Top Block: " + topBlock); if (firstPoint) { startPoint = topBlock; } else if (lastPoint) { goalPoint = topBlock; } } } } if (startPoint != Vector3.zero && goalPoint != Vector3.zero) { Debug.Log("Starting A* path finding. Distance: " + Vector3.Distance(startPoint, goalPoint)); // Start pathfinding CubicPathfinding pathfinder = CubicPathfinding.GetInstance(); this.path = pathfinder.GetPath(startPoint, goalPoint, true); startPoint = Vector3.zero; goalPoint = Vector3.zero; } }