using Unity.Entities;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 先将自己转换成实体,再由预设生成新的实体
/// </summary>
[RequiresEntityConversion] ///必须实体转化
public class SpawnerAuthoring_FromEntity : MonoBehaviour, IDeclareReferencedPrefabs, IConvertGameObjectToEntity
public GameObject m_Prefab;
public int m_CountX;
public int m_CountY;
/// <summary>
/// IDeclareReferencedPrefabs接口的实现,声明引用的预设,好让转化系统提前知道它们的存在
/// </summary>
/// <param name="referencedPrefabs">引用的预设</param>
public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
referencedPrefabs.Add(m_Prefab);
/// <summary>
/// 我们将编辑器的数据表述转化成实体最佳的运行时表述
/// </summary>
/// <param name="entity">实体</param>
/// <param name="dstManager">目标实体管理器</param>
/// <param name="conversionSystem">转化系统</param>
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
var spawnerData = new Spawner_FromEntity
/// 被引用的预设因为做了声明将被转化成实体
/// 所以我们这里只是将游戏对象标记到一个引用该预设的实体上
m_Porfab = conversionSystem.GetPrimaryEntity(m_Prefab),
m_CountX = m_CountX,
m_CountY = m_CountY
dstManager.AddComponentData(entity, spawnerData);
这段代码大家应该有一部分是有印象的,只是,这次的复杂一点。
但要理解还是没问题的,仍然一步步来:
a.这个类继承了MonoBehaviour,所以肯定也是要挂到GameObject下的
b.继承了IConvertGameObjectToEntity接口,于是也要实现Convert函数,Convert函数要做的事情和以前差不多,创建一个组件,然后把组件添加到实体里。
c.但是,这个组件有点特别,这个组件有一个Prefab字段,是Entity类型的。于是,调用GameObjectConversionSystem的GetPrimaryEntity函数,可以将我们的GameObject对象转换为Entity对象,然后赋值给组件。
d.于是,我们将当前的GameObject转换为了一个包含Spawner_FromEntity组件的实体,这个实体的组件又包含了一个新创建的实体,这个新实体是通过我们的Prefab预制体创建的。
e.DeclareReferencedPrefabs函数是做什么用呢?是为了让GameObjectConversionSystem对象知道我们的Prefab预制体的存在,以便通过预制体创建实体。
有点绕是不是?实际上我们现在有了两个实体了。
第一个:当前MonoBehaviour转换后的实体,包含Spawner_FromEntity组件;
第二个:Spawner_FromEntity组件的字段引用了另外一个实体,这个是通过Prefab预制体创建的实体。
最后,再看一次我们的System类的OnUpdate函数:
a.我们通过Spawner_FromEntity类型筛选出了一个实体,也就是我们的第一个实体。
b.这个实体通过第一个参数【Entity entity】传递进来。
c.接着,通过Spawner_FromEntity组件的Prefab字段(引用了我们的第二个实体)创建了一个新的实体
d.调用DestoryEntity把筛选出来的实体删除(即,删除了我们的第一个实体,所以连同它的组件也消失了,于是第二个实体也消失了)
好了,可能大家有点绕懵了,但,这就是第二种创建实体的方式。
而且,比起以前介绍的方式,这反而是更加推荐的,可能更实用的。
然后大家创建一个空的GameObject,把SpawnerAuthoring_FromEntity挂上去,然后再给它的Prefab拖个预制体上去,然后运行:
7.这种创建实体的方式有什么优势?
“好麻烦,不实用”,大家可能心里是这么想的,说实话,我一开始也是,整这么乱做什么。
其实,只要大家熟悉了EntityCommandBufferSystem,就不会觉得乱了。
不会觉得乱之后呢,就会发现,这确实是目前为止最灵活的方式。
首先,我们把空的GameObject转换为了实体,但它只是一个空的实体,不会在场景里展现出来。
而这个空实体的组件里引用了一个真正有用的实体,但这个实体还没有添加到EntityManager中,所以它也不会展现出来。
于是,这就变成了,我们可以在任何时候创建这个实体,而不是在MonoBehaviour的Start函数里创建。
比如,我们需要点击召唤按钮才能召唤生物,这种灵活的创建方式,不就能满足我们的需求了吗?
不过,因为我还没有用ECS做实际开发,所以,实际当中到底怎么样,都不好说。
注意,本系列教程基于DOTS相关预览版的Package包,是预览版,不代表正式版的时候也适用。
下图出自同样不错的官方案例讲解:https://blog.csdn.net/qq_30137245/article/details/99083411
1.任务系统Jobs是C#为了让我们安全地使用多线程而封装的;
2.不能滥用任务系统,否则会引起线程之间的竞争,例如你有四个线程,但是现在有三个被占用,却有五个任务要完成,这时就3会五个任务去争夺一个线程,从而造成线程安全问题;
3.任务组件系统可以在工作线程上运行,但是创建和移除实体只能在主线程上做,从而防止线程之间的竞争;
4.为了确保任务可以完成,这里引入了命令缓存机制,就在先把任务缓存起来,等待主线程完成工作后,再进行增删实体的操作。
5.关于阻塞系统,是为了确保安全而生,当线程在执行任务的时候,将其阻塞起来,避免其他任务误入,等任务完成之后,再执行下一个任务,从而有序进行。
最近在学习unity的ecs框架,转载几篇写的比较好的文章帮助理解原文日期2019-12-5 避免误导未来使用正式版的开发者。接下来,我要给大家介绍一个很重要的东西——EntityCommandBufferSystem。1.不能在Job中执行的操作我们已经知道,JobComponentSystem配合各种Job(IJobForEach、IJobChunk等),可以方便地实现...
Systems
System, ECS三要素之一,负责把组件当中的数据从一个状态转换到另一个状态的逻辑, 比如,一个system可以可能会根据所有移动实体的速度乘以自上次更新以来的时间间隔来更新它们的位置。
Unity ECS 提供了多种不同的systems. main systems 主系统你可以实现转换实体数据的系统是 ComponentSystem 和JobComponentSyste.........
以下文档均来源于ECS官网:
https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/ecs_entities.html
Entity Command Buffer(实体命令缓存)
EntityCommandBuffer类解决了两个重要问题:
当在Job中时,无法访问EntityManager
当您访问Entity...
Entity Command Buffer (ECB)
在前面的例子中,我们都是通过EntityManager来创建或销毁Entity,或者给Entity添加删除Component。但是在实际的情况中,我们可能需要在System中来做这些操作,比如一个Entity有一个存活时长的属性,我们会用一个System来计算已存活的时间,当时间到了后销毁该Entity。
根据前面的知识,我们需要一个Component来存储这个存活时长的属性,例如:
struct Lifetime : IComponentDa
EntityCommandBufferSystem能使我们在System中创建/销毁Entity。
利用EntityCommandBufferSystem创建Entity
其实是利用EntityCommandBufferSystem将命令队列压入主线程执行。
1、首先设计Component:
using Unity.Entities;
public struct SpawnData : IComponentData
public int Count;
public Entity Tem
Unity ECS 小知识1 - PhysicsTrigger Event ,
ECS套件
学习过程中会遇到各种问题,专门开辟一个专题“
ECS小知识”来记录这些点滴。每个小知识文章是没有先后顺序的,这里是第一篇 - 物理触发器 。小知识的所有Demo,都是使用
ECS 0.50+的版本。具体不多做阐述,具体如何安装
ECS环境,可以看我之前的文章 -
Unity DOTS
学习笔记1 -
ECS 0.50介绍和安装那么用例开始。
Using Entity Command Buffers – Unite Copenhagen 2019
https://www.youtube.com/watch?v=SecJibpoTYw
https://www.slideshare.net/unity3d/using-entity-command-buffers-unite-copenhagen-2019
https://...
新的物理系统是什么?
Unity Physics是在
ECS上运行物理的附加功能。这个物理操作并不完全是
Unity过去使用的过去和安全的PhysX,而是使用C#完全重建的物理操作。
物理学的作用如下。
搜索空间以进行碰撞...
学习 Unity ECS 需要先了解 Unity 游戏引擎的基本知识,然后再学习 ECS 的相关知识。推荐以下学习方式:
1. 阅读官方文档:https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/index.html
2. 完成官方提供的 ECS 教程:https://learn.unity.com/project/unity-ecs-tutorial
3. 尝试自己创建一个简单的 ECS 项目,并在此过程中查阅相关资料解决问题
4. 加入 Unity 社区,与其他开发者一起讨论 ECS 相关问题
希望这些建议能帮助你开始学习 Unity ECS。