Advertisement
443eb9

Untitled

Sep 10th, 2023 (edited)
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.80 KB | None | 0 0
  1. using HexagonSurvive.Environment.Components;
  2. using HexagonSurvive.Map.Components;
  3. using Lib;
  4. using Unity.Collections;
  5. using Unity.Entities;
  6. using Unity.Mathematics;
  7.  
  8. namespace HexagonSurvive.Map.Aspects
  9. {
  10.     public readonly partial struct HexMapAspect : IAspect
  11.     {
  12.         public readonly Entity self;
  13.  
  14.         private readonly RefRW<HexMapData> _mapData;
  15.         private readonly RefRO<EnvironmentData> _envData;
  16.         private readonly RefRW<HexMapRandom> _random;
  17.  
  18.         public float3 Position => _mapData.ValueRO.basicProp.position;
  19.  
  20.         public HexMapData MapData => _mapData.ValueRO;
  21.         public EnvironmentData EnvData => _envData.ValueRO;
  22.         public Random Random => _random.ValueRW.random;
  23.         public FastNoiseLite Noise => _random.ValueRO.noise;
  24.  
  25.         public NativeHashMap<int3, Entity> Units
  26.         {
  27.             get => _mapData.ValueRO.units;
  28.             set => _mapData.ValueRW.units = value;
  29.         }
  30.     }
  31. }
  32.  
  33. ----------------------------------
  34.  
  35. // allocates in line 109
  36. // add elements in line 219
  37.  
  38. using HexagonSurvive.Constants;
  39. using HexagonSurvive.Containers.ECS;
  40. using HexagonSurvive.Containers.ECS.Models;
  41. using HexagonSurvive.Environment.Aspects;
  42. using HexagonSurvive.Environment.Enums;
  43. using HexagonSurvive.Extensions.ECS;
  44. using HexagonSurvive.Map.Aspects;
  45. using HexagonSurvive.Map.Enums;
  46. using HexagonSurvive.Map.Properties;
  47. using Lib;
  48. using Unity.Burst;
  49. using Unity.Collections;
  50. using Unity.Entities;
  51. using Unity.Mathematics;
  52. using Unity.Transforms;
  53. using Random = Unity.Mathematics.Random;
  54.  
  55. namespace HexagonSurvive.Map.Systems
  56. {
  57.     [UpdateInGroup(typeof(InitializationSystemGroup))]
  58.     public partial struct HexMapInitSystem : ISystem
  59.     {
  60.         private Random _random;
  61.         private HexMapAspect _map;
  62.         private FastNoiseLite _noise;
  63.         private HexMapPrefabs _prefabs;
  64.         private EntityCommandBuffer _ecb;
  65.  
  66.         private NativeArray<float2> _unitDirections;
  67.         private NativeArray<float2> _chunkDirections;
  68.         private DynamicBuffer<TreePrefabBuffer> _treePrefabs;
  69.  
  70.         private const float Sin60 = 0.8660254f;
  71.         private const float CenterToSide = CenterToVertex * Sin60;
  72.         private const float CenterToVertex = GlobalConstants.HexUnitSideLength;
  73.  
  74.         [BurstCompile]
  75.         public void OnCreate(ref SystemState state)
  76.         {
  77.             state.RequireForUpdate<EntityContainerData>();
  78.         }
  79.  
  80.         public void OnUpdate(ref SystemState state)
  81.         {
  82.             state.Enabled = false;
  83.             Generate(ref state);
  84.         }
  85.  
  86.         [BurstCompile]
  87.         public void OnDestroy(ref SystemState state)
  88.         {
  89.             _map.MapData.units.Dispose();
  90.         }
  91.  
  92.         private void Generate(ref SystemState state)
  93.         {
  94.             foreach (HexMapAspect hexMapAspect in SystemAPI.Query<HexMapAspect>())
  95.             {
  96.                 _map = hexMapAspect;
  97.                 Initialize(ref state);
  98.                 GenerateWaterSurface(ref state);
  99.                 GenerateMap(ref state);
  100.                 CleanUp();
  101.             }
  102.         }
  103.  
  104.         private void Initialize(ref SystemState state)
  105.         {
  106.             _ecb = new EntityCommandBuffer(Allocator.Temp);
  107.             _noise = new FastNoiseLite((int)_map.MapData.basicProp.seed);
  108.             _random = new Random(_map.MapData.basicProp.seed);
  109.             _map.Units = new NativeHashMap<int3, Entity>();
  110.             EntityContainerData containerData = SystemAPI.GetSingleton<EntityContainerData>();
  111.             _prefabs = containerData.hexMapPrefabs;
  112.             _treePrefabs = SystemAPI.GetBuffer<TreePrefabBuffer>(containerData.container);
  113.  
  114.             _unitDirections = new NativeArray<float2>(6, Allocator.Temp);
  115.             _unitDirections[0] = new float2(-Sin60, 3 / 2f) * CenterToVertex;
  116.             _unitDirections[1] = new float2(-2 * Sin60, 0) * CenterToVertex;
  117.             _unitDirections[2] = new float2(-Sin60, -3 / 2f) * CenterToVertex;
  118.             _unitDirections[3] = new float2(Sin60, -3 / 2f) * CenterToVertex;
  119.             _unitDirections[4] = new float2(2 * Sin60, 0) * CenterToVertex;
  120.             _unitDirections[5] = new float2(Sin60, 3 / 2f) * CenterToVertex;
  121.  
  122.             float chunkRadius = _map.MapData.basicProp.chunkRadius;
  123.             _chunkDirections = new NativeArray<float2>(6, Allocator.Temp);
  124.             _chunkDirections[0] = new float2(Sin60 * 3 * chunkRadius - Sin60, 3 / 2f * (chunkRadius - 1)) * CenterToVertex;
  125.             _chunkDirections[1] = new float2(CenterToSide, 3 * CenterToVertex * chunkRadius - 3 / 2f * CenterToVertex);
  126.             _chunkDirections[2] = new float2(2 * CenterToSide - 3 * CenterToSide * chunkRadius, 3 / 2f * CenterToVertex * chunkRadius);
  127.             _chunkDirections[3] = -new float2(Sin60 * 3 * chunkRadius - Sin60, 3 / 2f * (chunkRadius - 1)) * CenterToVertex;
  128.             _chunkDirections[4] = -new float2(CenterToSide, 3 * CenterToVertex * chunkRadius - 3 / 2f * CenterToVertex);
  129.             _chunkDirections[5] = -new float2(2 * CenterToSide - 3 * CenterToSide * chunkRadius, 3 / 2f * CenterToVertex * chunkRadius);
  130.         }
  131.  
  132.         /// <summary>
  133.         /// 生成区块拼接成为地图
  134.         /// </summary>
  135.         private void GenerateMap(ref SystemState state)
  136.         {
  137.             float2 mapCenter = new float2(_map.Position.x, _map.Position.z);
  138.             GenerateChunk(ref state, float2.zero);
  139.  
  140.             for (int r = 1; r < _map.MapData.basicProp.mapRadius; r++)
  141.             {
  142.                 float2 curCenter = mapCenter + _chunkDirections[4] * r;
  143.  
  144.                 foreach (float2 dir in _chunkDirections)
  145.                 {
  146.                     for (int hex = 0; hex < r; hex++)
  147.                     {
  148.                         GenerateChunk(ref state, curCenter);
  149.                         curCenter += dir;
  150.                     }
  151.                 }
  152.             }
  153.         }
  154.  
  155.         /// <summary>
  156.         /// 生成六边形单元生成区块
  157.         /// </summary>
  158.         /// <param name="state">ECS SystemState</param>
  159.         /// <param name="center">区块中心,即中心六边形的中心</param>
  160.         /// <returns></returns>
  161.         private void GenerateChunk(ref SystemState state, float2 center)
  162.         {
  163.             InstantiateUnit(ref state, center);
  164.  
  165.             for (int r = 1; r < _map.MapData.basicProp.chunkRadius; r++)
  166.             {
  167.                 float2 curCenter = new float2(center.x + r * CenterToSide * 2, center.y);
  168.  
  169.                 foreach (float2 dir in _unitDirections)
  170.                 {
  171.                     for (int hex = 0; hex < r; hex++)
  172.                     {
  173.                         InstantiateUnit(ref state, curCenter);
  174.                         curCenter += dir;
  175.                     }
  176.                 }
  177.             }
  178.         }
  179.  
  180.         /// <summary>
  181.         /// 生成六边形单元
  182.         /// </summary>
  183.         /// <param name="state">ECS SystemState</param>
  184.         /// <param name="pos">生成位置</param>
  185.         /// <returns></returns>
  186.         private void InstantiateUnit(ref SystemState state, float2 pos)
  187.         {
  188.             Entity hexUnit = state.EntityManager.Instantiate(_prefabs.hexUnit);
  189.             HexUnitAspect unitAspect = SystemAPI.GetAspect<HexUnitAspect>(hexUnit);
  190.  
  191.             float height = GetUnitHeight(pos);
  192.             int altitude = StepAltitude(height);
  193.             TerrainNoiseProperties settings = _map.MapData.tnProp;
  194.             float unitHeight = altitude * settings.stepHeight + settings.baseHeight;
  195.             Biome biome = height > settings.seaLevel
  196.                 ? GetBiomeLand(unitAspect, pos, unitHeight)
  197.                 : GetBiomeWater(unitAspect, pos, unitHeight);
  198.  
  199.             unitAspect.AdjustData
  200.             (
  201.                 altitude,
  202.                 unitHeight / 2,
  203.                 unitHeight > _map.MapData.tnProp.seaLevel,
  204.                 biome
  205.             );
  206.             unitAspect.Position = new float3(pos.x, unitHeight / 4, pos.y);
  207.             unitAspect.NonUniformScale = new float3(1, unitHeight / 2, 1);
  208.  
  209.             CalculateCoordinates(unitAspect);
  210.             GenerateVegetation(ref state, unitAspect);
  211.         }
  212.  
  213.         private void CalculateCoordinates(HexUnitAspect unit)
  214.         {
  215.             float3 p = unit.Position;
  216.             int x = Round(p.x / MathConstants.Sqrt3 / GlobalConstants.HexUnitSideLength * 2);
  217.             int z = Round(p.z / 1.5f / GlobalConstants.HexUnitSideLength);
  218.             unit.Coordinate = new int3((x - z) / 2, z, (-x - z) / 2);
  219.             _map.Units.Add(unit.Coordinate, unit.self);
  220.         }
  221.  
  222.         private int Round(float x) =>
  223.             math.frac(x) > 0.5 ? (int)x + 1 : (int)x;
  224.  
  225.         /// <summary>
  226.         /// 使海拔数值阶梯化
  227.         /// </summary>
  228.         /// <param name="altitude">原始海拔</param>
  229.         /// <returns>阶梯化后的海拔等级</returns>
  230.         private int StepAltitude(float altitude)
  231.         {
  232.             TerrainNoiseProperties settings = _map.MapData.tnProp;
  233.             float refAltitude = altitude - settings.baseHeight;
  234.  
  235.             for (int i = 0; i < settings.terrainSteps; i++)
  236.             {
  237.                 if (refAltitude < i * settings.altitudePerStep)
  238.                     return i;
  239.             }
  240.  
  241.             return settings.terrainSteps;
  242.         }
  243.  
  244.         /// <summary>
  245.         /// 生成陆地气候
  246.         /// </summary>
  247.         /// <param name="unitAspect">目标六边形</param>
  248.         /// <param name="pos">六边形位置</param>
  249.         /// <param name="altitude">六边形海拔,即噪声值</param>
  250.         /// <returns>六边形高度</returns>
  251.         private Biome GetBiomeLand(HexUnitAspect unitAspect, float2 pos, float altitude)
  252.         {
  253.             return Biome.Plains;
  254.         }
  255.  
  256.         /// <summary>
  257.         /// 生成水面气候,并重新调整六边形单元的高度
  258.         /// </summary>
  259.         /// <param name="unitAspect">目标六边形</param>
  260.         /// <param name="pos">六边形位置</param>
  261.         /// <param name="altitude">六边形海拔,即噪声值</param>
  262.         /// <returns>六边形高度</returns>
  263.         private Biome GetBiomeWater(HexUnitAspect unitAspect, float2 pos, float altitude)
  264.         {
  265.             return Biome.River;
  266.         }
  267.  
  268.         // /// <summary>
  269.         // /// 获取当前位置的生物群系噪声值
  270.         // /// </summary>
  271.         // /// <param name="pos">六边形位置</param>
  272.         // /// <param name="altitude">海拔</param>
  273.         // /// <returns>0: 温度(现实温度) 1: 降水(0-1) 2: 特别程度(0-1)</returns>
  274.         // private float[] GetBiomeNoiseValue(Vector2 pos, float altitude)
  275.         // {
  276.         //     _noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2S);
  277.         //     BiomeNoiseSettings settings = _map.Data.biomeSettings;
  278.         //
  279.         //     _noise.SetSeed((int)_mapMono.seed + _random.Int(0, int.MaxValue));
  280.         //     Vector2 tempNoisePos = pos * settings.temperatureFrequency + settings.temperatureOffset;
  281.         //     float tempNoise = (_noise.GetNoise(tempNoisePos.x, tempNoisePos.y) + 1) / 2;
  282.         //     tempNoise = Mathf.Pow(tempNoise, settings.temperaturePower);
  283.         //
  284.         //     _noise.SetSeed((int)_mapMono.seed + _random.Int(0, int.MaxValue));
  285.         //     Vector2 precipNoisePos = pos * settings.precipitationFrequency + settings.precipitationOffset;
  286.         //     float precipNoise = (_noise.GetNoise(precipNoisePos.x, precipNoisePos.y) + 1) / 2;
  287.         //     precipNoise = Mathf.Pow(precipNoise, settings.precipitationPower);
  288.         //
  289.         //     _noise.SetSeed((int)_mapMono.seed + _random.Int(0, int.MaxValue));
  290.         //     Vector2 peculiarityPos = pos * settings.peculiarityFrequency + settings.peculiarityOffset;
  291.         //     float peculiarity = (_noise.GetNoise(peculiarityPos.x, peculiarityPos.y) + 1) / 2;
  292.         //     peculiarity = Mathf.Pow(peculiarity, settings.peculiarityPower);
  293.         //
  294.         //     _noise.SetSeed((int)_mapMono.seed);
  295.         //     float latitude = Mathf.Abs(pos.y / _mapMono.mapRadius / _mapMono.chunkRadius / GlobalConstants.HexUnitSideLength / 2 * 90);
  296.         //     latitude = Mathf.Clamp(latitude, 0, 90);
  297.         //
  298.         //     float temp = Mathf.Cos(latitude / 180 * Mathf.PI) * 53.595f - 20.055f - altitude * 0.6f + tempNoise * 5;
  299.         //     return new[] { temp, precipNoise, peculiarity };
  300.         // }
  301.  
  302.         /// <summary>
  303.         /// 使用噪声生成地形
  304.         /// </summary>
  305.         /// <param name="pos">六边形的位置</param>
  306.         /// <returns>六边形高度</returns>
  307.         private float GetUnitHeight(float2 pos)
  308.         {
  309.             float baseNoise = _map.MapData.tnProp.baseTerrain.GetNoise(_noise, pos);
  310.             float ridgeNoise = _map.MapData.tnProp.ridged.GetNoise(_noise, pos);
  311.             float riverNoise = _map.MapData.tnProp.river.GetNoise(_noise, pos);
  312.             return (baseNoise + ridgeNoise - riverNoise) * _map.MapData.tnProp.altitudeMultiplier + _map.MapData.tnProp.baseHeight;
  313.         }
  314.  
  315.         /// <summary>
  316.         /// 生成树
  317.         /// </summary>
  318.         /// <param name="state">ECS SystemState</param>
  319.         /// <param name="targetUnit">目标六边形</param>
  320.         private void GenerateVegetation(ref SystemState state, HexUnitAspect targetUnit)
  321.         {
  322.             if (targetUnit.Data.height <= _map.MapData.tnProp.seaLevel)
  323.                 return;
  324.  
  325.             float2 pos = new float2(targetUnit.Position.x, targetUnit.Position.z);
  326.             if (_map.MapData.bnProp.treeNoise.GetNoise(_noise, pos) < _map.MapData.bnProp.treeSpawnThreshold
  327.                 || _random.NextFloat() > _map.MapData.bnProp.treeDensity)
  328.                 return;
  329.  
  330.             Entity tree = state.EntityManager.Instantiate(_random.Sample(ref _treePrefabs).entity);
  331.             NaturalEntityAspect naturalEntityAspect = SystemAPI.GetAspect<NaturalEntityAspect>(tree);
  332.             naturalEntityAspect.Init
  333.             (
  334.                 NatualEntityType.Tree,
  335.                 new float3(targetUnit.Position.x, targetUnit.Data.height, targetUnit.Position.z),
  336.                 _random.NextFloat() * 360,
  337.                 targetUnit.self
  338.             );
  339.             targetUnit.NaturalEntity = tree;
  340.         }
  341.  
  342.         private void GenerateWaterSurface(ref SystemState state)
  343.         {
  344.             Entity water = state.EntityManager.Instantiate(_prefabs.waterSurface);
  345.             SystemAPI.GetComponentRW<LocalToWorld>(water).ValueRW.Value =
  346.                 float4x4.Translate(new float3
  347.                 (
  348.                     -_map.EnvData.planeMeshSize.x / 2f,
  349.                     _map.MapData.tnProp.seaLevel,
  350.                     -_map.EnvData.planeMeshSize.y / 2f
  351.                 ));
  352.         }
  353.  
  354.         private void CleanUp()
  355.         {
  356.             _ecb.Dispose();
  357.             _unitDirections.Dispose();
  358.             _chunkDirections.Dispose();
  359.         }
  360.     }
  361. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement