Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using HexagonSurvive.Constants;
- using HexagonSurvive.Environment.Aspects;
- using HexagonSurvive.Environment.Components;
- using HexagonSurvive.Extensions.ECS;
- using HexagonSurvive.Map.Aspects;
- using HexagonSurvive.Map.Components;
- using HexagonSurvive.Map.Enums;
- using HexagonSurvive.Map.Properties;
- using HexagonSurvive.Noise;
- using Lib;
- using Unity.Burst;
- using Unity.Collections;
- using Unity.Entities;
- using Unity.Mathematics;
- using Unity.Transforms;
- using UnityEngine;
- using Random = Unity.Mathematics.Random;
- namespace HexagonSurvive.Map.Systems
- {
- [UpdateInGroup(typeof(InitializationSystemGroup))]
- public partial struct HexMapInitSystem : ISystem
- {
- private Random _random;
- private HexMapAspect _map;
- private FastNoiseLite _noise;
- private HexMapPrefabsData _prefabs;
- private EntityCommandBuffer _ecb;
- private NativeArray<float2> _unitDirections;
- private NativeArray<float2> _chunkDirections;
- private const float Sin60 = 0.8660254f;
- private const float CenterToSide = CenterToVertex * Sin60;
- private const float CenterToVertex = GlobalConstants.HexUnitSideLength;
- [BurstCompile]
- public void OnCreate(ref SystemState state)
- {
- state.RequireForUpdate<GlobalEnvironmentData>();
- state.RequireForUpdate<HexMapPrefabsData>();
- }
- public void OnUpdate(ref SystemState state)
- {
- state.Enabled = false;
- Generate(ref state);
- }
- [BurstCompile]
- public void OnDestroy(ref SystemState state)
- {
- }
- private void Generate(ref SystemState state)
- {
- foreach (HexMapAspect hexMapAspect in SystemAPI.Query<HexMapAspect>())
- {
- Debug.Log("Map");
- _map = hexMapAspect;
- Initialize(ref state);
- // RemoveAll();
- // GenerateWaterSurface(ref state);
- GenerateMap(ref state);
- CleanUp();
- }
- }
- private void Initialize(ref SystemState state)
- {
- _ecb = new EntityCommandBuffer(Allocator.Temp);
- _noise = new FastNoiseLite((int)_map.Data.seed);
- _random = new Random(_map.Data.seed);
- _prefabs = SystemAPI.GetSingleton<HexMapPrefabsData>();
- _unitDirections = new NativeArray<float2>(6, Allocator.Temp);
- _unitDirections[0] = new float2(-Sin60, 3 / 2f) * CenterToVertex;
- _unitDirections[1] = new float2(-2 * Sin60, 0) * CenterToVertex;
- _unitDirections[2] = new float2(-Sin60, -3 / 2f) * CenterToVertex;
- _unitDirections[3] = new float2(Sin60, -3 / 2f) * CenterToVertex;
- _unitDirections[4] = new float2(2 * Sin60, 0) * CenterToVertex;
- _unitDirections[5] = new float2(Sin60, 3 / 2f) * CenterToVertex;
- float chunkRadius = _map.Data.chunkRadius;
- _chunkDirections = new NativeArray<float2>(6, Allocator.Temp);
- _chunkDirections[0] = new float2(Sin60 * 3 * chunkRadius - Sin60, 3 / 2f * (chunkRadius - 1)) * CenterToVertex;
- _chunkDirections[1] = new float2(CenterToSide, 3 * CenterToVertex * chunkRadius - 3 / 2f * CenterToVertex);
- _chunkDirections[2] = new float2(2 * CenterToSide - 3 * CenterToSide * chunkRadius, 3 / 2f * CenterToVertex * chunkRadius);
- _chunkDirections[3] = -new float2(Sin60 * 3 * chunkRadius - Sin60, 3 / 2f * (chunkRadius - 1)) * CenterToVertex;
- _chunkDirections[4] = -new float2(CenterToSide, 3 * CenterToVertex * chunkRadius - 3 / 2f * CenterToVertex);
- _chunkDirections[5] = -new float2(2 * CenterToSide - 3 * CenterToSide * chunkRadius, 3 / 2f * CenterToVertex * chunkRadius);
- }
- private void RemoveAll()
- {
- // for (int i = _mapMono.transform.childCount - 1; i >= 0; i--)
- // {
- // CoreUtils.Destroy(_mapMono.transform.GetChild(i).gameObject);
- // }
- }
- /// <summary>
- /// 生成区块拼接成为地图
- /// </summary>
- private void GenerateMap(ref SystemState state)
- {
- float2 mapCenter = new float2(_map.Position.x, _map.Position.z);
- GenerateChunk(ref state, float2.zero);
- for (int r = 1; r < _map.Data.mapRadius; r++)
- {
- float2 curCenter = mapCenter + _chunkDirections[4] * r;
- foreach (float2 dir in _chunkDirections)
- {
- for (int hex = 0; hex < r; hex++)
- {
- GenerateChunk(ref state, curCenter);
- curCenter += dir;
- }
- }
- }
- }
- /// <summary>
- /// 生成六边形单元生成区块
- /// </summary>
- /// <param name="state">ECS SystemState</param>
- /// <param name="center">区块中心,即中心六边形的中心</param>
- /// <returns></returns>
- private void GenerateChunk(ref SystemState state, float2 center)
- {
- InstantiateUnit(ref state, center);
- for (int r = 1; r < _map.Data.chunkRadius; r++)
- {
- float2 curCenter = new float2(center.x + r * CenterToSide * 2, center.y);
- foreach (float2 dir in _unitDirections)
- {
- for (int hex = 0; hex < r; hex++)
- {
- InstantiateUnit(ref state, curCenter);
- curCenter += dir;
- }
- }
- }
- }
- /// <summary>
- /// 生成六边形单元
- /// </summary>
- /// <param name="state">ECS SystemState</param>
- /// <param name="pos">生成位置</param>
- /// <returns></returns>
- private void InstantiateUnit(ref SystemState state, float2 pos)
- {
- Entity hexUnit = state.EntityManager.Instantiate(_prefabs.hexUnit);
- HexUnitAspect unitAspect = SystemAPI.GetAspect<HexUnitAspect>(hexUnit);
- float height = GetUnitHeight(pos);
- int altitude = StepAltitude(height);
- TerrainNoiseProperties settings = _map.Data.tnProp;
- float unitHeight = altitude * settings.stepHeight + settings.baseHeight;
- Biome biome = height > settings.seaLevel
- ? GetBiomeLand(unitAspect, pos, unitHeight)
- : GetBiomeWater(unitAspect, pos, unitHeight);
- unitAspect.AdjustData
- (
- altitude,
- unitHeight / 2,
- unitHeight > _map.Data.tnProp.seaLevel,
- biome
- );
- unitAspect.Transform
- (
- new float3(pos.x, unitHeight / 4, pos.y),
- float3.zero,
- new float3(1, unitHeight / 2, 1)
- );
- // GenerateVegetation(ref state, unitAspect);
- }
- /// <summary>
- /// 使海拔数值阶梯化
- /// </summary>
- /// <param name="altitude">原始海拔</param>
- /// <returns>阶梯化后的海拔等级</returns>
- private int StepAltitude(float altitude)
- {
- TerrainNoiseProperties settings = _map.Data.tnProp;
- float refAltitude = altitude - settings.baseHeight;
- for (int i = 0; i < settings.terrainSteps; i++)
- {
- if (refAltitude < i * settings.altitudePerStep)
- return i;
- }
- return settings.terrainSteps;
- }
- /// <summary>
- /// 生成陆地气候
- /// </summary>
- /// <param name="unitAspect">目标六边形</param>
- /// <param name="pos">六边形位置</param>
- /// <param name="altitude">六边形海拔,即噪声值</param>
- /// <returns>六边形高度</returns>
- private Biome GetBiomeLand(HexUnitAspect unitAspect, float2 pos, float altitude)
- {
- return Biome.Plains;
- }
- /// <summary>
- /// 生成水面气候,并重新调整六边形单元的高度
- /// </summary>
- /// <param name="unitAspect">目标六边形</param>
- /// <param name="pos">六边形位置</param>
- /// <param name="altitude">六边形海拔,即噪声值</param>
- /// <returns>六边形高度</returns>
- private Biome GetBiomeWater(HexUnitAspect unitAspect, float2 pos, float altitude)
- {
- return Biome.River;
- }
- // /// <summary>
- // /// 获取当前位置的生物群系噪声值
- // /// </summary>
- // /// <param name="pos">六边形位置</param>
- // /// <param name="altitude">海拔</param>
- // /// <returns>0: 温度(现实温度) 1: 降水(0-1) 2: 特别程度(0-1)</returns>
- // private float[] GetBiomeNoiseValue(Vector2 pos, float altitude)
- // {
- // _noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2S);
- // BiomeNoiseSettings settings = _map.Data.biomeSettings;
- //
- // _noise.SetSeed((int)_mapMono.seed + _random.Int(0, int.MaxValue));
- // Vector2 tempNoisePos = pos * settings.temperatureFrequency + settings.temperatureOffset;
- // float tempNoise = (_noise.GetNoise(tempNoisePos.x, tempNoisePos.y) + 1) / 2;
- // tempNoise = Mathf.Pow(tempNoise, settings.temperaturePower);
- //
- // _noise.SetSeed((int)_mapMono.seed + _random.Int(0, int.MaxValue));
- // Vector2 precipNoisePos = pos * settings.precipitationFrequency + settings.precipitationOffset;
- // float precipNoise = (_noise.GetNoise(precipNoisePos.x, precipNoisePos.y) + 1) / 2;
- // precipNoise = Mathf.Pow(precipNoise, settings.precipitationPower);
- //
- // _noise.SetSeed((int)_mapMono.seed + _random.Int(0, int.MaxValue));
- // Vector2 peculiarityPos = pos * settings.peculiarityFrequency + settings.peculiarityOffset;
- // float peculiarity = (_noise.GetNoise(peculiarityPos.x, peculiarityPos.y) + 1) / 2;
- // peculiarity = Mathf.Pow(peculiarity, settings.peculiarityPower);
- //
- // _noise.SetSeed((int)_mapMono.seed);
- // float latitude = Mathf.Abs(pos.y / _mapMono.mapRadius / _mapMono.chunkRadius / GlobalConstants.HexUnitSideLength / 2 * 90);
- // latitude = Mathf.Clamp(latitude, 0, 90);
- //
- // float temp = Mathf.Cos(latitude / 180 * Mathf.PI) * 53.595f - 20.055f - altitude * 0.6f + tempNoise * 5;
- // return new[] { temp, precipNoise, peculiarity };
- // }
- /// <summary>
- /// 使用噪声生成地形
- /// </summary>
- /// <param name="pos">六边形的位置</param>
- /// <returns>六边形高度</returns>
- private float GetUnitHeight(float2 pos)
- {
- float2 p = pos;
- PerlinNoise baseProp = _map.Data.tnProp.baseTerrain;
- RidgeNoise ridgedProp = _map.Data.tnProp.ridged;
- RidgeNoise riverProp = _map.Data.tnProp.river;
- _noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- float2 baseNoise = p * baseProp.baseFrequency + baseProp.baseOffset;
- float baseAltitude = math.pow((_noise.GetNoise(baseNoise.x, baseNoise.y) + 1) / 2, baseProp.basePower);
- baseAltitude *= baseProp.baseMultiplier;
- float2 ridgeNoise = p * ridgedProp.frequency + ridgedProp.offset;
- _noise.SetFractalType(FastNoiseLite.FractalType.Ridged);
- _noise.SetFractalOctaves(ridgedProp.octaves);
- _noise.SetFractalLacunarity(ridgedProp.lacunarity);
- _noise.SetFractalGain(ridgedProp.gain);
- float ridged = (_noise.GetNoise(ridgeNoise.x, ridgeNoise.y) + 1) / 2;
- ridged = math.pow(ridged, ridgedProp.power) * ridgedProp.multiplier;
- float2 riverNoise = p * riverProp.frequency + riverProp.offset;
- _noise.SetFractalType(FastNoiseLite.FractalType.Ridged);
- _noise.SetFractalOctaves(riverProp.octaves);
- _noise.SetFractalLacunarity(riverProp.lacunarity);
- _noise.SetFractalGain(riverProp.gain);
- float river = (_noise.GetNoise(riverNoise.x, riverNoise.y) + 1) / 2;
- river = -math.pow(river, riverProp.power) * riverProp.multiplier;
- return (baseAltitude + ridged + river) * _map.Data.tnProp.altitudeMultiplier + _map.Data.tnProp.baseHeight;
- }
- /// <summary>
- /// 生成树
- /// </summary>
- /// <param name="state">ECS SystemState</param>
- /// <param name="targetUnit">目标六边形</param>
- private void GenerateVegetation(ref SystemState state, HexUnitAspect targetUnit)
- {
- if (targetUnit.Data.height <= _map.Data.tnProp.seaLevel
- || _random.NextFloat() > _map.Data.bnProp.treeDensity)
- return;
- Entity tree = state.EntityManager.Instantiate(_random.Sample(ref _prefabs.trees.Value));
- NaturalEntityAspect naturalEntityAspect = SystemAPI.GetAspect<NaturalEntityAspect>(tree);
- naturalEntityAspect.BelongsTo = targetUnit.self;
- naturalEntityAspect.Position += new float3(0, targetUnit.Data.RelativeSurfaceHeight, 0);
- targetUnit.NaturalEntity = tree;
- }
- private void GenerateWaterSurface(ref SystemState state)
- {
- // var g = EnvironmentManager.Instance.globalEnvironment;
- // ProceduralMeshContainer.Instance.planeMeshMatchTerrain =
- // PlaneGenerator.Generate(g.planeMeshSize.x, g.planeMeshSize.y, g.planeMeshRes, "TerrainMesh");
- Entity water = state.EntityManager.Instantiate(_prefabs.waterSurface);
- GlobalEnvironmentData env = SystemAPI.GetSingleton<GlobalEnvironmentData>();
- SystemAPI.GetComponentRW<LocalToWorld>(water).ValueRW.Value =
- float4x4.Translate(new float3(-env.planeMeshSize.x / 2f, _map.Data.tnProp.seaLevel, -env.planeMeshSize.y / 2f));
- }
- private void CleanUp()
- {
- _ecb.Dispose();
- _unitDirections.Dispose();
- _chunkDirections.Dispose();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement