Created
June 30, 2018 11:51
-
-
Save zulfajuniadi/ab63483e44f9f9ae29f3a4581d642e3e to your computer and use it in GitHub Desktop.
Fast Terrain Scanning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using Unity.Collections; | |
using UnityEngine; | |
[System.Serializable] | |
public class Tile | |
{ | |
public int Key; | |
public Vector3 Position; | |
public Vector3 Normal; | |
public float Elevation; | |
public bool Sloped; | |
public Tile (int key, Vector3 position, Vector3 normal, bool sloped) | |
{ | |
Key = key; | |
position.y = Elevation = Mathf.Round (position.y * 10) / 10; | |
Normal = normal; | |
Position = position; | |
Sloped = sloped; | |
} | |
} | |
public class TerrainScanner : MonoBehaviour | |
{ | |
public Dictionary<int, Tile> TilePositions = new Dictionary<int, Tile> (); | |
public LayerMask raycastMask; | |
public Vector2Int MapSize = new Vector2Int (512, 512); | |
private void Start () | |
{ | |
MapTerrain (); | |
} | |
public void MapTerrain () | |
{ | |
var sw = new System.Diagnostics.Stopwatch (); | |
sw.Start (); | |
TilePositions.Clear (); | |
var commandSize = (MapSize.x * MapSize.y); | |
var up = Vector3.up; | |
var down = Vector3.down; | |
var hits = 1; | |
var results = new NativeArray<RaycastHit> (commandSize * hits, Allocator.Temp); | |
var commands = new NativeArray<RaycastCommand> (commandSize, Allocator.Temp); | |
for (int x = 0; x < MapSize.x; x++) | |
{ | |
for (int y = 0; y < MapSize.y; y++) | |
{ | |
var key = GetKey (x, y); | |
var origin = new Vector3 (x, 200, y); | |
commands[key] = new RaycastCommand (origin, down, 300, raycastMask, hits); | |
} | |
} | |
var handle = RaycastCommand.ScheduleBatch (commands, results, MapSize.x); | |
handle.Complete (); | |
commands.Dispose (); | |
for (int x = 0; x < MapSize.x; x++) | |
{ | |
for (int y = 0; y < MapSize.y; y++) | |
{ | |
var position = new Vector3 (x, 0, y); | |
position.y = 0; | |
var key = GetKey (x, y); | |
var result = results[key]; | |
var isSloped = false; | |
var normal = up; | |
if (result.collider) | |
{ | |
position = result.point; | |
normal = result.normal; | |
isSloped = normal != up; | |
} | |
var tile = new Tile (key, position, normal, isSloped); | |
TilePositions[key] = tile; | |
} | |
} | |
results.Dispose (); | |
sw.Stop (); | |
Debug.Log ("Scanning done in " + sw.ElapsedMilliseconds + "ms"); | |
} | |
public Tile GetTileAtPosition (Vector3 position) | |
{ | |
if (TilePositions.Count == 0) return null; | |
var x = Mathf.RoundToInt (position.x); | |
var z = Mathf.RoundToInt (position.z); | |
var key = GetKey (x, z); | |
if (!TilePositions.ContainsKey (key)) return null; | |
return TilePositions[key]; | |
} | |
int GetKey (int x, int y) | |
{ | |
return x * MapSize.x + y; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For a 512 x 512 terain:
Scanning done in 176ms
Minimum Unity Version: 2018.1
Set project to use .net 4
Install the entities package from the Package Manager