Last active
October 22, 2019 17:38
-
-
Save tsubaki/22453785321ec8b0732f13fc6b719434 to your computer and use it in GitHub Desktop.
ISystemStateComponentData及びISystemStateBufferElementDataの使用例
This file contains hidden or 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
using Unity.Collections; | |
using Unity.Entities; | |
using Unity.Transforms; | |
using static Unity.Entities.ComponentType; | |
public struct LookAtInitialized : ISystemStateComponentData | |
{ | |
public Entity Value; | |
} | |
public struct ReferenceFromLookatBuffer : ISystemStateBufferElementData | |
{ | |
public Entity Value; | |
} | |
public struct ReferenceFromLookatInitialized : IComponentData { } | |
[UpdateInGroup(typeof(InitializationSystemGroup))] | |
public sealed class LookAtCleanupSystem : ComponentSystem | |
{ | |
EntityQuery initializeQuery, cleanupQuery, cleanupTargetQuery; | |
protected override void OnCreate() | |
{ | |
initializeQuery = GetEntityQuery(ReadOnly<LookAt>(), Exclude<LookAtInitialized>()); | |
cleanupQuery = GetEntityQuery(ReadOnly<LookAtInitialized>(), Exclude<LookAt>()); | |
cleanupTargetQuery = GetEntityQuery(ReadOnly<ReferenceFromLookatBuffer>(), Exclude<ReferenceFromLookatInitialized>(), Exclude<LocalToWorld>()); | |
} | |
protected override void OnUpdate() | |
{ | |
if (initializeQuery.CalculateChunkCount() > 0) | |
{ | |
InitializeLookAt(); | |
} | |
if (cleanupQuery.CalculateChunkCount() > 0) | |
{ | |
CleanupLookAt(); | |
} | |
if (cleanupTargetQuery.CalculateChunkCount() > 0) | |
{ | |
CleanupReferenceFromLookat(); | |
} | |
} | |
void InitializeLookAt() | |
{ | |
// LookAtが参照するEntityにReferenceFromLookatBufferを追加、LookAtを持つEntityを参照させる。 | |
Entities.With(initializeQuery).ForEach((Entity entity, ref LookAt lookat) => | |
{ | |
var buffer = EntityManager.AddBuffer<ReferenceFromLookatBuffer>(lookat.Target); | |
buffer.Add(new ReferenceFromLookatBuffer { Value = entity }); | |
}); | |
// 初期化完了フラグを設定。 | |
// LookAtInitializedはEntityが破棄されても参照先の情報を把握できるようにバックアップする。 | |
using (var lookats = initializeQuery.ToComponentDataArray<LookAt>(Allocator.TempJob)) | |
{ | |
EntityManager.AddComponentData(initializeQuery, lookats.Reinterpret<LookAt, LookAtInitialized>()); // LookAtがLookAtInitializedと同じデータ構造なので、そのままコピー。 | |
EntityManager.AddComponent<ReferenceFromLookatInitialized>(lookats.Reinterpret<LookAt, Entity>()); // LookAtの中身がEntityだけなので、変換して参照先として使用 | |
} | |
} | |
void CleanupLookAt() | |
{ | |
// ReferenceFromLookatBufferの一覧から、破棄されたEntityを削除。 | |
Entities.With(cleanupQuery).ForEach((Entity entity, ref LookAtInitialized lookat) => | |
{ | |
var buffer = EntityManager.GetBuffer<ReferenceFromLookatBuffer>(lookat.Value); | |
var bufferIndex = buffer.Find(new ReferenceFromLookatBuffer { Value = entity }); | |
if (bufferIndex != -1) { buffer.RemoveAt(bufferIndex); } | |
}); | |
EntityManager.RemoveComponent<LookAtInitialized>(cleanupQuery); | |
} | |
void CleanupReferenceFromLookat() | |
{ | |
var lookatEntityList = new NativeList<Entity>(Allocator.Temp); | |
// ReferenceFromLookatBufferが参照しているEntityを全てlistに格納。 | |
// 格納完了後、ReferenceFromLookatBufferは破棄する。 | |
using (var referencedEntities = cleanupTargetQuery.ToEntityArray(Allocator.TempJob)) | |
{ | |
foreach (var entity in referencedEntities) | |
{ | |
var buffer = EntityManager.GetBuffer<ReferenceFromLookatBuffer>(entity); | |
lookatEntityList.AddRange(buffer.Reinterpret<Entity>().AsNativeArray()); // ReferenceFromLookatBufferがEntityしか格納してないので使える力業 | |
EntityManager.RemoveComponent<ReferenceFromLookatBuffer>(entity); // 代わりに使用:EntityManager.RemoveComponent<ReferenceFromLookatBuffer>(referencedEntities); | |
} | |
} | |
// ReferenceFromLookatBufferが参照していたEntityのLookAtとLookAtInitializedコンポーネントを全て破棄。 | |
EntityManager.RemoveComponent<LookAt>(lookatEntityList); | |
EntityManager.RemoveComponent<LookAtInitialized>(lookatEntityList); | |
lookatEntityList.Dispose(); | |
} | |
} | |
public static class DynamicBufferEx | |
{ | |
public static int Find<T>(this ref DynamicBuffer<T> buffer, T input) where T : struct | |
{ | |
for (var bufferIndex = 0; bufferIndex < buffer.Length; bufferIndex++) | |
{ | |
if (buffer[bufferIndex].Equals(input)) { return bufferIndex; } | |
} | |
return -1; | |
} | |
} |
This file contains hidden or 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
using Unity.Entities; | |
using Unity.Mathematics; | |
using UnityEngine; | |
[DisallowMultipleComponent] | |
[RequiresEntityConversion] | |
public class LookAtComponent : MonoBehaviour, IConvertGameObjectToEntity | |
{ | |
[SerializeField] | |
GameObject target; | |
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) | |
{ | |
dstManager.AddComponentData(entity, new LookAt { Target = conversionSystem.GetPrimaryEntity(target) }); | |
} | |
} | |
public struct LookAt : IComponentData | |
{ | |
public Entity Target; | |
} |
This file contains hidden or 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
using Unity.Collections; | |
using Unity.Entities; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using Unity.Transforms; | |
public sealed class LookAtSystem : JobComponentSystem | |
{ | |
struct LookatJob : IJobForEach<LocalToWorld, Rotation, LookAt> | |
{ | |
[ReadOnly] public ComponentDataFromEntity<LocalToWorld> worldPositions; | |
public void Execute([ReadOnly] ref LocalToWorld worldPosition, ref Rotation rotation, [ReadOnly] ref LookAt lookat) | |
{ | |
var diffPos = math.normalizesafe(worldPositions[lookat.Target].Position - worldPosition.Position); | |
rotation.Value = quaternion.LookRotation(diffPos, math.up()); | |
} | |
} | |
protected override JobHandle OnUpdate(JobHandle inputDeps) | |
{ | |
inputDeps = new LookatJob | |
{ | |
worldPositions = GetComponentDataFromEntity<LocalToWorld>(true) | |
}.Schedule(this, inputDeps); | |
return inputDeps; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment