Advertisement
443eb9

Untitled

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