Unity DOTS中創建一個AssetBundle并將其用作Entity
-
創建一個新的Unity項目,并確保已啟用DOTS功能。
-
創建一個AssetBundle,可以通過在Project視圖中右鍵單擊文件夾并選擇“Create > AssetBundle”來創建。
-
將您想要轉換為Entity的資源(例如模型、紋理等)拖放到AssetBundle中。
-
創建一個新的C#腳本,用于加載AssetBundle并將其轉換為Entity。以下是一個示例代碼:
System間的數
using Unity.Entities;
using Unity.Transforms;
using Unity.Rendering;
using UnityEngine;
using Unity.Mathematics;
public class AssetBundleToEntity : MonoBehaviour
{
? ? public GameObject prefab;
? ? public Material material;
? ? void Start()
? ? {
? ? ? ? var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
? ? ? ? var entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, World.Active);
? ? ? ? Entity entity = entityManager.Instantiate(entityPrefab);
? ? ? ? entityManager.AddComponentData(entity, new Translation { Value = new float3(0, 0, 0) });
? ? ? ? entityManager.AddSharedComponentData(entity, new RenderMesh
? ? ? ? {
? ? ? ? ? ? material = material,
? ? ? ? ? ? mesh = entityManager.GetSharedComponentData<RenderMesh>(entityPrefab).mesh
? ? ? ? });
? ? }
}
據傳遞
動態加載代碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Rendering;
using Unity.Mathematics;
public class DynamicAssetBundleLoading : MonoBehaviour
{
? ? public string assetBundlePath;
? ? public string assetName;
? ? public Material material;
? ? IEnumerator Start()
? ? {
? ? ? ? AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(assetBundlePath);
? ? ? ? yield return request;
? ? ? ? AssetBundle assetBundle = request.assetBundle;
? ? ? ? AssetBundleRequest assetRequest = assetBundle.LoadAssetAsync<GameObject>(assetName);
? ? ? ? yield return assetRequest;
? ? ? ? GameObject prefab = assetRequest.asset as GameObject;
? ? ? ? var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
? ? ? ? var entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, World.Active);
? ? ? ? Entity entity = entityManager.Instantiate(entityPrefab);
? ? ? ? entityManager.AddComponentData(entity, new Translation { Value = new float3(0, 0, 0) });
? ? ? ? entityManager.AddSharedComponentData(entity, new RenderMesh
? ? ? ? {
? ? ? ? ? ? material = material,
? ? ? ? ? ? mesh = entityManager.GetSharedComponentData<RenderMesh>(entityPrefab).mesh
? ? ? ? });
? ? ? ? assetBundle.Unload(false);
? ? }
}
釋放Entity
using Unity.Entities;
using Unity.Transforms;
using Unity.Rendering;
using UnityEngine;
public class ReleaseEntity : MonoBehaviour
{
? ? EntityManager entityManager;
? ? void Start()
? ? {
? ? ? ? entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
? ? ? ? // 創建Entity
? ? ? ? Entity entity = entityManager.CreateEntity();
? ? ? ? // 添加組件數據
? ? ? ? entityManager.AddComponentData(entity, new Translation { Value = new float3(0, 0, 0) });
? ? ? ? // 添加SharedComponent數據
? ? ? ? entityManager.AddSharedComponentData(entity, new RenderMesh
? ? ? ? {
? ? ? ? ? ? material = GetComponent<Renderer>().material,
? ? ? ? ? ? mesh = GetComponent<MeshFilter>().sharedMesh
? ? ? ? });
? ? }
? ? void OnDestroy()
? ? {
? ? ? ? // 釋放Entity
? ? ? ? entityManager.DestroyEntity(entity);
? ? ? ? // 釋放相關的GameObject和AssetBundle引用
? ? ? ? Destroy(gameObject);
? ? ? ? Resources.UnloadUnusedAssets();
? ? }
}
System以MonoBehaviour數據事件通知
在Unity的Data-Oriented Technology Stack (DOTS)中,如果您希望在ECS系統中的Job執行完畢后通知MonoBehaviour或外部代碼,可以使用Unity的Events系統或自定義事件系統來實現通信。以下是一種常見的方法:
- 使用Unity的Events系統:
- 在MonoBehaviour中定義一個事件,當事件被觸發時通知外部代碼。
- 在ECS系統中,創建一個System,在System中檢查Job是否執行完畢,并在適當的時機觸發MonoBehaviour中定義的事件。
-
using Unity.Entities;
using UnityEngine;
using UnityEngine.Events;public class JobCompletedEvent : MonoBehaviour
{
? ? public UnityEvent onJobCompleted;? ? public void TriggerJobCompletedEvent()
? ? {
? ? ? ? onJobCompleted.Invoke();
? ? }
}public class JobCompletionSystem : ComponentSystem
{
? ? protected override void OnUpdate()
? ? {
? ? ? ? // 檢查Job是否執行完畢
? ? ? ? if (jobCompleted)
? ? ? ? {
? ? ? ? ? ? // 獲取JobCompletedEvent組件
? ? ? ? ? ? JobCompletedEvent jobCompletedEvent = FindObjectOfType<JobCompletedEvent>();? ? ? ? ? ? // 觸發事件通知外部代碼
? ? ? ? ? ? jobCompletedEvent?.TriggerJobCompletedEvent();
? ? ? ? }
? ? }
} - 自定義事件系統:
- 創建一個自定義的事件系統,允許ECS系統和MonoBehaviour之間進行通信。
- 在ECS系統中,觸發自定義事件來通知MonoBehaviour或外部代碼。
-
using Unity.Entities;
using UnityEngine;public class CustomEventSystem : ComponentSystem
{
? ? public delegate void JobCompletedEventHandler();
? ? public static event JobCompletedEventHandler OnJobCompleted;? ? protected override void OnUpdate()
? ? {
? ? ? ? // 檢查Job是否執行完畢
? ? ? ? if (jobCompleted)
? ? ? ? {
? ? ? ? ? ? // 觸發自定義事件通知外部代碼
? ? ? ? ? ? OnJobCompleted?.Invoke();
? ? ? ? }
? ? }
}
-
IBufferElementData
要將DynamicBuffer與Entity關聯,我們只需要定義需要的IBufferElementData,而不是DynamicBuffer本身,使用GenerateAuthoringComponent屬性會自動幫我們生成DynamicBuffer并添加到Entity上,這里需要注意一下,下面定義一個簡單的IBufferElementData看一下吧:
-
using Unity.Entities;[GenerateAuthoringComponent] public struct IntBufferElement : IBufferElementData {public int Value; }
?添加與釋放
EntityManager.AddComponent<IntBufferElement>(yourEntity);
EntityManager.RemoveComponent<IntBufferElement>(yourEntity);