(二) ECS: Pure vs Hybrid

目前的ECS分为两种 Pure ECSHyBridECS 区别主要就是Pure版的不能使用GameObjects 和 MonoBehaviours ,当然这中理解很表面,但是刚开始嘛?

Pure——》干净纯洁

HyBrid——》混合的

我也从Youtube上找到了一些资料分享出来。

Pure ECS系统特点:

1.Entities是一个新的Gameobjects

2.实体上没有多余的Mono脚本:数据存储在Components上;逻辑执行处理在System里面

3.可以利用C# 的 Job System系统来进行工作,这点很有优势啊

Hybrid ECS系统特点:

1.包括所有Pure ECS 的功能

2.一些特别的工具类:把GameObject当成Entities;把Mono脚本当成Components

3.更多的支持原生Unity的类

当然可以看出来Hybrid ECS 更加具有开发游戏和原先的开发习惯也比较符合。

————————————————————————————————————————————————————————

当然我们用ECS开发首先要打开Entity Debugger的功能在 Windows菜单栏下——》Analysis——》Entity Debugger。ECS有别于传统的Unity游戏开发需要有专门的窗口来查看创建的物体信息。

Hybrid ECS使物体移动(Unity2018.3f2):

1.首先创建场景中的平面和一个胶囊体:

胶囊体上挂在一个GameObjectEntity脚本,此时可以在Debugger中看到存在一个实体:

我们要让胶囊体进行移动,按照ECS思想需要先创建Components把数据存放在里面,并且由于Hybrid特点我们可以把Components当成原先Unity开发的Components挂载到GameObjec上。

Hybrid ECS 中的Speed组建(Components):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace HyBridECS//这里就是为了和后面的Pure区别加了个命名空间
{
    public class Speed : MonoBehaviour
    {
        public float Value;//Speed 组件中的数据值
    }
}

Hybrid ECS 中的PlayerInput组建(Components):

namespace HyBridECS
{
    public class PlayerInput : MonoBehaviour
    {
        public float Horizontal;//数据
    }
}

然后我们需要添加数据处理的System,创建一个PlayerMovementSystem继承自ComponentSystem:

using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;

namespace HyBridECS
{
    public class PlayerMovementSystem : ComponentSystem
    {
        /// <summary>
        /// 创建一个结构体,ECS现在处理的只能是结构体(关于结构体和类的区别自行Google就好)
        /// </summary>
        private struct Group//这里的意思就是说查找到符合这种结构的实体
        {
            public Transform Transform;
            public PlayerInput PlayerInput;
            public Speed Speed;
        }

        protected override void OnUpdate()//这里是处理的逻辑核心
        {
            foreach (var entity in GetEntities<Group>())//寻找到所有符合Group结构的实体
            {
                Vector3 position = entity.Transform.position;
                Quaternion rotation = entity.Transform.rotation;
                position.x += entity.Speed.Value * entity.PlayerInput.Horizontal * Time.deltaTime;
                rotation.w += math.clamp(entity.PlayerInput.Horizontal, -.5f, .5f);
                entity.Transform.position = position;
                entity.Transform.rotation = rotation;
            }
        }
    }
}

写道这里其实只是处理完成移动的System,由于ECS特点C要单独对应S(嗯这点有点烦 很操蛋?),所以就会发现我们没有处理玩家输入的System!!!所以接着添加一个PlayerInputSystem:

using Unity.Entities;
using UnityEngine;

namespace HyBridECS
{
    public class PlayerInputSystem : ComponentSystem
    {
        /// <summary>
        /// 创建一个结构体
        /// </summary>
        public struct Group//这里的意思就是说查找到符合这种结构的实体
        {
            public PlayerInput PlayerInput;
        }

        protected override void OnUpdate()
        {
            foreach (Group entity in GetEntities<Group>())
            {
                entity.PlayerInput.Horizontal = Input.GetAxis("Horizontal");
            }
        }
    }
}

我们可以在Debugger中看到有我们自己添加的组建信息

在System中可以看到系统调用的System,可以手动取消勾选System这样系统就不会在执行Systems了:

用ECS写了BUG估计调试就麻烦了,想问一下大家调试有什么好的方法吗?

然后你在编辑器中就可以点击“A”或者“S”就可以看到游戏物体的移动了?,ECS中调用System并不需要我们自己进行操作,这是由系统自己调用的,So我也不是很清楚里面的具体代码 还没有研究过!!!有大神可以指导一下小弟我啊。

PureECS使物体移动(Unity2018.3f2):

不同于Hybrid ECS ,Pure ECS的组建不需要挂载到游戏中的物体上同时组建继承也有所区别是:

namespace PureECS
{
    public class Speed : IComponentData//继承有所区别
    {
        public float Value;
    }
}
using System.Collections;
using Unity.Entities;

namespace PureECS
{
    public class PlayerInput : IComponentData//继承有所区别
    {
        public float Horizontal;
    }
}

因为我们不要把脚本挂在Go上但是场景中我们还是需要一个Mono脚本来进行调用,在场景中创建一个Boot物体并在Boot上进行添加控制脚本Boot:

using Unity.Entities;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;

namespace PureECS
{
    public class Boot : MonoBehaviour
    {
        public float Speed;//这里外面设置参数好进行代码生成物体
        public Mesh Mesh;
        public Material Material;

        void Start()
        {
            EntityManager entityManager = World.Active.GetOrCreateManager<EntityManager>();//获取场景中EntityManager脚本,这个可以在Debugger中System看到
            Entity playerEntity = entityManager.CreateEntity(//创建出来是一个结构体,通过代码创建
                ComponentType.Create<Speed>(),//只有俩个自己定义的组建
                ComponentType.Create<PlayerInput>(),//只有俩个自己定义的组建
                ComponentType.Create<Position>(),
                ComponentType.Create<Transform>(),
                ComponentType.Create<MeshInstanceRenderer>()
            );

            entityManager.SetComponentData(playerEntity, new Speed { Value = Speed });//设置组建关联信息
            entityManager.SetSharedComponentData(playerEntity, new MeshInstanceRenderer
            {
                mesh = Mesh,
                material = Material
            });
        }
    }
}

这时候运行代码就可以看到在场景中有了生成的物体(别忘了Boot上设置参数)但是在Hierarchy中是看不到生成的物体的只能在Debugger中进行查看。

在Pure ECS中C对应的S所要继承的是JobComponentSystem,俩个System:

using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;
using UnityEngine;

namespace PureECS
{
    public class PlayerMovementSystem : JobComponentSystem
    {
        /// <summary>
        /// 类似于HyBrid ECS的Struct,我这理解也不是很深
        /// </summary>
        private struct PlayerMovementJob : IJobProcessComponentData<Speed, PlayerInput, Position>
        {
            public float DeltaTime;

            public void Execute(ref Speed speed, ref PlayerInput input, ref Position position)
            {
                position.Value.x += speed.Value * input.Horizontal * DeltaTime;
            }
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps)//这里是处理的逻辑核心
        {
            PlayerMovementJob job = new PlayerMovementJob
            {
                DeltaTime = Time.deltaTime
            };
            return job.Schedule(this, inputDeps);
        }
    }
}
using Unity.Entities;
using Unity.Jobs;
using UnityEngine;

namespace PureECS
{
    public class PlayerInputSystem : JobComponentSystem
    {
        private struct PlayerInputJob : IJobProcessComponentData<PlayerInput>
        {
            public float Horizontal;

            public void Execute(ref PlayerInput input)
            {
                input.Horizontal = Horizontal;
            }
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            PlayerInputJob job = new PlayerInputJob
            {
                Horizontal = Input.GetAxis("Horizontal")
            };
            return job.Schedule(this, inputDeps);
        }
    }
}

然后你就会发现场景里面的物体又可以移动了。ECS现在最主要的就是这俩个 先了解会用 深入问题慢慢搞。

关于一些API接口后续再来讨论。

发布了71 篇原创文章 · 获赞 89 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/u012371712/article/details/87527005
ECS