Beispiel #1
0
    //Return random tunnel tendency based on set distribution
    int SelectPieceIndex(TunnelTendency tend)
    {
        int ind = 0;
        switch (tend)
        {
            case TunnelTendency.up: //For up tunnel, more likely to select index 0 or 1
                if (Random.Range(0f, 1f) < 0.25)    //Ex. If value is set to 0.25, there is a 75% chance that we go to the else statement and select an upward sloping tunnel
                {
                    ind = Random.Range(2, 5);
                }
                else
                {
                    ind = Random.Range(0, 2);
                }
                break;

            case TunnelTendency.down:   //For up tunnel, more likely to select index 3 or 4
                if (Random.Range(0f, 1f) < 0.25)
                {
                    ind = Random.Range(0, 3);
                }
                else
                {
                    ind = Random.Range(3, 5);
                }
                break;

            default:       //For normal tunnel, all pieces have equal chance of being selected
                ind = Random.Range(0, 5);
                break;
        }

        return ind;
    }
    //Return random tunnel tendency based on set distribution
    float SelectNextPieceAngle(TunnelTendency tend)
    {
        float ang = 0f;
        switch (tend)
        {
            case TunnelTendency.up: //For up tunnel, more likely to select index 0 or 1
                if (Random.Range(0f, 1f) < 0.25)    //Ex. If value is set to 0.25, there is a 75% chance that we go to the else statement and select an upward sloping tunnel
                {
                    ang = Random.Range(0, maxAngle);
                }
                else
                {
                    ang = Random.Range(-maxAngle, 0);
                }
                break;

            case TunnelTendency.down:   //For up tunnel, more likely to select index 3 or 4
                if (Random.Range(0f, 1f) < 0.25)
                {
                    ang = Random.Range(0, maxAngle);
                }
                else
                {
                    ang = Random.Range(-maxAngle, 0);
                }
                break;

            default:       //For normal tunnel, all pieces have equal chance of being selected
                ang = Random.Range(-maxAngle, maxAngle);
                break;
        }

        return ang;
    }
Beispiel #3
0
    // Generate a mostly horizontal tunnel with some vertical shafts
    void GenerateTunnel(Vector3 startPos, int direction, TunnelTendency vertTend)
    {
        //Initialize
        int floorInd = 2;   //Should be flat/neutral piece index
        int ceilingInd = 2;
        Vector3 floorPos;
        Vector3 ceilingPos;
        Vector3 prevFloorPos;
        Vector3 prevCeilingPos;

        floorPos = startPos;
        floorPos.x += 0.5f * direction;
        ceilingPos = floorPos;
        ceilingPos.y += 1f;

        List<Vector2[]> waterQuads = new List<Vector2[]>();
        List<Vector2> waterSurface = new List<Vector2>();

        bool upShaftAllowed = false;
        bool downShaftAllowed = false;
        int upCoolTimer = 0;
        int downCoolTimer = 0;
        branchCount++;

        int branchNum = branchCount;

        int biomeInd = SelectBiomeMaterial();
        Material biomeMat = biomeMaterials[biomeInd];

        bool startFreeSurface = false;
        bool endFreeSurface = false;
        bool startedFreeSurface = false;

        //if (branchCount > maxBranches)  //If max branches has been reached, don't continue this function. (Other functions currently executing should still finish)
        //    return;

        //Determine tunnel characteristics
        int tunnelLength = Random.Range(minTunnelLength, maxTunnelLength + 1);

        for (int i = 0; i < tunnelLength; i++)
        {

            //Chance to create a shaft
            shaftUp = false;
            shaftDown = false;
            if (upShaftAllowed)
            {
                if (Random.Range(0f, 1f) <= shaftFrequency)
                {
                    //Debug.Log("ShaftUp on iter " + i);
                    shaftUp = true;
                    upShaftAllowed = false;
                }
            }
            else
            {
                upCoolTimer++;
            }
            if (upCoolTimer > shaftCooldown)
            {
                upCoolTimer = 0;
                upShaftAllowed = true;
            }

            if (downShaftAllowed)
            {
                if (Random.Range(0f, 1f) <= shaftFrequency)
                {
                    //Debug.Log("ShaftDown on iter " + i);
                    shaftDown = true;
                    downShaftAllowed = false;
                }
            }
            else
            {
                downCoolTimer++;
            }
            if (downCoolTimer > shaftCooldown)
            {
                downCoolTimer = 0;
                downShaftAllowed = true;
            }

            //Determine next piece type and positions of next pieces
            prevFloorPos = floorPos;
            prevCeilingPos = ceilingPos;

            //Determine start position for next floor piece
            floorPos.y += yOffsets[floorInd] * direction;   //This is y position of end point for previous piece
            //Determine start position for next ceiling piece
            ceilingPos.y += yOffsets[ceilingInd] * direction;   //Account for offset of last piece that was placed. Gives y position at end of piece

            if (!shaftDown)
            {
                //Select next piece type
                if (i == 0)
                {
                    floorInd = 2;
                }
                else
                {
                    floorInd = SelectPieceIndex(vertTend);
                    floorPos.y += yOffsets[floorInd] * direction;   //Account for offset of next piece. Should now be y pos of where center of next piece should go
                }
            }

            else //If shaftDown
            {
                floorInd = 0;
            }

            if (!shaftUp)
            {
                //Select next piece type
                if (i == 0)
                {
                    ceilingInd = 2;
                    ceilingPos = floorPos;
                    ceilingPos.y += tunnelHeight;
                }
                else
                {
                    float yPosTest = 0;
                    bool passed = false;
                    int iter = 0;
                    while (!passed)    //Enforce that ceiling must be at least minimum height above floor
                    {
                        yPosTest = ceilingPos.y;
                        ceilingInd = SelectPieceIndex(vertTend);
                        yPosTest += yOffsets[ceilingInd] * direction; //Account for offset of next piece. Should now be y pos of where center of next piece should go

                        float ht = yPosTest + yOffsets[ceilingInd] * direction - (floorPos.y + yOffsets[floorInd] * direction); //Calculate clearance height

                        if (ht > 0.9f || iter >= 20)
                        {
                            passed = true;
                            if (iter == 20) //If solution not reached, there might not be a solution. Next ceiling piece should be angled up as much as possible to try to create enough space between floor and ceiling
                            {
                                Debug.Log("Passed on iter " + iter + "; Height of " + ht);
                                ceilingInd = 0;
                                yPosTest = ceilingPos.y;
                                yPosTest += yOffsets[ceilingInd] * direction;
                            }
                        }
                        iter++;
                    }
                    ceilingPos.y = yPosTest;
                }
            }

            else //If shaftUp
            {
                ceilingInd = 0;
            }

            //For constant height tunnel
            //ceilingPos = floorPos;
            //ceilingPos.y += tunnelHeight;
            //ceilingInd = floorInd;

            //First check for interference
            //Check for overlap before placing anything

            Vector3 floorStart = floorPos; //Line 1 spans floor piece
            floorStart.x -= (0.5f - clearanceWidth/2) * direction;  //Account for clearance of previous piece (previous vertical pieces can get collided with otherwise)
            floorStart.y -= yOffsets[floorInd] * direction + clearanceWidth / 2; //Use outside edge accounting for clearance
            Vector3 floorEnd = floorPos;
            floorEnd.x += (0.5f + clearanceWidth / 2) * direction;
            floorEnd.y += yOffsets[floorInd] * direction - clearanceWidth / 2;

            Vector3 ceilingStart = ceilingPos; //Line 2 spans ceiling piece
            ceilingStart.x -= (0.5f - clearanceWidth/2) * direction;
            ceilingStart.y -= yOffsets[ceilingInd] * direction - clearanceWidth / 2;
            Vector3 ceilingEnd = ceilingPos;
            ceilingEnd.x += (0.5f + clearanceWidth / 2) * direction;
            ceilingEnd.y += yOffsets[ceilingInd] * direction + clearanceWidth / 2;

            //Debug Lines
            //GameObject ln = GameObject.Instantiate(line);
            //ln.GetComponent<LineRenderer>().SetPosition(0, floorStart);
            //ln.GetComponent<LineRenderer>().SetPosition(1, floorEnd);
            //ln.GetComponent<LineRenderer>().SetPosition(2, ceilingEnd);
            //ln.GetComponent<LineRenderer>().SetPosition(3, ceilingStart);

            if (CheckForOverlap(floorStart, floorEnd, ceilingStart, ceilingEnd, floorEnd, ceilingEnd))
            {
                Debug.Log("Found interference with tunnel placement #" + branchNum);

                goto EndTunnelActions;

            }

            //Keep track of water area using line positions from above
            //Vector4 quad = new Vector4(floorStart.y, ceilingStart.y, floorEnd.y, ceilingEnd.y);
            if (floorStart.y < waterElevation || floorEnd.y < waterElevation)
            {
                bool startWater = false;
                bool endWater = false;

                int numberOfQuads = 1;

                Vector2 waterBottomStart = floorStart;
                Vector2 waterBottomEnd = floorEnd;
                Vector2 waterTopStart = ceilingStart;
                Vector2 waterTopEnd = ceilingEnd;
                Vector2 waterBottomStart2 = floorStart;
                Vector2 waterBottomEnd2 = floorEnd;
                Vector2 waterTopStart2 = ceilingStart;
                Vector2 waterTopEnd2 = ceilingEnd;

                if (i == 0)
                {
                    startFreeSurface = true;
                }

                if (ceilingStart.y < waterElevation && ceilingEnd.y > waterElevation)
                {
                    startFreeSurface = true;
                    numberOfQuads = 2;
                    //First Quad
                    waterTopEnd.y = waterElevation;
                    waterTopEnd.x = ceilingEnd.x - (Mathf.Abs(waterElevation - ceilingEnd.y) * Mathf.Abs(ceilingEnd.x - ceilingStart.x) / Mathf.Abs(ceilingEnd.y - ceilingStart.y));
                    waterBottomEnd.x = waterTopEnd.x;
                    //waterBottomEnd.y = /////Need to finish

                    //Second Quad
                    waterBottomStart2.x = waterTopStart2.x = waterTopEnd.x;
                    waterTopStart2.y = waterTopEnd2.y = waterElevation;
                    waterBottomStart.y = waterBottomEnd.y;

                }
                else if (ceilingStart.y > waterElevation && ceilingEnd.y < waterElevation)
                {
                    endFreeSurface = true;
                    numberOfQuads = 2;
                    //First Quad
                    waterTopStart.y = waterTopEnd.y = waterElevation;
                    waterTopEnd.x = ceilingEnd.x - (Mathf.Abs(waterElevation - ceilingEnd.y) * Mathf.Abs(ceilingEnd.x - ceilingStart.x) / Mathf.Abs(ceilingEnd.y - ceilingStart.y));
                    waterBottomEnd.x = waterTopEnd.x;
                    //waterBottomEnd.y = /////Need to finish
                    //Second Quad
                    waterBottomStart2.x = waterTopStart2.x = waterTopEnd.x;
                    waterTopStart2.y = waterElevation;
                    waterBottomStart.y = waterBottomEnd.y;
                }

                else if (ceilingStart.y > waterElevation && ceilingEnd.y > waterElevation)
                {
                    waterTopStart.y = Mathf.Min(ceilingStart.y, waterElevation);    //Don't allow water to be above water elevation
                    waterTopEnd.y = Mathf.Min(ceilingEnd.y, waterElevation);
                }

                if (floorStart.y > waterElevation && floorEnd.y < waterElevation)
                {
                    startWater = true;
                    waterBottomStart.x = floorEnd.x - (Mathf.Abs(waterElevation - floorEnd.y) * Mathf.Abs(floorEnd.x - floorStart.x) / Mathf.Abs(floorEnd.y - floorStart.y));
                    waterTopStart.x = waterBottomStart.x;
                    //waterTopStart.y = waterElevation;
                }
                else if (floorStart.y < waterElevation && floorEnd.y > waterElevation)
                {
                    endWater = true;
                    endFreeSurface = true;
                    waterBottomEnd.x = floorEnd.x - (Mathf.Abs(waterElevation - floorEnd.y) * Mathf.Abs(floorEnd.x - floorStart.x) / Mathf.Abs(floorEnd.y - floorStart.y));
                    waterTopEnd.x = waterBottomStart.x;
                    waterTopEnd.y = waterElevation;
                }

                //waterTopStart.y = Mathf.Min(ceilingStart.y, waterElevation);    //Don't allow water to be above water elevation
                //waterTopEnd.y = Mathf.Min(ceilingEnd.y, waterElevation);

                if (startWater)
                {
                    waterQuads.Clear();
                    waterSurface.Clear();
                }

                Vector2[] quad = new Vector2[4];
                quad[0] = waterBottomStart;
                quad[1] = waterTopStart;
                quad[2] = waterBottomEnd;
                quad[3] = waterTopEnd;
                waterQuads.Add(quad);

                if (numberOfQuads == 2)
                {
                    Vector2[] quad2 = new Vector2[4];
                    quad2[0] = waterBottomStart2;
                    quad2[1] = waterTopStart2;
                    quad2[2] = waterBottomEnd2;
                    quad2[3] = waterTopEnd2;
                    waterQuads.Add(quad2);
                }
                //Debug.Log("Quad0 " + quad[0] + " Quad1 " + quad[1] + " Quad2 " + quad[2] + " Quad3 " + quad[3]);

                if (startFreeSurface)
                {
                    if (numberOfQuads == 2)
                    {
                        waterSurface.Add(waterTopStart2);
                        //Instantiate(marker, waterTopStart2, Quaternion.identity);
                    }
                    else
                    {
                        waterSurface.Add(waterTopStart);
                        //Instantiate(marker, waterTopStart, Quaternion.identity);
                    }
                    startFreeSurface = false;
                    startedFreeSurface = true;
                }
                if (startedFreeSurface && endFreeSurface)
                {
                    waterSurface.Add(waterTopEnd);
                    startFreeSurface = endFreeSurface = false; //Reset flags
                    //Instantiate(marker, waterTopEnd, Quaternion.identity);
                    startedFreeSurface = false;
                    endFreeSurface = false;
                }

                if (endWater)
                {
                    GameObject nothingObj2 = new GameObject();
                    createWater.CreateWaterBody(waterQuads, waterSurface, direction, nothingObj2);
                }
            }

            if (shaftDown)
            {
                floorPos = prevFloorPos;
            }
            if (shaftUp)
            {
                ceilingPos = prevCeilingPos;
            }

            //Place Background
            Vector3 bottomPos = floorPos;
            Vector3 topPos = ceilingPos;
            int bottomInd = floorInd;
            int topInd = ceilingInd;

            if (shaftDown)
            {
                bottomPos.y += yOffsets[floorInd] * direction; //Account for offset of last piece that was placed
                bottomInd = 2;
                Instantiate(marker, bottomPos, Quaternion.identity);
            }

            if (shaftUp)
            {
                topPos.y += yOffsets[ceilingInd] * direction; //Account for offset of last piece that was placed
                topInd = 2;
                Instantiate(marker, topPos, Quaternion.identity);
            }

            createBackground.CoverHeight(bottomPos, topPos, bottomInd, topInd, biomeInd);

            //Create floor if not doing a shaft
            if (!shaftDown)
            {
                //Place floor
                lastFloor = (GameObject)Instantiate(floorPieces[floorInd], floorPos, Quaternion.identity);
                Renderer[] rendArray = lastFloor.gameObject.GetComponentsInChildren<Renderer>();
                foreach (Renderer rend in rendArray)
                {
                    rend.material = biomeMat;
                }
            }
            else //Create an down shaft
            {
                Vector3 shaftStart = floorPos;
                shaftStart.x -= 0.5f * direction;
                shaftStart.y += yOffsets[floorInd] * direction; //Account for offset of last piece that was placed
                //Debug.Log("StartPos " + shaftStart);
                GenerateShaft(shaftStart, -1, direction, biomeInd);
            }

            //Create ceiling if not doing a shaft
            if (!shaftUp)
            {
                //Place ceiling
                lastCeiling = (GameObject)Instantiate(ceilingPieces[ceilingInd], ceilingPos, Quaternion.identity);
                Renderer[] rendArray = lastCeiling.gameObject.GetComponentsInChildren<Renderer>();
                foreach (Renderer rend in rendArray)
                {
                    rend.material = biomeMat;
                }
            }

            else //Create an up shaft
            {
                Vector3 shaftStart = ceilingPos;
                shaftStart.x -= 0.5f * direction;
                shaftStart.y += yOffsets[ceilingInd] * direction; //Account for offset of last piece that was placed
                GenerateShaft(shaftStart, 1, direction, biomeInd);
            }

            //Place background pieces
            //float highestElev = ceilingPos.y + Mathf.Abs(yOffsets[ceilingInd]);
            //float lowestElev = floorPos.y - Mathf.Abs(yOffsets[floorInd]);
            //Vector3 lowestPoint = floorPos;
            //lowestPoint.y = lowestElev;
            //float coverHeight = highestElev - lowestElev;

            floorPos.x += 1f * direction;
            ceilingPos.x += 1f * direction;

        }
        EndTunnelActions:
        GameObject nothingObj = new GameObject();
        createWater.CreateWaterBody(waterQuads, waterSurface, direction, nothingObj);

        return;
    }
    // Generate a mostly horizontal tunnel with some vertical shafts
    void GenerateTunnel(Vector3 startPos, int direction, TunnelTendency vertTend)
    {
        //Initialize
        float floorSlope = 0f;
        float ceilingSlope = 0f;
        float floorAngle = 0f;
        float ceilingAngle = 0f;
        Vector3 floorStartPos;
        Vector3 ceilingStartPos;
        Vector3 floorEndPos = new Vector3();
        Vector3 ceilingEndPos = new Vector3();;
        Vector3 tunnelFloorStart;
        Vector3 tunnelCeilingStart;
        List<Vector3> floorEndPoints = new List<Vector3>();
        List<Vector3> ceilingEndPoints = new List<Vector3>();
        List<float> floorSlopeList = new List<float>();
        List<float> ceilingSlopeList = new List<float>();
        GameObject Tunnel = new GameObject("Tunnel");
        GameObject FloorPieces = new GameObject("FloorPieces");
        GameObject CeilingPieces = new GameObject("CeilingPieces");
        GameObject WallPieces = new GameObject("WallPieces");
        GameObject BackgroundPieces = new GameObject("BackgroundPieces");
        FloorPieces.transform.SetParent(Tunnel.transform);
        CeilingPieces.transform.SetParent(Tunnel.transform);
        BackgroundPieces.transform.SetParent(Tunnel.transform);
        BackgroundPieces.AddComponent<CreateBackground5>();
        CreateBackground5 createBackground;
        createBackground = BackgroundPieces.GetComponent<CreateBackground5>();

        GameObject parentWaterObj = createWater.SetupWaterObjects();

        floorStartPos = startPos;
        //floorPos.x += 0.5f * direction;
        ceilingStartPos = floorStartPos;
        ceilingStartPos.y += tunnelHeight;

        tunnelFloorStart = floorStartPos;
        tunnelCeilingStart = ceilingStartPos;

        //List<Vector2[]> waterQuads = new List<Vector2[]>();
        //List<Vector2> waterSurface = new List<Vector2>();

        bool upShaftAllowed = false;
        bool downShaftAllowed = false;
        int upCoolTimer = 0;
        int downCoolTimer = 0;
        branchCount++;

        int branchNum = branchCount;

        int biomeInd = SelectBiomeMaterial();
        Material biomeMat = biomeMaterials[biomeInd];

        //bool startFreeSurface = false;
        //bool endFreeSurface = false;
        //bool startedFreeSurface = false;

        //if (branchCount > maxBranches)  //If max branches has been reached, don't continue this function. (Other functions currently executing should still finish)
        //    return;

        //Determine tunnel characteristics
        int tunnelLength = Random.Range(minTunnelLength, maxTunnelLength + 1);

        for (int i = 0; i < tunnelLength; i++)
        {

            //Chance to create a shaft
            shaftUp = false;
            shaftDown = false;
            if (upShaftAllowed)
            {
                if (Random.Range(0f, 1f) <= shaftFrequency)
                {
                    //Debug.Log("ShaftUp on iter " + i);
                    shaftUp = true;
                    upShaftAllowed = false;
                }
            }
            else
            {
                upCoolTimer++;
            }
            if (upCoolTimer > shaftCooldown)
            {
                upCoolTimer = 0;
                upShaftAllowed = true;
            }

            if (downShaftAllowed)
            {
                if (Random.Range(0f, 1f) <= shaftFrequency)
                {
                    //Debug.Log("ShaftDown on iter " + i);
                    shaftDown = true;
                    downShaftAllowed = false;
                }
            }
            else
            {
                downCoolTimer++;
            }
            if (downCoolTimer > shaftCooldown)
            {
                downCoolTimer = 0;
                downShaftAllowed = true;
            }

            //Determine next piece type and positions of next pieces
            floorEndPos = floorStartPos;    //Initialize
            ceilingEndPos = ceilingStartPos;
            floorEndPos.x += 1f * direction;
            ceilingEndPos.x += 1f * direction;
            //Determine start position for next floor piece
            ////floorPos.y += lastFloorSlope * pieceLength;   //This is y position of end point for previous piece
            //Determine start position for next ceiling piece
            ////ceilingPos.y += lastCeilingSlope * pieceLength;   //Account for offset of last piece that was placed. Gives y position at end of piece

            if (!shaftDown)
            {
                //Select next piece type
                if (i == 0)
                {
                    floorAngle = 0f;
                }
                else
                {
                    floorAngle = SelectNextPieceAngle(vertTend);

                }
                //floorSlope = Mathf.Tan(floorAngle * Mathf.Deg2Rad);

            }

            else //If shaftDown
            {
                floorAngle = 0f;
            }
            floorSlope = Mathf.Tan(floorAngle * Mathf.Deg2Rad);
            floorEndPos.y += floorSlope * pieceLength;   //Account for offset of next piece. Should now be y pos of primary surface at end of this piece

            if (!shaftUp)
            {
                //Select next piece type
                if (i == 0)
                {
                    floorAngle = 0f;
                    ceilingStartPos = floorStartPos;
                    ceilingStartPos.y += tunnelHeight;
                }
                else
                {
                    float endPosTest = 0;
                    bool passed = false;
                    int iter = 0;
                    while (!passed)    //Enforce that ceiling must be at least minimum height above floor
                    {
                        endPosTest = ceilingStartPos.y;
                        ceilingAngle = SelectNextPieceAngle(vertTend);  //Select an angle for this piece
                        ceilingSlope = Mathf.Tan(ceilingAngle * Mathf.Deg2Rad);
                        endPosTest += ceilingSlope * pieceLength; //Should now be y pos of end of ceiling piece
                        //Check where yPosTest is if having problems

                        float ht = endPosTest - floorEndPos.y; //Calculate clearance height. Should be height between end points of floor and ceiling

                        if (ht > 0.9f || iter >= 20)
                        {
                            passed = true;
                            if (iter == 20) //If solution not reached, there might not be a solution. Next ceiling piece should be angled up as much as possible to try to create enough space between floor and ceiling
                            {
                                Debug.Log("Passed on iter " + iter + "; Height of " + ht);
                                ceilingAngle = maxAngle;
                            }
                        }
                        iter++;
                    }
                    //ceilingPos.y = yPosTest;
                }
            }

            else //If shaftUp
            {
                ceilingAngle = 0f;
            }
            ceilingSlope = Mathf.Tan(ceilingAngle * Mathf.Deg2Rad);
            ceilingEndPos.y += ceilingSlope * pieceLength;

            //For constant height tunnel
            //ceilingPos = floorPos;
            //ceilingPos.y += tunnelHeight;
            //ceilingInd = floorInd;

            //First check for interference
            //Check for overlap before placing anything

            //At this point floorPos should be end point for current/about to be placed piece. prevFloorPos should be start point for current/about to be placed piece

            Vector3 floorStart = floorStartPos; //Line 1 spans floor piece middle to end
            floorStart.x += clearanceWidth * direction;
            floorStart.y -= clearanceWidth; //Use outside edge accounting for clearance
            Vector3 floorEnd = floorEndPos;
            floorEnd.x += clearanceWidth * direction;
            floorEnd.y -= clearanceWidth;

            Vector3 ceilingStart = ceilingStartPos; //Line 2 spans ceiling piece middle to end
            ceilingStart.x += clearanceWidth * direction;
            ceilingStart.y += clearanceWidth;
            Vector3 ceilingEnd = ceilingEndPos;
            ceilingEnd.x += clearanceWidth * direction;
            ceilingEnd.y += clearanceWidth;

            //Debug Lines
            //GameObject ln = GameObject.Instantiate(line);
            //ln.GetComponent<LineRenderer>().SetPosition(0, floorStart);
            //ln.GetComponent<LineRenderer>().SetPosition(1, floorEnd);
            //ln.GetComponent<LineRenderer>().SetPosition(2, ceilingEnd);
            //ln.GetComponent<LineRenderer>().SetPosition(3, ceilingStart);

            if (CheckForOverlap(floorStart, floorEnd, ceilingStart, ceilingEnd, floorEnd, ceilingEnd))
            {
                Debug.Log("Found interference with tunnel placement #" + branchNum);

                //floorEndPoints.RemoveAt(floorEndPoints.Count-1);
                //ceilingEndPoints.RemoveAt(floorEndPoints.Count - 1);
                //floorSlopeList.RemoveAt(floorEndPoints.Count - 1);
                //ceilingSlopeList.RemoveAt(floorEndPoints.Count - 1);

                floorEndPos = floorStartPos;    //Set end point back to start and end tunnel there
                ceilingEndPos = ceilingStartPos;

                goto EndTunnelActions;

            }

            //Create floor if not doing a shaft
            if (!shaftDown)
            {
                //Place floor
                Vector3 objLoc = new Vector3(floorStartPos.x + pieceLength / 2f * direction, (floorStartPos.y + floorEndPos.y) / 2f, 0f);
                Vector3 meshStart = new Vector3(-pieceLength / 2f * direction, (floorStartPos.y - floorEndPos.y) / 2f, 0f);
                floorObj = (GameObject)Instantiate(tunnelPiecePrefab, objLoc, Quaternion.identity);
                floorObj.GetComponent<CreatePieceMesh>().InitializePiece(floorAngle, meshStart, direction, -1, pieceThickness, pieceThickness, 2.0f, biomeMat, 9);
                //Renderer[] rendArray = floorObj.gameObject.GetComponentsInChildren<Renderer>();
                //foreach (Renderer rend in rendArray)
                //{
                //    rend.material = biomeMat;
                //}
                floorObj.transform.SetParent(FloorPieces.transform);
            }
            else //Create a down shaft
            {
                Vector3 shaftStart = floorStartPos;
                //shaftStart.x -= 0.5f * direction;
                ////shaftStart.y += yOffsets[floorInd] * direction; //Account for offset of last piece that was placed
                //Debug.Log("StartPos " + shaftStart);
                GenerateShaft(shaftStart, -1, direction, biomeInd, parentWaterObj);
            }

            //Create ceiling if not doing a shaft
            if (!shaftUp)
            {
                //Place ceiling
                Vector3 objLoc = new Vector3(ceilingStartPos.x + pieceLength / 2f * direction, (ceilingStartPos.y + ceilingEndPos.y) / 2f, 0f);
                Vector3 meshStart = new Vector3(-pieceLength / 2f * direction, (ceilingStartPos.y - ceilingEndPos.y) / 2f, 0f);
                ceilingObj = (GameObject)Instantiate(tunnelPiecePrefab, objLoc, Quaternion.identity);
                ceilingObj.GetComponent<CreatePieceMesh>().InitializePiece(ceilingAngle, meshStart, direction, 1, pieceThickness, pieceThickness, 2.0f, biomeMat, 9);
                //Renderer[] rendArray = ceilingObj.gameObject.GetComponentsInChildren<Renderer>();
                //foreach (Renderer rend in rendArray)
                //{
                //    rend.material = biomeMat;
                //}
                ceilingObj.transform.SetParent(CeilingPieces.transform);
            }

            else //Create an up shaft
            {
                Vector3 shaftStart = ceilingStartPos;
                //shaftStart.x -= 0.5f * direction;
                //shaftStart.y += yOffsets[ceilingInd] * direction; //Account for offset of last piece that was placed
                GenerateShaft(shaftStart, 1, direction, biomeInd, parentWaterObj);
            }

            //Add to end points list that will be used for background generation
            floorEndPoints.Add(floorEndPos);
            ceilingEndPoints.Add(ceilingEndPos);
            floorSlopeList.Add(floorSlope);
            ceilingSlopeList.Add(ceilingSlope);

            floorStartPos = floorEndPos;    //Starting point for next piece will be end point for current piece
            ceilingStartPos = ceilingEndPos;

        }

        EndTunnelActions:

        float endHt = ceilingEndPos.y - floorEndPos.y;
        int endPieceCount = (int)(endHt / pieceLength) + 1;

        for (int i = 0; i < endPieceCount; i++)
        {
            Vector3 objLoc = floorEndPos;
            objLoc.y += i * pieceLength + pieceLength / 2 - 0.2f;

            Vector3 meshStart = new Vector3(-pieceLength / 2, 0f, 0f); //Mesh start is relative to instantiated object

            float rotation;
            if (direction == 1)   //If up shaft then end will be ceiling piece
            {
                rotation = -90f;
            }
            else
            {
                rotation = 90f;
            }
            GameObject thisObj = (GameObject)Instantiate(tunnelPiecePrefab, objLoc, Quaternion.identity);
            thisObj.GetComponent<CreatePieceMesh>().InitializePiece(0f, meshStart, 1, 1, 0.2f, 0.2f, 2.0f, biomeMat, 13);    //Create a 0 degree piece with direction of 1 that will be turned by 90 degrees to become vertical piece
            //Renderer[] rendArray = thisObj.gameObject.GetComponentsInChildren<Renderer>();
            //foreach (Renderer rend in rendArray)
            //{
            //    rend.material = biomeMat;
            //}
            thisObj.transform.Rotate(0f, 0f, rotation);

            thisObj.transform.SetParent(WallPieces.transform);

            worldResources.PopulateTunnel(Tunnel, direction);
        }

        createBackground.PlaceBackground(tunnelFloorStart, tunnelCeilingStart, floorEndPoints, floorSlopeList, ceilingEndPoints, ceilingSlopeList, direction, biomeInd, BackgroundPieces);
        createWater.CreateTunnelWater(tunnelFloorStart, tunnelCeilingStart, floorEndPoints, floorSlopeList, ceilingEndPoints, ceilingSlopeList, direction, parentWaterObj);
        //return;
    }