Advertisement
443eb9

Untitled

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