Entitas深入研究(2):Unity交互

特殊说明:本文参照siki学院视频教程以及官方示例做的一个Entitas与Unity交互的例子,重点在于提供一种交互思维。浏览本教程前,请先浏览基础篇教程

设计大纲:本例子很简单,大概内容如下:
1.鼠标左键按下时,在当前鼠标点击地方创建子弹对象。
2.鼠标右键按下时,将创建的子弹对象对准当前鼠标点击方向移动到鼠标点击坐标的地方。

编写代码:例子目录如下图所示:
在这里插入图片描述
具体流程如下:
1.在Sources/Const目录中创建通用枚举类Enums.cs文件。用来记录例子中用到的所有枚举。代码如下:

using UnityEngine;

/// <summary>
/// 鼠标类型
/// </summary>
public enum MouseButtonType
{
    LEFT,
    RIGHT
}

/// <summary>
/// 鼠标事件
/// </summary>
public enum MouseButtonEvent
{
    DOWN,
    PRESS,
    UP
}

2.在Interation/Components/Game目录下添加ViewComponent.cs文件。用来定义视图中的游戏对象,此时游戏对象就是该组件持有的数据。代码如下:

using UnityEngine;
using Entitas;

namespace Interation
{
    /// <summary>
    /// 视图层组件
    /// </summary>
    [Game]
    public class ViewComponent : IComponent
    {
        /// <summary>
        /// 子弹对象
        /// </summary>
        public Transform bulletTrans = null;
    }
}

3.在Interation/Components/Input目录下添加MouseComponent.cs文件。用来记录全局唯一的鼠标操作。代码如下:

using Entitas;
using Entitas.CodeGeneration.Attributes;
using UnityEngine;

namespace Interation
{
    /// <summary>
    /// 鼠标点击组件
    /// </summary>
    [Input, Unique]
    public class MouseComponent : IComponent
    {
        /// <summary>
        /// 点击的鼠标类型
        /// </summary>
        public MouseButtonType mouseType;
        /// <summary>
        /// 鼠标事件
        /// </summary>
        public MouseButtonEvent mouseEvent;
    }
}

4.在Interation/System目录下添加MouseSystem.cs文件。主要是对Unity鼠标左右键和按下弹起等状态进行监听,并修改鼠标组件。代码如下:

using UnityEngine;
using Entitas;

namespace Interation
{
    public class MouseSystem : IExecuteSystem
    {
        private InputContext _inputContext;

        public MouseSystem(Contexts contexts)
        {
            _inputContext = contexts.input;
        }

        public void Execute()
        {
            // 更新鼠标左键点击
            if (Input.GetMouseButtonDown(0))
            {
                _inputContext.ReplaceInterationMouse(MouseButtonType.LEFT, MouseButtonEvent.DOWN);
            }

            // 更新鼠标右键点击
            if (Input.GetMouseButtonDown(1))
            {
                _inputContext.ReplaceInterationMouse(MouseButtonType.RIGHT, MouseButtonEvent.DOWN);
            }
        }
    }
}

5.在Interation/System目录下添加ViewSystem.cs文件。主要是在鼠标组件更新时,对鼠标左键进行监听,并创建视图对象以及初始化该对象中的子弹对象,包括设置精灵和起始坐标。代码如下:

using UnityEngine;
using System.Collections.Generic;
using Entitas;
using Entitas.Unity;

namespace Interation
{
    public class ViewSystem : ReactiveSystem<InputEntity>
    {
        /// <summary>
        /// 视图父节点对象
        /// </summary>
        private Transform _viewParent;

        /// <summary>
        /// 游戏层上下文对象
        /// </summary>
        private GameContext _gameContext;

        public ViewSystem(Contexts context)
            : base(context.input)
        {
            _viewParent = new GameObject("ViewParent").transform;

            _gameContext = context.game;
        }

        protected override bool Filter(InputEntity entity)
        {
            return entity.hasInterationMouse
                && entity.interationMouse.mouseType == MouseButtonType.LEFT
                && entity.interationMouse.mouseEvent == MouseButtonEvent.DOWN;
        }

        protected override ICollector<InputEntity> GetTrigger(IContext<InputEntity> context)
        {
            return context.CreateCollector(InputMatcher.InterationMouse);
        }

        protected override void Execute(List<InputEntity> entities)
        {
            foreach (InputEntity entity in entities)
            {
                // 向ViewParent游戏对象中添加一个View对象
                GameEntity gameEntity = _gameContext.CreateEntity();

                GameObject go = new GameObject("View");
                go.transform.SetParent(_viewParent);
                go.Link(gameEntity);
                gameEntity.AddInterationView(go.transform);

                // 向子弹对象上添加SpriteRender并加载精灵显示
                Transform bulletTrans = gameEntity.interationView.bulletTrans;
                SpriteRenderer sr = bulletTrans.gameObject.AddComponent<SpriteRenderer>();
                sr.sprite = Resources.Load<Sprite>("Bullet");

                // 将鼠标position值赋给子弹对象
                Vector2 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                bulletTrans.position = worldPos;
            }
        }
    }
}

6.在Interation/System目录下添加MoveSystem.cs文件。主要是在鼠标组件更新时,对鼠标右键进行监听,并对所有视图对象中的子弹进行旋转和移动操作。此处用到了DoTween,需要再Libraries中添加该库的文件,如上图所示。代码如下:

using UnityEngine;
using System.Collections.Generic;
using Entitas;
using DG.Tweening;

namespace Interation
{
    public class MoveSystem : ReactiveSystem<InputEntity>
    {
        private GameContext _gameContext;

        public MoveSystem(Contexts context)
            : base(context.input)
        {
            _gameContext = context.game;
        }

        protected override ICollector<InputEntity> GetTrigger(IContext<InputEntity> context)
        {
            return context.CreateCollector(InputMatcher.InterationMouse);
        }

        protected override bool Filter(InputEntity entity)
        {
            return entity.hasInterationMouse
                && entity.interationMouse.mouseType == MouseButtonType.RIGHT
                && entity.interationMouse.mouseEvent == MouseButtonEvent.DOWN;
        }

        protected override void Execute(List<InputEntity> entities)
        {
            IGroup<GameEntity> _viewGroup = _gameContext.GetGroup(GameMatcher.InterationView);
            foreach (GameEntity entity in _viewGroup)
            {
                // 修改子弹对象的角度
                Vector2 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                Vector3 targetPos = worldPos;
                Transform bulletTrans = entity.interationView.bulletTrans;
                Vector3 direction = (targetPos - bulletTrans.position).normalized;
                Quaternion angle = Quaternion.FromToRotation(bulletTrans.up, direction);
                bulletTrans.rotation *= angle;

                // 使用dotween对子弹对象进行移动到指定目标坐标上
                bulletTrans.DOMove(targetPos, 3);
            }
        }
    }
}

7.在Interation/Feature目录下添加InputFeature.cs文件。主要是将监听Input实体的System进行整合。顺便提一下:如果存在监听Game视体或者其他自定义视体的System,也要创建对应的实体类型Feature文件来进行整合。代码如下:

using UnityEngine;
using Entitas;

namespace Interation
{
    public class InputFeature : Feature
    {
        public InputFeature(Contexts context)
        {
            Add(new MouseSystem(context));
            Add(new ViewSystem(context));
            Add(new MoveSystem(context));
        }
    }
}

8.在Interation/Controller目录下添加GameController.cs文件。主要是用来挂载到场景上充当入口文件使用。并在Start和Update等生命周期中,对游戏中的System做生命周期操作。代码如下:

using UnityEngine;
using Entitas;

namespace Interation
{
    public class GameController : MonoBehaviour
    {
        private Systems _systems;

        void Start()
        {
            Contexts contexts = Contexts.sharedInstance;
            _systems = new Feature("Systems").Add(new InputFeature(contexts));
            //_systems.Initialize();
        }

        void Update()
        {
            _systems.Execute();
            _systems.Cleanup();
        }
    }
}

9.新建游戏场景,并将GameController.cs挂载到当前场景上,然后将相机改成正交类型。如图所示:
在这里插入图片描述
友情提醒
1.在编写完Component后记得使用Entitas生成以下代码,否则System中使用实体就会找不到对应Component。

2.属性Game和属性Input分别标明是GameEntity和InputEntity中的组件。在自定导出组件代码时,会生成到不同的Components目录下。而且在System中使用时也要给对实体类型泛型。如图所示:
在这里插入图片描述
3.属性Unique表示全局唯一的意思。此时自动导出组件代码时,会在xxxContext中生成代码,使用时应该从xxxContext中获取。不是Unique属性的组件使用时应该从xxxEntity中获取。如图所示:
在这里插入图片描述
在这里插入图片描述
4.没有任何内容的Component,在自动生成代码时,会生成一个bool类型的接口,用来判定是否有组件。如图所示:
在这里插入图片描述在这里插入图片描述
5.组件导出时生成的文件名是以实体类型标签+命名空间+Component类名组成的。如下图所示:
在这里插入图片描述

发布了81 篇原创文章 · 获赞 39 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zjz520yy/article/details/87932615
今日推荐