[196839-gif-28052022-13-46-06v2.gif*_|196839]
// src: https://gist.github.com/andrew-raphael-lukasik/19170443b976582f97404f6da9875b4c
using UnityEngine;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Collections;
using Unity.Jobs;
namespace Sandbox
{
public class Planted : MonoBehaviour
{
[SerializeField] int _numPlantsOnStart = 5;
[SerializeField] int2 _coordMinOnStart = -10, _coordMaxnOnStart = 10;
EntityManager _entityManager;
EntityQuery _query;
void Start ()
{
var world = World.DefaultGameObjectInjectionWorld;
_entityManager = world.EntityManager;
_query = _entityManager.CreateEntityQuery( ComponentType.ReadOnly<Coord>() , ComponentType.ReadOnly<Spread>() , ComponentType.ReadOnly<Gene>() );
var prefabs = world.GetOrCreateSystem<PrefabSystem>();
var rnd = new Unity.Mathematics.Random( (uint) System.DateTime.Now.GetHashCode() );
for( int i=0 ; i<_numPlantsOnStart ; i++ )
{
Entity plantInstance = _entityManager.Instantiate( prefabs.Plant );
_entityManager.SetComponentData( plantInstance , new Coord{
Value = rnd.NextInt2( _coordMinOnStart , _coordMaxnOnStart )
} );
_entityManager.SetComponentData( plantInstance , new Age{
Value = rnd.NextFloat( 0f , rnd.NextFloat(Age.limit*0.1f) )
} );
var genes = _entityManager.GetBuffer<Gene>( plantInstance );
Color32 colorBytes = Color.HSVToRGB( rnd.NextFloat(1f) , 1f , 1f );
genes.Add( colorBytes.r );
genes.Add( colorBytes.g );
genes.Add( colorBytes.b );
}
}
#if UNITY_EDITOR
void OnDrawGizmos ()
{
if( !Application.isPlaying ) return;
int len = _query.CalculateEntityCount();
var entities = _query.ToEntityArray(Allocator.Temp).ToArray();
var coords = _query.ToComponentDataArray<Coord>(Allocator.Temp).ToArray();
for( int i=0 ; i<len ; i++ )
{
var genes = _entityManager.GetBuffer<Gene>( entities *);*
_ int2 coord = coords*.Value;_
_ Gizmos.DrawSphere( new Vector3( coord.x , coord.y , 0 ) , 0.5f );_
_ }_
_ }_
_ #endif*_
* }*
* public struct Coord : IComponentData*
* {*
* public int2 Value;*
* }*
* public struct Age : IComponentData*
* {*
* public float Value;*
* public const float limit = 10f;*
* }*
* public struct Spread : IComponentData*
* {*
* public float Value;*
* public const float spread_threshold = 2f;
_ }_
_ [InternalBufferCapacity(5)]_
_ public struct Gene : IBufferElementData*_
* {*
* public byte Value;*
* public static implicit operator byte ( Gene value ) => value.Value;*
* public static implicit operator Gene ( byte value ) => new Gene{ Value=value };*
* }*
* [UpdateInGroup( typeof(SimulationSystemGroup) )]*
* public partial class SpreadSystem : SystemBase*
* {*
* EntityCommandBufferSystem _ecbSystem;
GridSystem _gridSystem;
PrefabSystem prefabs;
_ protected override void OnCreate ()*
* {*
* base.OnCreate();*
* _ecbSystem = World.GetOrCreateSystem();
_gridSystem = World.GetOrCreateSystem();
prefabs = World.GetOrCreateSystem();
_ }*
* protected override void OnUpdate ()*
* {*
* float deltaTime = Time.DeltaTime;*
* uint rndHash = (uint) Time.ElapsedTime.GetHashCode();*
* var grid = _gridSystem.Lookup;
var plantPrefab = prefabs.Plant;
_ var geneBuffers = GetBufferFromEntity( isReadOnly:false );*
* var cmd = _ecbSystem.CreateCommandBuffer().AsParallelWriter();*
* this.Dependency = JobHandle.CombineDependencies( Dependency , _gridSystem.LookupDependency );*
* Entities*
* .WithReadOnly( grid )*
* .WithAll()*
* .ForEach( ( ref Spread spread , in Coord coord , in Entity e , in int nativeThreadIndex ) =>*
* {*
* spread.Value += deltaTime;*
* if( spread.Value>Spread.spread_threshold )
_ {_
_ var rnd = new Unity.Mathematics.Random( rndHash + (uint)e.GetHashCode() + (uint)nativeThreadIndex.GetHashCode() );_
_ var myGenes = geneBuffers[e];*_
* int2 spreadAttemptCoord = coord.Value + rnd.NextInt2( -2 , 2 );*
* if( !grid.ContainsKey(spreadAttemptCoord) )// is this spot free*
* {*
* var newPlant = cmd.Instantiate( nativeThreadIndex , plantPrefab );*
* cmd.SetComponent( nativeThreadIndex , newPlant , new Coord{ Value=spreadAttemptCoord } );*
cmd.SetComponent( nativeThreadIndex , newPlant , new Spread{ Value=rnd.NextFloat(0f,Spread.spread_threshold0.5f) } );
_ cmd.SetComponent( nativeThreadIndex , newPlant , new Age{ Value=rnd.NextFloat(0f,Age.limit0.1f) } );
* // propagate genes with slight mutation:*
* const byte mutation_range_half = 30;
cmd.AppendToBuffer( nativeThreadIndex , newPlant , (byte)math.clamp( myGenes[0] + rnd.NextInt(-mutation_range_half,mutation_range_half+1) , 0 , 255 ) );
cmd.AppendToBuffer( nativeThreadIndex , newPlant , (byte)math.clamp( myGenes[1] + rnd.NextInt(-mutation_range_half,mutation_range_half+1) , 0 , 255 ) );
cmd.AppendToBuffer( nativeThreadIndex , newPlant , (byte)math.clamp( myGenes[2] + rnd.NextInt(-mutation_range_half,mutation_range_half+1) , 0 , 255 ) );
_ }*
* else// it’s taken so lets attempt cross-pollination*
* {*
* foreach( var other in grid.GetValuesForKey(spreadAttemptCoord) )*
* if( geneBuffers.HasComponent(other) )*
* {*
* var otherGenes = geneBuffers[other];*
* otherGenes[0] = rnd.NextBool() ? otherGenes[0] : myGenes[0];*
* otherGenes[1] = rnd.NextBool() ? otherGenes[1] : myGenes[1];*
* otherGenes[2] = rnd.NextBool() ? otherGenes[2] : myGenes[2];*
* }*
* }*
* spread.Value = 0;*
* }*
* } )*
* .WithBurst()*
* .Schedule();*
* ecbSystem.AddJobHandleForProducer( Dependency );
_ }*
* }*
* [UpdateInGroup( typeof(SimulationSystemGroup) )]*
* public partial class AgeSystem : SystemBase*
* {*
* EntityCommandBufferSystem ecbSystem;
_ protected override void OnCreate ()*
* {*
* base.OnCreate();*
* ecbSystem = World.GetOrCreateSystem();
_ }*
* protected override void OnUpdate ()*
* {*
* float deltaTime = Time.DeltaTime;*
* var cmd = _ecbSystem.CreateCommandBuffer().AsParallelWriter();*
* Entities*
* .ForEach( ( ref Age age , in Entity e , in int nativeThreadIndex ) =>*
* {*
* age.Value += deltaTime;*
* if( age.Value>Age.limit )*
* cmd.DestroyEntity( nativeThreadIndex , e );*
* } )*
* .WithBurst()*
* .ScheduleParallel();*
* ecbSystem.AddJobHandleForProducer( Dependency );
_ }*
* }*
* [UpdateInGroup( typeof(SimulationSystemGroup) , OrderFirst=true )]*
* public partial class GridSystem : SystemBase*
* {*
* ///
Read-Only *
* public NativeMultiHashMap<int2,Entity> Lookup { get; private set; }*
* public JobHandle LookupDependency => base.Dependency;*
* EntityCommandBufferSystem _ecbSystem;
EntityQuery queryNew;
_ protected override void OnCreate ()*
* {*
* base.OnCreate();*
* _ecbSystem = World.GetOrCreateSystem();
queryNew = EntityManager.CreateEntityQuery( new EntityQueryDesc{
_ None = new ComponentType[]{ ComponentType.ReadOnly() } ,*
* All = new ComponentType[]{ ComponentType.ReadOnly() }*
* } );*
* Lookup = new NativeMultiHashMap<int2,Entity>( 1024 , Allocator.Persistent );*
* }*
* protected override void OnDestroy ()*
* {*
* base.OnDestroy();*
* Lookup.Dispose();*
* }*
* protected override void OnUpdate ()*
* {*
* var cmd = ecbSystem.CreateCommandBuffer().AsParallelWriter();
_ var lookup = Lookup;*
* var lookupPW = Lookup.AsParallelWriter();*
* int countNewToLookup = queryNew.CalculateEntityCount();
_ if( countNewToLookup!=0 && (lookup.Count()+countNewToLookup)>lookup.Capacity/2 )*
* {*
_ lookup.Capacity = Mathf.Max( lookup.Count()+countNewToLookup , lookup.Capacity2 );_
_ Debug.Log($“{nameof(GridSystem)}.{nameof(Lookup)} capacity increased to {lookup.Capacity}”);_
_ }*_
* Entities*
* .WithName(“coord_created_job”)
_ .WithNone()_
_ .ForEach( ( in Coord coord , in Entity e , in int nativeThreadIndex ) =>_
_ {_
_ lookupPW.Add( coord.Value , e );_
_ cmd.AddComponent( nativeThreadIndex , e , new Tracked{ Value=coord.Value } );_
_ } )_
_ .WithBurst()_
_ .ScheduleParallel();*_
* Entities*
* .WithName(“coord_destroyed_job”)
_ .WithNone()_
_ .ForEach( ( in Tracked tracked , in Entity e , in int nativeThreadIndex ) =>_
_ {_
_ lookup.Remove( tracked.Value , e );_
_ cmd.RemoveComponent( nativeThreadIndex , e );_
_ } )_
_ .WithBurst()_
_ .Schedule();*_
* ecbSystem.AddJobHandleForProducer( Dependency );
_ }*
* struct Tracked : ISystemStateComponentData { public int2 Value; }*
* }*
* [DisableAutoCreation]*
* [UpdateInGroup( typeof(InitializationSystemGroup) )]*
* public partial class PrefabSystem : SystemBase*
* {*
* public Entity Plant { get; private set; }*
* protected override void OnCreate ()*
* {*
* base.OnCreate();*
* this.Enabled = false;*
* Plant = EntityManager.CreateEntity( typeof(Prefab) , typeof(Coord) , typeof(Age) , typeof(Spread) , typeof(Gene) );*
* }*
* protected override void OnUpdate () {}*
* }*
}
_*