Last active
October 1, 2020 01:08
-
-
Save admal/bf91c434ee31934143109b201fe7ec8b to your computer and use it in GitHub Desktop.
Unity dots: migration to new DOTS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FindTargetSystem : SystemBase | |
{ | |
private EndSimulationEntityCommandBufferSystem ecbSystem; | |
protected override void OnCreate() | |
{ | |
ecbSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>(); | |
base.OnCreate(); | |
} | |
public struct EntityWithPosition | |
{ | |
public Entity entity; | |
public float3 position; | |
} | |
protected override void OnUpdate() | |
{ | |
//It is needed to use instead of PostUpdateCommands | |
var ecb = ecbSystem.CreateCommandBuffer().ToConcurrent(); | |
//EnemyUnit == Target | |
var enemiesQuery = GetEntityQuery(typeof(EnemyUnit), ComponentType.ReadOnly<Translation>()); | |
var enemiesEntityArray = enemiesQuery.ToEntityArray(Allocator.TempJob); | |
var enemiesTranslationArray = enemiesQuery.ToComponentDataArray<Translation>(Allocator.TempJob); | |
var enemiesArray = new NativeArray<EntityWithPosition>(enemiesEntityArray.Length, Allocator.TempJob); | |
for (int i = 0; i < enemiesEntityArray.Length; i++) | |
{ | |
enemiesArray[i] = new EntityWithPosition() | |
{ | |
entity = enemiesEntityArray[i], | |
position = enemiesTranslationArray[i].Value | |
}; | |
} | |
//Put quadrant map into class variable, to use burst and jobs in dots you can't pass static fields. | |
//Thanks to that multihashmap is a struct so only value is copied to local variable. | |
//That variable is later used inside of the ForEach method. | |
var quadrantMultiHashMap = QuadrantSystem.quadrantMultiHashMap; | |
//That code uses jobs and burst | |
Entities | |
//WithReadOnly - you can read in parallel | |
.WithReadOnly(quadrantMultiHashMap) | |
.WithNone<HasTarget>() | |
.WithAll<PlayerUnit>() | |
.ForEach((Entity entity, int entityInQueryIndex, ref Translation translation, ref QuadrantEntity quadrantEntity) => | |
{ | |
var closestEnemy = Entity.Null; | |
var closestEnemyPosition = float3.zero; | |
var unitPosition = translation.Value; | |
var hashMapKey = QuadrantSystem.GetPositionHashMapKey(translation.Value); | |
//This little hack allows you to use 'static' stuff inside jobs (you can't use class' methods nor truly static methods here) | |
var helper = new TargetHelper(); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey + 1, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey - 1, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey + QuadrantSystem.QuadrantZMultiplier, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey - QuadrantSystem.QuadrantZMultiplier, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey + 1 - QuadrantSystem.QuadrantZMultiplier, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey - 1 - QuadrantSystem.QuadrantZMultiplier, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey + 1 + QuadrantSystem.QuadrantZMultiplier, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
helper.FindTarget(quadrantMultiHashMap, hashMapKey - 1 + QuadrantSystem.QuadrantZMultiplier, unitPosition, quadrantEntity, ref closestEnemy, ref closestEnemyPosition); | |
if (closestEnemy != Entity.Null) | |
{ | |
ecb.AddComponent<HasTarget>(entityInQueryIndex, entity, new HasTarget() { targetEntity = closestEnemy }); | |
} | |
}) | |
.ScheduleParallel(); | |
enemiesEntityArray.Dispose(Dependency); | |
enemiesTranslationArray.Dispose(Dependency); | |
enemiesArray.Dispose(Dependency); | |
// quadrantMultiHashMap.Dispose(Dependency); //I don't know why this part does not work, but in my opinion it should be disposed | |
ecbSystem.AddJobHandleForProducer(Dependency); | |
} | |
private struct TargetHelper | |
{ | |
public void FindTarget( | |
NativeMultiHashMap<int, QuadrantData> quadrantMap, | |
int hashMapKey, | |
float3 unitPosition, | |
QuadrantEntity quadrantEntity, | |
ref Entity closestEnemy, | |
ref float3 closestEnemyPosition | |
) | |
{ | |
NativeMultiHashMapIterator<int> nativeMultiHashMapIterator; | |
if (quadrantMap.TryGetFirstValue(hashMapKey, out var quadrantData, out nativeMultiHashMapIterator)) | |
{ | |
do | |
{ | |
if (quadrantData.quadrantEntity.type == quadrantEntity.type) | |
{ | |
continue; | |
} | |
if (closestEnemy == Entity.Null) | |
{ | |
//no target | |
closestEnemy = quadrantData.entity; | |
closestEnemyPosition = quadrantData.position; | |
} | |
else | |
{ | |
if (math.distance(unitPosition, quadrantData.position) < math.distance(unitPosition, closestEnemyPosition)) | |
{ | |
closestEnemy = quadrantData.entity; | |
closestEnemyPosition = quadrantData.position; | |
} | |
} | |
} while (quadrantMap.TryGetNextValue(out quadrantData, ref nativeMultiHashMapIterator)); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment