Advertisement
Guest User

Terrain Manager Script

a guest
Jan 9th, 2016
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.75 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class TerrainManager : MonoBehaviour, ICameraObserver {
  6.  
  7.     public Terrain mainTerrain;
  8.     public float terrainChangeRate = 0.0001f;
  9.     public int brushArea = 20;
  10.     public static int viewDistance = 9;
  11.     public static Vector2 VECTOR_WILDCARD = new Vector2(-10000, -10000);
  12.  
  13.     int resolutionX;
  14.     int resolutionY;
  15.     float[,] heights;
  16.     int heightEdit = 1;
  17.  
  18.     //Chunks
  19.     List<Vector2> loadedChunks = new List<Vector2>();
  20.     Vector2[] visibleChunks = null;
  21.     Terrain[] chunkGraphics = new Terrain[viewDistance];
  22.     Vector2 curChunkIndex = new Vector2();
  23.     int chunkSizeX = 256;
  24.     int chunkSizeY = 256;
  25.  
  26.     // Use this for initialization
  27.     void Start () {
  28.         resolutionX = mainTerrain.terrainData.heightmapWidth;
  29.         resolutionY = mainTerrain.terrainData.heightmapHeight;
  30.  
  31.         heights = mainTerrain.terrainData.GetHeights(0, 0, resolutionX, resolutionY);
  32.  
  33.         Camera.main.GetComponent<RTSCamera>().Subscribe(this);
  34.         GameObject world = new GameObject();
  35.         world.name = "World";
  36.  
  37.         for (int i = 0; i < viewDistance; i++)
  38.         {
  39.             GameObject go = new GameObject();
  40.             go.name = "Chunk_" + i;
  41.             go.transform.SetParent(world.transform);
  42.  
  43.             chunkGraphics[i] = go.AddComponent<Terrain>();
  44.  
  45.             chunkGraphics[i].terrainData = new TerrainData();
  46.             go.AddComponent<TerrainCollider>().terrainData = chunkGraphics[i].terrainData;
  47.  
  48.             chunkGraphics[i].terrainData.size = new Vector3((int)(chunkSizeX / 4), 600, (int)(chunkSizeY / 4));
  49.             chunkGraphics[i].terrainData.heightmapResolution = (int)(chunkSizeX / 2);
  50.         }
  51.         onCameraMove(Camera.main.transform.position);
  52.     }
  53.    
  54.     // Update is called once per frame
  55.     void Update () {
  56.         if (Input.GetMouseButton(0))
  57.         {
  58.             RaycastHit hit;
  59.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  60.             if (Physics.Raycast(ray, out hit))
  61.             {
  62.                 editTerrainHeight(hit.point, terrainChangeRate, brushArea);
  63.             }
  64.         }
  65.     }
  66.  
  67.     void editTerrainHeight(Vector3 position, float amount, int diameter)
  68.     {
  69.         int terrainPosX = (int)((position.x / mainTerrain.terrainData.size.x) * resolutionX);
  70.         int terrainPosY = (int)((position.z / mainTerrain.terrainData.size.z) * resolutionY);
  71.  
  72.         float[,] heightChange = new float[diameter, diameter];
  73.  
  74.         int radius = diameter / 2;
  75.  
  76.         if (Input.GetKey(KeyCode.LeftShift))
  77.         {
  78.             heightEdit = -1;
  79.         }
  80.         else
  81.         {
  82.             heightEdit = 1;
  83.         }
  84.         amount = amount * heightEdit;
  85.  
  86.         for (int x = 0; x < diameter; x++)
  87.         {
  88.             for (int y = 0; y < diameter; y++)
  89.             {
  90.                 int x2 = x - radius;
  91.                 int y2 = y - radius;
  92.                 heightChange[y, x] = heights[terrainPosY + y2, terrainPosX + x2] + amount;
  93.                 heights[terrainPosY + y2, terrainPosX + x2] = heightChange[y, x];
  94.             }
  95.         }
  96.  
  97.         mainTerrain.terrainData.SetHeights(terrainPosX - radius, terrainPosY - radius, heightChange);
  98.     }
  99.  
  100.     public void onCameraMove(Vector3 newCameraPosition)
  101.     {
  102.         int chunkIndexX = Mathf.FloorToInt(newCameraPosition.x / chunkSizeX);
  103.         int chunkIndexY = Mathf.FloorToInt(newCameraPosition.z / chunkSizeY);
  104.  
  105.         if (curChunkIndex.x == chunkIndexX && curChunkIndex.y == chunkIndexY)
  106.         {
  107.             return;
  108.         }
  109.  
  110.         curChunkIndex.x = chunkIndexX;
  111.         curChunkIndex.y = chunkIndexY;
  112.  
  113.         Vector2[] newVisibleChunks = new Vector2[viewDistance];
  114.  
  115.         newVisibleChunks[0] = new Vector2(chunkIndexX - 1, chunkIndexY +1);
  116.         newVisibleChunks[1] = new Vector2(chunkIndexX, chunkIndexY +1);
  117.         newVisibleChunks[2] = new Vector2(chunkIndexX + 1, chunkIndexY +1);
  118.  
  119.         newVisibleChunks[3] = new Vector2(chunkIndexX -1, chunkIndexY);
  120.         newVisibleChunks[4] = new Vector2(chunkIndexX, chunkIndexY);
  121.         newVisibleChunks[5] = new Vector2(chunkIndexX + 1, chunkIndexY);
  122.  
  123.         newVisibleChunks[6] = new Vector2(chunkIndexX - 1, chunkIndexY -1);
  124.         newVisibleChunks[7] = new Vector2(chunkIndexX, chunkIndexY -1);
  125.         newVisibleChunks[8] = new Vector2(chunkIndexX + 1, chunkIndexY -1);
  126.  
  127.         Terrain[] newChunkGraphics = new Terrain[viewDistance];
  128.         List<int> freeTerrains = new List<int>();
  129.         List<int> loadingIndexes = new List<int>();
  130.  
  131.         for (int i = 0; i < viewDistance; i++)
  132.         {
  133.             bool found = false;
  134.  
  135.             for (int j = 0; j < viewDistance; j++)
  136.             {
  137.                 if (visibleChunks == null)
  138.                 {
  139.                     break;
  140.                 }
  141.                 if (newVisibleChunks[i].Equals(visibleChunks[j]))
  142.                 {
  143.                     visibleChunks[j] = VECTOR_WILDCARD;
  144.                     newChunkGraphics[i] = chunkGraphics[j];
  145.  
  146.                     found = true;
  147.                     break;
  148.                 }
  149.             }
  150.             if (!found)
  151.             {
  152.                 loadingIndexes.Add(i);
  153.             }
  154.         }
  155.  
  156.         if (visibleChunks != null)
  157.         {
  158.             for (int i = 0; i < viewDistance; i++)
  159.             {
  160.                 if (visibleChunks[i] != VECTOR_WILDCARD)
  161.                 {
  162.                     freeTerrains.Add(i);
  163.                     saveChunkToMemory(chunkGraphics[i], visibleChunks[i]);
  164.                 }
  165.             }
  166.         }
  167.         else
  168.         {
  169.             for (int i = 0; i < viewDistance; i++)
  170.             {
  171.                     freeTerrains.Add(i);
  172.             }
  173.         }
  174.  
  175.         for (int i = 0; i < loadingIndexes.Count; i++)
  176.         {
  177.             loadChunkFromMemory(newVisibleChunks[loadingIndexes[i]], freeTerrains[i]);
  178.             newChunkGraphics[loadingIndexes[i]] = chunkGraphics[freeTerrains[i]];
  179.         }
  180.  
  181.         visibleChunks = newVisibleChunks;
  182.         chunkGraphics = newChunkGraphics;
  183.     }
  184.  
  185.     void loadChunkFromMemory(Vector2 cordIndex, int graphicIndex)
  186.     {
  187.         bool found = false;
  188.         foreach (Vector2 v in loadedChunks)
  189.         {
  190.             if (v == cordIndex)
  191.             {
  192.                 found = true;
  193.                 break;
  194.             }
  195.         }
  196.         GameObject terrainGO;
  197.         if (!found)
  198.         {
  199.             terrainGO = generateChunk(cordIndex, graphicIndex);
  200.         }
  201.         else
  202.         {
  203.             //Load Chunk from Memory
  204.             Debug.Log("Loading Chunk(" + cordIndex.x + "," + cordIndex.y + ")");
  205.  
  206.             terrainGO = chunkGraphics[graphicIndex].gameObject;
  207.         }
  208.  
  209.         terrainGO.transform.position = new Vector3(chunkSizeX * cordIndex.x, 0, chunkSizeY * cordIndex.y);
  210.  
  211.  
  212.     }
  213.  
  214.     GameObject generateChunk(Vector2 cordIndex, int graphicIndex)
  215.     {
  216.         GameObject terrainGO = chunkGraphics[graphicIndex].gameObject;
  217.  
  218.         loadedChunks.Add(cordIndex);
  219.  
  220.         setTerrainHeightMap(terrainGO.GetComponent<Terrain>(), cordIndex);
  221.  
  222.         return terrainGO;
  223.     }
  224.  
  225.     void setTerrainHeightMap(Terrain terrain, Vector2 cordIndex)
  226.     {
  227.         float[,] heights = new float[terrain.terrainData.heightmapHeight, terrain.terrainData.heightmapWidth];
  228.  
  229.         heights[0, 0] = 0.5f;
  230.         heights[terrain.terrainData.heightmapWidth - 1, 0] = 0.5f;
  231.         heights[0, terrain.terrainData.heightmapHeight - 1] = 0.5f;
  232.         heights[terrain.terrainData.heightmapWidth - 1, terrain.terrainData.heightmapHeight - 1] = 0.5f;
  233.  
  234.         heights = diamondSquare(heights, 0, 0, terrain.terrainData.heightmapWidth - 1, 0);
  235.  
  236.         terrain.terrainData.SetHeights(0, 0, heights);
  237.     }
  238.  
  239.     float[,] getTerrainHeightMap(Vector2 cordIndex)
  240.     {
  241.           return null;
  242.     }
  243.  
  244.     float[,] diamondSquare(float[,] heights, int offSetX, int offSetY, int squareSize, int depth)
  245.     {
  246.         if (squareSize == 1)
  247.         {
  248.             return heights;
  249.         }
  250.        
  251.         float topLeft = heights[offSetY, offSetX];
  252.         float topRight = heights[offSetY, offSetX + squareSize];
  253.         float bottomLeft = heights[offSetY + squareSize, offSetX];
  254.         float bottomRight = heights[offSetY + squareSize, offSetX + squareSize];
  255.  
  256.         int size = squareSize / 2;
  257.  
  258.         if (topLeft == 0 || topRight == 0 || bottomLeft == 0 || bottomRight == 0)
  259.         {
  260.             Debug.LogError("One or more Corner Seeds have not been set..");
  261.         }
  262.  
  263.         if (heights[offSetY + size, offSetX + size] == 0)
  264.         {
  265.             heights[offSetY + size, offSetX + size] = getRandomHeight(depth + (int)averagePoints(topLeft, topRight, bottomLeft, bottomRight));
  266.         }
  267.         float centrePoint = heights[offSetY + size, offSetX + size];
  268.  
  269.         //left Diamond
  270.         float runningAverage = averagePoints(topLeft, centrePoint, bottomLeft);
  271.  
  272.         if (offSetX - size > 0 && heights[offSetY + size, offSetX - size] != 0)
  273.         {
  274.             runningAverage = averagePoints(topLeft, centrePoint, bottomLeft, heights[offSetY + size, offSetX - size]);
  275.         }
  276.  
  277.         if (heights[offSetY + size, offSetX] == 0)
  278.         {
  279.             heights[offSetY + size, offSetX] = runningAverage + getRandomHeight(depth);
  280.         }
  281.  
  282.         //right Diamond
  283.         runningAverage = averagePoints(topRight, centrePoint, bottomRight);
  284.  
  285.         if (offSetX + (squareSize * 1.5f) < heights.GetLength(1) && heights[offSetY + size, offSetX + (int)(squareSize * 1.5f)] != 0)
  286.         {
  287.             runningAverage = averagePoints(topRight, centrePoint, bottomRight, heights[offSetY + size, offSetX + (int)(squareSize * 1.5f)]);
  288.         }
  289.  
  290.         if (heights[offSetY + size, offSetX + squareSize] == 0)
  291.         {
  292.             heights[offSetY + size, offSetX + squareSize] = runningAverage + getRandomHeight(depth);
  293.         }
  294.  
  295.         //top Diamond
  296.         runningAverage = averagePoints(topLeft, centrePoint, topRight);
  297.  
  298.         if (offSetY - size > 0 && heights[offSetY - size, offSetX + size] != 0)
  299.         {
  300.             runningAverage = averagePoints(topLeft, centrePoint, topRight, heights[offSetY - size, offSetX + size]);
  301.         }
  302.  
  303.         if (heights[offSetY, offSetX + size] == 0)
  304.         {
  305.             heights[offSetY, offSetX + size] = runningAverage + getRandomHeight(depth);
  306.         }
  307.  
  308.         //bottom Diamond
  309.         runningAverage = averagePoints(bottomRight, centrePoint, bottomLeft);
  310.  
  311.         if (offSetY + (squareSize * 1.5f) < heights.GetLength(0) && heights[offSetY + (int)(squareSize * 1.5f), offSetX + size] != 0)
  312.         {
  313.             runningAverage = averagePoints(bottomRight, centrePoint, topRight, heights[offSetY + (int)(squareSize * 1.5f), offSetX + size]);
  314.         }
  315.  
  316.         if (heights[offSetY + squareSize, offSetX + size] == 0)
  317.         {
  318.             heights[offSetY + squareSize, offSetX + size] = runningAverage + getRandomHeight(depth);
  319.         }
  320.  
  321.         heights = diamondSquare(heights, offSetX, offSetY, size, depth + 1);
  322.         heights = diamondSquare(heights, offSetX + size, offSetY, size, depth + 1);
  323.         heights = diamondSquare(heights, offSetX, offSetY + size, size, depth + 1);
  324.         heights = diamondSquare(heights, offSetX + size, offSetY + size, size, depth + 1);
  325.  
  326.         return heights;
  327.  
  328.      }
  329.  
  330.     float averagePoints(float p1, float p2, float p3, float p4)
  331.     {
  332.         return (p1 + p2 + p3 + p4) * 0.25f;
  333.     }
  334.  
  335.     float averagePoints(float p1, float p2, float p3)
  336.     {
  337.         return (p1 + p2 + p3) * 0.3333f;
  338.     }
  339.  
  340.     float getRandomHeight(int depth)
  341.     {
  342.         return Random.Range(-0.1f, 0.0f) / Mathf.Pow(2, depth);
  343.     }
  344.  
  345.     void saveChunkToMemory(Terrain chunk, Vector2 index)
  346.     {
  347.         Debug.Log("Unloading Chunk(" + index.x + "," + index.y + ")");
  348.     }
  349. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement