public void GenerateTerrain()
        {
            GetHills();
            GetTerrain();

            if (alignHills)
            {
                AutoAlignHills();
            }

            foreach (var terr in terrains)
            {
                Vector3 center = terr.GetComponent <Transform>().position;
                float[,] tab    = new float[terr.terrainData.heightmapResolution, terr.terrainData.heightmapResolution];
                float[,] coeffs = new float[terr.terrainData.heightmapResolution, terr.terrainData.heightmapResolution];
                // bool[,] insideHill = new bool[terr.terrainData.heightmapResolution, terr.terrainData.heightmapResolution];
                for (int i = 0; i < terr.terrainData.heightmapResolution; i++)
                {
                    for (int j = 0; j < terr.terrainData.heightmapResolution; j++)
                    {
                        float x = (float)(j) / (terr.terrainData.heightmapResolution - 1) * (terr.terrainData.size.x) + center.x;
                        float z = (float)(i) / (terr.terrainData.heightmapResolution - 1) * (terr.terrainData.size.z) + center.z;
                        coeffs[i, j] = 2;
                        // int hillsCount = 0;
                        // float terrainHeight = 0;
                        for (int ii = 0; ii < hills.Count; ii++)
                        {
                            Transform hillTransform = hills[ii].GetComponent <Transform>();
                            Hill      hill          = hillsList[ii];
                            float     inrunTerrain  = hills[ii].inrunTerrain;
                            Vector3   pointOnHill   = hillTransform.InverseTransformPoint(new Vector3(x, 0, z));

                            float hillY = 0;
                            float b     = 15;
                            float c     = 0;

                            if (pointOnHill.x < hill.A.x)
                            {
                                c     = hill.A.x + inrunFlatLength - pointOnHill.x;
                                hillY = hill.A.y * inrunTerrain - hill.s;
                                b     = hill.b1 / 2;
                            }
                            else if (pointOnHill.x < hill.T.x)
                            {
                                hillY = hill.Inrun(pointOnHill.x) * inrunTerrain - hill.s;
                                if (hill.A.x <= pointOnHill.x)
                                {
                                    b = hill.bK;
                                }
                                b = Mathf.Lerp(hill.b2, hill.b1, pointOnHill.x / hill.A.x) / 2;
                            }
                            else if (hill.T.x <= pointOnHill.x && pointOnHill.x <= hill.U.x)
                            {
                                hillY = hill.LandingArea(pointOnHill.x);
                                b     = (pointOnHill.x <= hill.K.x ? (hill.b2 / 2) + pointOnHill.x / hill.K.x * ((hill.bK - hill.b2) / 2) :
                                         pointOnHill.x >= hill.U.x ? (hill.bU / 2) : (hill.bK / 2) + (pointOnHill.x - hill.K.x) / (hill.U.x - hill.K.x) * ((hill.bU - hill.bK) / 2));
                            }
                            else if (pointOnHill.x <= hill.U.x + hill.a)
                            {
                                hillY = hill.U.y;
                                b     = hill.bU / 2;
                            }
                            else
                            {
                                c     = pointOnHill.x - hill.U.x - hill.a;
                                hillY = hill.U.y;
                            }

                            hillY += hillTransform.position.y;

                            // float terrainY = 200 * Mathf.PerlinNoise(x / 200.0f + 2000, z / 200.0f + 2000);
                            float terrainY = hill.U.y + hillTransform.GetComponent <Transform>().position.y;
                            if (terrainBase == TerrainBase.PerlinNoise)
                            {
                                terrainY = 200 * Mathf.PerlinNoise(x / 200.0f + 2000, z / 200.0f + 2000);
                            }
                            else if (terrainBase == TerrainBase.currentTerrain)
                            {
                                terrainY = terr.terrainData.GetHeight(j, i) + center.y;
                                // terrainY = coeffs[i, j] + center.y;
                            }

                            float blendFactor = Mathf.SmoothStep(0, 1, Mathf.Clamp01(new Vector2(Mathf.Clamp01((Mathf.Abs(pointOnHill.z) - b) / offset), Mathf.Clamp01(c / offset)).magnitude));
                            // float blendFactor = Mathf.Clamp01(new Vector2(Mathf.Clamp01((Mathf.Abs(pointOnHill.z) - b) / offset), Mathf.Clamp01(c / offset)).magnitude);
                            float y = hillY * (1 - blendFactor) + terrainY * blendFactor;
                            y = (y - center.y - 1) / terr.terrainData.size.y;
                            if (blendFactor < coeffs[i, j])
                            {
                                coeffs[i, j] = blendFactor;
                                tab[i, j]    = y;
                            }
                            // if (insideHill[i, j] == false) { tab[i, j] = y; }

                            // if (blendFactor == 0) { insideHill[i, j] = true; }
                        }
                    }
                }
                terr.terrainData.SetHeights(0, 0, tab);
            }
        }
        public void GenerateMesh()
        {
            hill.SetValues(profileData.Value);
            inrunTerrain         = profileData.Value.terrainSteepness;
            generateGateStairsL  = profileData.Value.gateStairsLeft;
            generateGateStairsR  = profileData.Value.gateStairsRight;
            generateInrunStairsL = profileData.Value.inrunStairsLeft;
            generateInrunStairsR = profileData.Value.inrunStairsRight;
            inrunStairsAngle     = profileData.Value.inrunStairsAngle;

            GenerateInrunCollider();
            GenerateInrunTrack();
            GenerateLandingAreaCollider();
            GenerateLandingArea();

            GenerateGateStairs(gateStairsL, 0, generateGateStairsL);
            GenerateGateStairs(gateStairsR, 1, generateGateStairsR);
            var stepsCount = Mathf.RoundToInt((hill.A.y - hill.T.y) / inrunStairsStepHeight);

            inrunStairsStepHeight = (hill.A.y - hill.T.y) / stepsCount;
            GenerateInrunStairs(inrunStairsL, 0, generateInrunStairsL, generateGateStairsL, stepsCount);
            GenerateInrunStairs(inrunStairsR, 1, generateInrunStairsR, generateGateStairsR, stepsCount);
            GenerateLandingAreaGuardrail(landingAreaGuardrailL, 0, generateLandingAreaGuardrailL);
            GenerateLandingAreaGuardrail(landingAreaGuardrailR, 1, generateLandingAreaGuardrailR);
            GenerateInrunGuardrail(inrunGuardrailL, 0, true);
            GenerateInrunGuardrail(inrunGuardrailR, 1, true);
            GenerateInrunOuterGuardrail(inrunOuterGuardrailL, 0, true, generateGateStairsL);
            GenerateInrunOuterGuardrail(inrunOuterGuardrailR, 1, true, generateGateStairsR);
            GenerateInrunConstruction();
            GenerateMarks();

            if (generateTerrain)
            {
                // Debug.Log("GENERATING TERRAIN");
                GetTerrain();
                // Transform hillTransform = GetComponent<Transform>().transform;
                const float offset          = 300f;
                const float inrunFlatLength = 5f;
                //Terrain
                foreach (var terr in terrains)
                {
                    var center = terr.GetComponent <Transform>().position;
                    var tab    = new float[terr.terrainData.heightmapResolution,
                                           terr.terrainData.heightmapResolution];
                    for (var i = 0; i < terr.terrainData.heightmapResolution; i++)
                    {
                        for (var j = 0; j < terr.terrainData.heightmapResolution; j++)
                        {
                            var x = (float)(j) / (terr.terrainData.heightmapResolution - 1) *
                                    (terr.terrainData.size.x) + center.x;
                            var z = (float)(i) / (terr.terrainData.heightmapResolution - 1) *
                                    (terr.terrainData.size.z) + center.z;


                            float hillY = 0;
                            float b     = 15;
                            float c     = 0;

                            if (x < hill.A.x)
                            {
                                c     = hill.A.x + inrunFlatLength - x;
                                hillY = hill.A.y * inrunTerrain - hill.s;
                            }
                            else if (x < hill.T.x)
                            {
                                hillY = hill.Inrun(x) * inrunTerrain - hill.s;
                                if (hill.A.x <= x)
                                {
                                    b = 15;
                                }
                            }
                            else if (hill.T.x <= x && x <= hill.U.x)
                            {
                                hillY = hill.LandingArea(x);
                                b     = 15;
                            }
                            else if (x <= hill.U.x + hill.a)
                            {
                                hillY = hill.U.y;
                                b     = 15;
                            }
                            else
                            {
                                c     = x - hill.U.x - hill.a;
                                hillY = hill.U.y;
                            }

                            // float terrainY = 200 * Mathf.PerlinNoise(x / 200.0f + 2000, z / 200.0f + 2000);
                            var terrainY = hill.U.y;
                            if (terrainBase == TerrainBase.PerlinNoise)
                            {
                                terrainY = 200 * Mathf.PerlinNoise(x / 200.0f + 2000, z / 200.0f + 2000);
                            }
                            else if (terrainBase == TerrainBase.currentTerrain)
                            {
                                terrainY = terr.terrainData.GetHeight(j, i) + center.y;
                            }

                            var blendFactor = Mathf.SmoothStep(0, 1,
                                                               Mathf.Clamp01(new Vector2(Mathf.Clamp01((Mathf.Abs(z) - b) / offset),
                                                                                         Mathf.Clamp01(c / offset)).magnitude));
                            var y = hillY * (1 - blendFactor) + terrainY * blendFactor;

                            // y += (Mathf.Abs((Mathf.Abs(z) - b)) <= 50 ? 2 * Mathf.Abs((Mathf.Abs(z) - b)) : 100) * 0.5f);


                            y = (y - center.y - 1) / terr.terrainData.size.y;


                            // if (i == 200 && j == 200) Debug.Log(x + " " + y);
                            // Debug.Log(x + " " + y);

                            tab[i, j] = Mathf.Clamp(y, 0, 1);
                        }
                    }

                    terr.terrainData.SetHeights(0, 0, tab);
                }
            }

            if (saveMesh)
            {
                SaveMesh(inrun.gObj, "Inrun", true);
                SaveMesh(inrun.gObj, "InrunTrack");
                SaveMesh(landingArea.gObj, "LandingAreaCollider", true);
                SaveMesh(landingArea.gObj, "LandingArea");
                SaveMesh(gateStairsL.gObj, "GateStairsL");
                SaveMesh(gateStairsR.gObj, "GateStairsR");
                SaveMesh(inrunStairsL.gObj, "InrunStairsL");
                SaveMesh(inrunStairsR.gObj, "InrunStairsR");
                SaveMesh(landingAreaGuardrailL.gObj, "LandingAreaGuardrailL");
                SaveMesh(landingAreaGuardrailR.gObj, "LandingAreaGuardrailR");
                SaveMesh(inrunConstruction.gObj, "InrunConstruction");
                SaveMesh(digitsMarks.gObj, "DigitsMarks");
            }

            SetGate(hill, 1);
            DestroyLamps();
            if (time == 0)
            {
                sunLight.intensity    = 0.1f;
                RenderSettings.skybox = nightSkybox;
                GenerateLamps();
            }
            else if (time == 1)
            {
                sunLight.intensity    = 1f;
                RenderSettings.skybox = daySkybox;
            }
        }