ã¯ããã«
ã©ãããåéã§ãã
ããã¯åéã²ã¨ã Advent Calendar 2024ã®2æ¥ç®ã®è¨äºã§ãã
ååã¯åéããã®【ECS&DI】Unity ECSでVContainerによるDIをやってみる - 土鍋で雑多煮ã§ããã
ãã¦ãECSã§é½å¸éçºã·ãã¥ã¬ã¼ã·ã§ã³ã²ã¼ã ãä½ãã·ãªã¼ãº4åç®ã¯ãããã建ç¯ã§ããããã«ãããã¨æãã¾ãã
ã¨ãã£ã¦ãã建ç©é¸ãã§Instantiateããã ãã§ãããã¾ã¼ã¼ECSã®ä»æ§ããããã£ã¦æãããã¾ããã
- ã¯ããã«
- 建ç¯ç©é¸æã¡ãã¥ã¼UI
- Raycastã«ãã建ç©é ç½®å ´æã®æ±ºå®
- Entityã®çæ
- ã¾ã¨ã
- åè
建ç¯ç©é¸æã¡ãã¥ã¼UI
ECSã¨UI Toolkit
ä»åã®ã²ã¼ã éçºã§ã¯ãªãã¹ãUnityã®æ°ããè¦ç´ ã«è§¦ããããã«ãããã¨ããææ³ã®å ãéçºãã¦ããã®ã§ãUIã«é¢ãã¦ãUI Toolkitãå°å ¥ãã¾ããã
UIãæ§ç¯ãã
建ç¯ããã建ç©ãé¸ã¶ã¡ãã¥ã¼ãã©ããããããªï½ã¨æã£ããã§ããããã£ã±ã°ãªãããã¥ã¼ãä¸çªè¦èªæ§ããããæ
å ±éãå¤ãã¦ããããªã¨æãå®è£
ãã¾ããã
ãã ããã§çºçããåé¡ãUI Toolkitã«ã°ãªãããã¥ã¼ããªãã¨ããåé¡ã§ããã(uGUIã«ã¯ããã®ã«ï¼)
ã¨ãããã¨ã§èªåã§å®è£ ãã¦å¥è¨äºã«ã¾ã¨ããã®ã§ãã覧ãã ããã
ClickEventã®è¨å®
ä¸è¨ã®è¨äºã§ã°ãªãããã¥ã¼ã®ä½æã¨ããã«DataãBindingããã¨ãã¾ã§å®è£ ããã®ã§ããã©ã¹ã¢ã«ãã¡ã§ã©ã®å»ºç©ãé¸æãããã®æ å ±ãPlayerStatusHolderã«æ¸¡ãã¦ãã¾ãã
public class ConstructMenu : MonoBehaviour { [SerializeField] private VisualTreeAsset buildingElement; // ã°ãªããè¦ç´ ãã³ãã¬ã¼ã [SerializeField] private BuildingList buildingList; // 追å ãããUIè¦ç´ ã®Listä¿æScriptableObject private void Start() { var root = GetComponent<UIDocument>().rootVisualElement; foreach (var building in buildingList.buildings) { var buildingTemplate = buildingElement.Instantiate(); // ãã³ãã¬ã¼ãã®çæ buildingTemplate.Q<VisualElement>("thumbnail").dataSource = building; // ãã¼ã¿ã®ãã¤ã³ã root.Q<VisualElement>("Grid").contentContainer.Add(buildingTemplate); // ã°ãªããã«è¦ç´ 追å buildingTemplate.RegisterCallback<ClickEvent, BuildingData>(Clicked, building); // ã¯ãªãã¯ã¤ãã³ãã®ç»é² } } private void Clicked(ClickEvent evt, BuildingData data) { Debug.Log("Click: " + data.buildingName); PlayerStatusHolder.I.NowSelectConstructBuildingID = data.buildingID; // PlayerStatusHolderã«IDã渡ã } }
Raycastã«ãã建ç©é ç½®å ´æã®æ±ºå®
Entityæ å ±ã®åå¾
é常ã®ç»é¢ã¯ãªãã¯ããã®Raycastã§ã¯ECSã®Entityæ
å ±ã¯åå¾ã§ãã¾ããã
ãã®ãããECSç¨ç©çã·ãã¥ã¬ã¼ã·ã§ã³ããã±ã¼ã¸ã®Physicsã使ãã¾ãã
å®è£
æ¹æ³ã¯å¥è¨äºã«ã¾ã¨ããã®ã§ãã¡ããã覧ãã ããã
UIä¸ã§ã¯Raycastããããã¯
ãã®Raycastã¯UIä¸ãæ§ãã貫éãã¦Rayãé£ã°ãã®ã§å¯¾çãå¿
è¦ã«ãªã£ã¦ãã¾ãã
ãããå¥è¨äºã«æ¸ããã®ã§ããã¡ããåç
§ãã¦ãã ããã
Entityã®çæ
ãã¦ããã¾ã§ã§ãããã建ç©é¸æã¨é ç½®ã®ããã®Raycastãå®è£ ã§ããã®ã§ãæå¾ã¯å»ºç©ã®Entityãçæããå¿ è¦ãããã¾ãã
Prefabã®Bake
建ç©ã®Prefabãä½ã£ãã®ã¯è¯ãã®ã§ãããããã¯GameObjectãªã®ã§ãã®ã¾ã¾ECSã§ã¯ä½¿ãã¾ããã
ãã®ããBakeãè¡ãå¿
è¦ãããã®ã§ãããã©ã³ã¿ã¤ã ã§çææã«Bakeã¯è¡ãã¾ããã
(èªåã¯ãã®ææ³ãçºè¦ã§ããªãã£ãã®ã§ãåãã®æ¹ããã£ãããã¾ããããææããã ãããã§ã)
建ç©ã®ç¨®é¡ãã¹ã¦ã«Bakeãè¡ãããã«ãé©å½ãªMonoBehaviorã¯ã©ã¹ã«Listãªã©ã§å ¨Prefabãä¿æããã¦ãåçæã«ä¸æ¬Bakeããã¾ããã
æ®éã«GameObjectã®ListããGetEntityã§EntityãAddãã¦ããã°ããã ããã¨æããã
ArgumentException: srcEntity is not a valid entity
InvalidOperationException: Baking error: Attempt to add duplicate component
ã®ãããªã¨ã©ã¼ãåºã¦ãã¾ããè¦å´ãã¾ãããã以ä¸ã®è¨äºãåèã«ããã¦ããã ããæ¸ãç´ããã¨ãããªãã¨ãåãã¾ããã
[System.Serializable] public struct PrefabEntityComponent : IComponentData // ä¸èº«ãªã â Tagçæ±ã { } public struct PrefabElement : IBufferElementData { public Entity prefabEntity; }
public class PrefabBaker : MonoBehaviour { [SerializeField] private List<GameObject> prefabs; class Baker : Baker<PrefabBaker> { public override void Bake(PrefabBaker authoring) { var entity = GetEntity(TransformUsageFlags.Dynamic); var sample = new PrefabEntityComponent(); var buffer = AddBuffer<PrefabElement>(entity); foreach (var prefab in authoring.prefabs) { buffer.Add(new PrefabElement { prefabEntity = GetEntity(prefab, TransformUsageFlags.Dynamic) }); } AddComponent(entity, sample); } } }
ç»åã®ããã«ã¤ã³ã¹ãã¯ã¿ã¼ããBakeãããPrefabãæå®ãã¦ããããã¨ã§ããã®Prefab群ãèªåçã«Bakeããããã«ãªãã¾ããã
Entityã®çæ
ãã¨ã¯ä»¥ä¸ã®ãããªã³ã¼ããã¯ãªãã¯æã«å®è¡ãã¦ãããã°ã¯ãªãã¯ããå ´æã«çæããã¾ãã
if (physics.CastRay(input, out var hit)) { var name = this.EntityManager.GetName(hit.Entity); if (name == "Plane") // ããååã§ãã£ã¦ãã®ãããªãã®ã§å¤ãã¾ã { foreach (var buffer in SystemAPI.Query<DynamicBuffer<PrefabElement>>().WithAll<PrefabEntityComponent>()) { for (int i = 0; i < buffer.Length; i++) { var entity = buffer[i].prefabEntity; if (PlayerStatusHolder.I.NowSelectConstructBuildingID == BuildingLookup[entity].BuildingID) { var buildingTransform = SystemAPI.GetComponentRW<LocalTransform>(entity); buildingTransform.ValueRW.Position = new float3(hit.Position.x, hit.Position.y + buildingTransform.ValueRW.Scale/2, hit.Position.z); // çæå ´æã®æ±ºå® EntityManager.Instantiate(entity); // Entityã®çæ } } } } }
å®æ
ã¾ã¨ã
MonoBehaviorãªãç°¡åãªãã¨ãããªãè³ã¿ã使ãã¾ããâ¦ã
ãã ãä»åã®å®è£
ã§ã ãã¶ECSã®æ°æã¡ãåãã£ã¦ãã¾ããã