Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using HexagonSurvive.Constants;
- using HexagonSurvive.Containers.ECS;
- using HexagonSurvive.Containers.ECS.Models;
- using HexagonSurvive.Environment.Aspects;
- using HexagonSurvive.Environment.Enums;
- using HexagonSurvive.Extensions.ECS;
- using HexagonSurvive.Map.Aspects;
- using HexagonSurvive.Map.Components;
- using HexagonSurvive.Map.Enums;
- using HexagonSurvive.Map.Properties;
- using Lib;
- using Unity.Burst;
- using Unity.Collections;
- using Unity.Entities;
- using Unity.Mathematics;
- using Unity.Transforms;
- 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 HexMapPrefabs _prefabs;
- private EntityCommandBuffer _ecb;
- private NativeArray<float2> _unitDirections;
- private NativeArray<float2> _chunkDirections;
- private DynamicBuffer<TreePrefabBuffer> _treePrefabs;
- private NativeHashMap<int3, Entity> _coordToUnit;
- 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<EntityContainerData>();
- }
- public void OnUpdate(ref SystemState state)
- {
- state.Enabled = false;
- Generate(ref state);
- }
- [BurstCompile]
- public void OnDestroy(ref SystemState state)
- {
- _coordToUnit.Dispose();
- }
- private void Generate(ref SystemState state)
- {
- foreach (HexMapAspect hexMapAspect in SystemAPI.Query<HexMapAspect>())
- {
- _map = hexMapAspect;
- Initialize(ref state);
- GenerateWaterSurface(ref state);
- GenerateMap(ref state);
- CleanUp();
- }
- }
- private void Initialize(ref SystemState state)
- {
- _ecb = new EntityCommandBuffer(Allocator.Temp);
- _noise = new FastNoiseLite((int)_map.MapData.basicProp.seed);
- _random = new Random(_map.MapData.basicProp.seed);
- _coordToUnit = new NativeHashMap<int3, Entity>();
- EntityContainerData containerData = SystemAPI.GetSingleton<EntityContainerData>();
- _prefabs = containerData.hexMapPrefabs;
- _treePrefabs = SystemAPI.GetBuffer<TreePrefabBuffer>(containerData.container);
- _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.MapData.basicProp.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);
- }
- /// <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.MapData.basicProp.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.MapData.basicProp.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.MapData.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.MapData.tnProp.seaLevel,
- biome
- );
- unitAspect.Position = new float3(pos.x, unitHeight / 4, pos.y);
- unitAspect.NonUniformScale = new float3(1, unitHeight / 2, 1);
- CalculateCoordinates(unitAspect);
- GenerateVegetation(ref state, unitAspect);
- }
- private void CalculateCoordinates(HexUnitAspect unit)
- {
- float3 p = unit.Position;
- int x = Round(p.x / MathConstants.Sqrt3 / GlobalConstants.HexUnitSideLength * 2);
- int z = Round(p.z / 1.5f / GlobalConstants.HexUnitSideLength);
- unit.Coordinate = new int3((x - z) / 2, z, (-x - z) / 2);
- _coordToUnit.Add(unit.Coordinate, unit.self);
- }
- private int Round(float x) =>
- math.frac(x) > 0.5 ? (int)x + 1 : (int)x;
- /// <summary>
- /// 使海拔数值阶梯化
- /// </summary>
- /// <param name="altitude">原始海拔</param>
- /// <returns>阶梯化后的海拔等级</returns>
- private int StepAltitude(float altitude)
- {
- TerrainNoiseProperties settings = _map.MapData.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)
- {
- float baseNoise = _map.MapData.tnProp.baseTerrain.GetNoise(_noise, pos);
- float ridgeNoise = _map.MapData.tnProp.ridged.GetNoise(_noise, pos);
- float riverNoise = _map.MapData.tnProp.river.GetNoise(_noise, pos);
- return (baseNoise + ridgeNoise - riverNoise) * _map.MapData.tnProp.altitudeMultiplier + _map.MapData.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.MapData.tnProp.seaLevel)
- return;
- float2 pos = new float2(targetUnit.Position.x, targetUnit.Position.z);
- if (_map.MapData.bnProp.treeNoise.GetNoise(_noise, pos) < _map.MapData.bnProp.treeSpawnThreshold
- || _random.NextFloat() > _map.MapData.bnProp.treeDensity)
- return;
- Entity tree = state.EntityManager.Instantiate(_random.Sample(ref _treePrefabs).entity);
- NaturalEntityAspect naturalEntityAspect = SystemAPI.GetAspect<NaturalEntityAspect>(tree);
- naturalEntityAspect.Init
- (
- NatualEntityType.Tree,
- new float3(targetUnit.Position.x, targetUnit.Data.height, targetUnit.Position.z),
- _random.NextFloat() * 360,
- targetUnit.self
- );
- targetUnit.NaturalEntity = tree;
- }
- private void GenerateWaterSurface(ref SystemState state)
- {
- Entity water = state.EntityManager.Instantiate(_prefabs.waterSurface);
- SystemAPI.GetComponentRW<LocalToWorld>(water).ValueRW.Value =
- float4x4.Translate(new float3
- (
- -_map.EnvData.planeMeshSize.x / 2f,
- _map.MapData.tnProp.seaLevel,
- -_map.EnvData.planeMeshSize.y / 2f
- ));
- }
- private void CleanUp()
- {
- _ecb.Dispose();
- _unitDirections.Dispose();
- _chunkDirections.Dispose();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement