Skip to content

Instantly share code, notes, and snippets.

@tsubaki
Last active April 20, 2022 04:46
Show Gist options
  • Save tsubaki/00469aeae95757dc225dd3e7deca9afc to your computer and use it in GitHub Desktop.
Save tsubaki/00469aeae95757dc225dd3e7deca9afc to your computer and use it in GitHub Desktop.
GameObjectを破棄するとEntityも破棄される。もしくはその逆
using Unity.Entities;
using Unity.Transforms;
using UnityEngine;
/// <summary>
/// GameObjectを破棄する時、紐付いているEntityを破棄する。
/// </summary>
[RequireComponent(typeof(ConvertToEntity))]
[DisallowMultipleComponent]
[RequiresEntityConversion]
public class SyncGameObjectWithEntity : MonoBehaviour, IConvertGameObjectToEntity
{
Entity _cachedEntity;
void Reset()
{
GetComponent<ConvertToEntity>().ConversionMode = ConvertToEntity.Mode.ConvertAndInjectGameObject;
}
/// <summary>
/// 座標を同期する方法
/// </summary>
[SerializeField] SyncType syncType = SyncType.EntityToGameObject;
void IConvertGameObjectToEntity.Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
_cachedEntity = entity;
// Entityを破棄した事を認識するために ReferenceGameObjectFromEntityState を登録
dstManager.AddComponentData(entity, new ReferenceGameObjectFromEntityState { Value = gameObject });
dstManager.AddComponentData(entity, new ReferenceGameObjectFromEntityTag());
// 座標を同期する方法を設定
switch (syncType)
{
case SyncType.EntityToGameObject:
dstManager.AddComponentData(entity, new CopyTransformToGameObject());
break;
case SyncType.GameObjectToEntity:
dstManager.AddComponentData(entity, new CopyTransformFromGameObject());
break;
}
}
void OnDestroy()
{
if (World.DefaultGameObjectInjectionWorld == null)
return;
// 紐付いているEntityを破棄する
var em = World.DefaultGameObjectInjectionWorld.EntityManager;
if (em.Exists(_cachedEntity))
{
em.RemoveComponent<ReferenceGameObjectFromEntityState>(_cachedEntity);
em.DestroyEntity(_cachedEntity);
}
}
/// <summary>
/// 座標の同期方法
/// </summary>
enum SyncType
{
/// <summary> Entityの座標をGameObjectに設定 </summary>
EntityToGameObject,
/// <summary> GameObjectの座標をEntityに設定 </summary>
GameObjectToEntity,
/// <summary> 何もしない </summary>
None
}
}
/// <summary>
/// Entityに紐付いているGameObjectを破棄する。
/// Update前に実行
/// </summary>
[UpdateInGroup(typeof(PresentationSystemGroup))]
public class GameObjectEntityCleanUpSystem : ComponentSystem
{
private EntityQuery query;
protected override void OnCreate()
{
// 破棄された、ReferenceGameObjectFromEntityStateを持つEntityを収集する。
query = GetEntityQuery(
ComponentType.ReadOnly<ReferenceGameObjectFromEntityState>(),
ComponentType.Exclude<ReferenceGameObjectFromEntityTag>());
}
protected override void OnUpdate()
{
// Entityに紐付いているGameObjectとReferenceGameObjectFromEntityStateを破棄する。
Entities
.With(query)
.ForEach((ReferenceGameObjectFromEntityState data) =>
{
Object.Destroy(data.Value);
});
EntityManager.RemoveComponent<ReferenceGameObjectFromEntityState>(query);
}
}
/// <summary>
/// 自身のEntityが破棄された時、紐付いているGameObjectを破棄する。
/// ReferenceGameObjectFromEntityTagとセットで運用。
/// </summary>
public class ReferenceGameObjectFromEntityState : ISystemStateComponentData
{
public GameObject Value;
}
/// <summary>
/// ReferenceGameObjectFromEntityStateが紐付いているEntityが破棄されたかを確認するためのタグ。
/// ReferenceGameObjectFromEntityStateとセットで運用。
/// </summary>
public struct ReferenceGameObjectFromEntityTag : IComponentData { }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment