Ejemplo n.º 1
0
    /// <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);
    }
Ejemplo n.º 2
0
    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;
        }
    }