Unity ProjectTiny纯ECS简单写个按钮点击事件系统

ProjectTiny包里是有UI模块的,当然功能肯定没GameObject的UI强大,常用的Text、Button、Image都有,还没仔细用过,先不用它。

点击了哪个按钮,然后需要执行对应的什么事件,这么点逻辑用ECS来写是很方便的,甚至可以比MonoBehavior写的简单。大致流程是,在运行时动态创建Mesh作为一个按钮,然后设置好Mesh的UV来显示纹理指定部分的字母作为按钮的label(这两个要点可以看前面几篇文章来进行实现),最后写个System来监听点击了哪个按钮,其他System就可以调用该System的接口来判断并执行点击事件了。

为了简单起见,就不动态创建Mesh并设置对应UV了,直接在Unity编辑器里创建4个Quad作为W、A、S、D按钮,也就是上下左右。Mesh也不用设置纹理,直接用空白的,按钮label并不影响点击事件。上代码:

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Tiny.Input;
using Unity.Tiny.Rendering;
using Unity.Tiny;

namespace ECSButton {
	[GenerateAuthoringComponent]
    public struct Button : IComponentData
    {
        public enum Type : byte {
            None,
            W, A, S, D
        }

        public enum State : byte {
            None,
            Down,
            Up
        }

        public Type type;

        public State state;
    }

    [UpdateInGroup(typeof(InitializationSystemGroup))]
    public class ButtonSystem : SystemBase
    {
        private InputSystem Input;

        private ScreenToWorld s2w;

        protected override void OnCreate() {
            base.OnCreate();
            Input = World.GetExistingSystem<InputSystem>();
            s2w = World.GetExistingSystem<ScreenToWorld>();
        }

        protected override void OnUpdate()
        {
            Dependency = Entities.WithAll<Button>().ForEach((Entity entity, ref Button button) => {
                if (button.state == Button.State.Down) {
                    button.state = Button.State.None;
                }
            }).Schedule(Dependency);

            if (Input.IsTouchSupported()) { // 触屏点击了按钮
                if (Input.TouchCount() == 1) {
                    var touch = Input.GetTouch(0);
                    if (touch.phase == TouchState.Began) {
                        OnClickDown(touch.x, touch.y);
                    }
                }
            } else { // 鼠标点击了按钮
                if (Input.GetMouseButtonDown(0)) {
                    var clickPos = Input.GetInputPosition();
                    OnClickDown(clickPos);
                }
            }
        }

        void OnClickDown(float x, float y) {
            var clickPosWS = s2w.ScreenSpaceToWorldSpacePos(new float2(x, y), 75);
            Dependency = Entities.WithAll<Button>().ForEach((Entity entity, ref Button button, in Translation translation) => {
                if (math.distance(new float3(clickPosWS.xy, 0), translation.Value) < 4) { // 这个数字4是写死的,可以根据按钮的Mesh大小计算出来
                    button.state = Button.State.Down;
                }
            }).ScheduleParallel(Dependency);
        }
        void OnClickDown(float2 pos) {
            OnClickDown(pos.x, pos.y);
        }

        public bool IsButtonDown(Button.Type type) {
            bool result = false;
            Entities.WithAll<Button>().ForEach((Entity entity, in Button button) => {
                if (button.state == Button.State.Down) {
                    if (type == button.type) {
                        result = true;
                    }
                }
            }).Run();
            return result;
        }
    }

	// 测试。其它System也是同样的用法
    public class TestButtonDownSystem : SystemBase
    {
        ButtonSystem buttonSystem;

        protected override void OnCreate() {
            base.OnCreate();
            buttonSystem = World.GetExistingSystem<ButtonSystem>();
        }

        protected override void OnUpdate()
        {
            if (buttonSystem.IsButtonDown(Button.Type.W)) {
                Debug.Log("Button W down");
            }
            else if (buttonSystem.IsButtonDown(Button.Type.A)) {
                Debug.Log("Button A down");
            }
            else if (buttonSystem.IsButtonDown(Button.Type.S)) {
                Debug.Log("Button S down");
            }
            else if (buttonSystem.IsButtonDown(Button.Type.D)) {
                Debug.Log("Button D down");
            }
        }
    }
}

Unity编辑器里的设置如下:
在这里插入图片描述

这个按钮很简单,就只有点击事件,不能设置按钮的锚点(没有分辨率适配),也不能设置按钮高亮跟按下状态,也没有点击后的震动反馈。按钮点击状态还是可以实现的,这里先不实现,目前只需要用到点击事件。

再贴个运行截图(因为要看打印日志,所以打包的是Web,安卓要看Log太麻烦了):
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值