Unity DOTS纯ECS实现虚拟摇杆Joystick控制角色移动

上篇已经实现了ECS框架下的IBeginDragHandlerIDragHandlerIEndDragHandler这几个拖动事件,使得可以任意给ECS框架下的UI(2D entity)响应拖动事件。本篇分享下在前篇实现的功能的基础上再实现一个常用的摇杆控制角色移动的功能。

需要注意的一点,目前Unity最新的Entities包是无法纯ECS写代码的,还有很多GameObject和组件无法转成Entity和IComponentData,所以要体验纯ECS写代码,得下载那个很久没更新过的ProjectTiny包,它的Entities版本还停留在0.17阶段。

代码不多,直接上代码:

using Unity.Entities;
using Unity.Mathematics;
using Unity.Tiny.UI;
using wangtal.EventSystem;
using TinyUI;namespace wangtal.Joystick {public struct Joystick : IComponentData {public readonly struct Settings : IComponentData {// 可拖动的范围,可以大于背景的圆形public readonly float Radius;public Settings(float radius) {Radius = radius;}}public Entity Entity {get; private set;}public Entity Knob {get; private set;}public Entity Highlight {get; private set;}// 拖动距离public float Distance;public float2 Direction;public Joystick(Entity joystickEntity, Entity knob, Entity highlight) {Entity = joystickEntity;Knob = knob;Highlight = highlight;Distance = 0;Direction = float2.zero;}}public abstract class JoystickSystem : SystemBase, IBeginDragHandler, IDragHandler, IEndDragHandler{// 上上篇实现的ECS下的UI分辨率适配系统-用来实现分辨率变化后,UI大小跟着变private CanvasScalerSystem canvasScalerSystem;protected override void OnCreate(){base.OnCreate();RequireSingletonForUpdate<Joystick>();RequireSingletonForUpdate<Joystick.Settings>();canvasScalerSystem = World.GetExistingSystem<CanvasScalerSystem>();}protected override void OnUpdate(){var joystick = GetSingleton<Joystick>();var settings = GetSingleton<Joystick.Settings>();var entity = joystick.Entity;var stickRectTransform = GetComponent<RectTransform>(entity);var highlight = joystick.Highlight;var higtlightRectTransform = GetComponent<RectTransform>(highlight);var knob = joystick.Knob;var knobRectTransform = GetComponent<RectTransform>(knob);if (this.BeginDrag(entity)) {higtlightRectTransform.Hidden = false;OnBeginDrag(joystick);}if (this.EndDrag(entity)) {higtlightRectTransform.Hidden = true;knobRectTransform.AnchoredPosition = float2.zero;joystick.Direction = float2.zero;joystick.Distance = 0;OnEndDrag(joystick);}if (this.Drag(entity, out DragEventData dragEventData)) {// Debug.Log("drag position:" + dragEventData.Position.ToString() + " pressPosition:" + dragEventData.PressPosition.ToString());var pressPosition = dragEventData.PressPosition;var position = dragEventData.Position;// 减去的是joystick的中心位置,所以要根据它的pivot来计算,如果是(0,0)的话,就要加上它宽高的一半var dstPos = position - (stickRectTransform.AnchoredPosition + stickRectTransform.SizeDelta * (-(stickRectTransform.Pivot - 0.5f)));// Debug.Log("距离:" + math.length(dstPos));var direction = math.normalize(dstPos);float distance = 0;float radius = canvasScalerSystem.WithScale(settings.Radius); // 这个半径要根据分辨率来,不然分辨率小了,可拖动距离就会变大if (math.length(dstPos) <= radius) {knobRectTransform.AnchoredPosition = dstPos;distance = math.length(dstPos);} else {var maxPos = direction * radius;knobRectTransform.AnchoredPosition = maxPos;distance = math.length(maxPos);}joystick.Direction = direction;joystick.Distance = distance;OnDrag(joystick);}SetComponent<RectTransform>(highlight, higtlightRectTransform);SetComponent<RectTransform>(knob, knobRectTransform);SetSingleton<Joystick>(joystick);}protected abstract void OnBeginDrag(in Joystick joystick);protected abstract void OnDrag(in Joystick joystick);protected abstract void OnEndDrag(in Joystick joystick);}
}

主要功能就是上面那些,代码不多,还有一个Authoring脚本,用来挂在场景中的遥感GameObject上,并赋值好所需要的数据。

using UnityEngine;
using Unity.Entities;
// using Joystick;namespace Authoring {[DisallowMultipleComponent]public class JoystickAuthoring : MonoBehaviour, IConvertGameObjectToEntity{public float radius;public GameObject Joy;public GameObject Knob;public GameObject Highlight;public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem){var joy = conversionSystem.GetPrimaryEntity(Joy);var knob = conversionSystem.GetPrimaryEntity(Knob);var highlight = conversionSystem.GetPrimaryEntity(Highlight);dstManager.AddComponentData<Joystick.Joystick>(entity, new Joystick.Joystick(joy, knob, highlight));dstManager.AddComponentData<Joystick.Joystick.Settings>(entity, new Joystick.Joystick.Settings(radius));}}
}

这是Unity编辑器里的节点设置。场景会在打包后,转成纯ECS的Entity和ComponentData的,在编辑器里运行无法看到效果,必须打包后才能正确执行DOTSruntime代码。
在这里插入图片描述
具体用法的示例代码:

using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using wangtal.Joystick;
using wangtal.EventSystem;namespace Tiny3D {[UpdateInGroup(typeof(InputSystemGroup))][UpdateAfter(typeof(EventSystem))]public class HeroJoystickSystem : JoystickSystem{protected override void OnBeginDrag(in Joystick.Joystick joystick){// 这里可以设置遥感到点击的位置,这样就不会一点击,角色就移动了,而是在拖动后才移动}protected override void OnDrag(in Joystick.Joystick joystick){var direction = joystick.Direction;// Unity.Tiny.Debug.Log("onDrag direction:" + direction);Entities.WithAll<Player>().ForEach((ref Moveable moveable) =>{if (math.all(direction == float2.zero)) {return;}moveable.moveDirection = new float3(direction.x, 0, direction.y);}).Run();}protected override void OnEndDrag(in Joystick.Joystick joystick){// Unity.Tiny.Debug.Log("endDrag direction:" + joystick.Direction);Entities.WithAll<Player>().ForEach((ref Moveable moveable) =>{moveable.moveDirection = float3.zero;}).Run();}}
}

打包WASM后到浏览器上的运行效果图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/22060.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何从一个仪表盘管理多个WordPress网站?

您是否正在寻找一种管理多个WordPress网站的简单方法&#xff1f; 监控多个网站并使其保持更新可能非常耗时。 幸运的是&#xff0c;有几种 WordPress 管理工具可以让您从单个仪表板管理多个 WordPress 网站变得非常容易。这将帮助您节省大量时间&#xff0c;同时使所有 Word…

Android复杂UI的性能优化实践 - PTQBookPageView 性能优化记录

作者&#xff1a;彭泰强 1 评价指标&优化成果 要做性能优化&#xff0c;首先得知道性能怎么度量、怎么表示。因为性能是一个很抽象的词&#xff0c;我们必须把它量化、可视化。那么&#xff0c;因为是UI组件优化&#xff0c;我首先选用了GPU呈现模式分析这一工具。 在手机…

如何应对ChatGPT这一波AI浪潮

最近我在写一系列文章&#xff0c;其中包括《ChatGPT 实战系列》和《WPS Office AI实战系列》。想通过这些文章提供实践指导&#xff0c;既自己动手实践了&#xff0c;也能与大家分享我的实践结果&#xff0c;这是一个学习的过程。在实践过程中&#xff0c;我发现有些实用的方面…

7.kafka+ELK连接

文章目录 kafkaELK连接部署Kafkakafka操作命令kafka架构深入FilebeatKafkaELK连接 kafkaELK连接 部署Kafka ###关闭防火墙systemctl stop firewalld systemctl disable firewalldsetenforce 0vim /etc/selinux/configSELINUXdisabled###下载安装包官方下载地址&#xff1a;ht…

【数据结构】初识

&#x1f341; 博客主页:江池俊的博客_CSDN博客-C语言——探索高效编程的基石领域博主 &#x1f341; 专栏&#xff1a;https://blog.csdn.net/2201_75743654/category_12348274.html &#x1f341; 如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏&#x1f…

【Linux】进程优先级

Linux 进程优先级 为什么要有优先级的划分&#xff1f;Linux 环境设置优先级的具体做法并发运行环境变量如何通过代码获取环境变量 环境变量的来源 为什么要有优先级的划分&#xff1f; 优先级的规定就是为了确定某种资源获取的先后顺序。 本质原因是因为CPU资源是有限的。进程…

LIS检验信息系统

LIS检验信息系统是以病人为中心、以业务处理为基础、以提高检验科室管理水平和工作效率为目标&#xff0c;将医学检验、科室管理和财务统计等工作进行整合&#xff0c;全面改善检验科室的工作现状。 LIS把检验、检疫、放免、细菌微生物及科研使用的各类分析仪器&#xff0c;通…

uniapp实现聊天消息触,vue3和vue2实现聊天消息触底 scrollTop ,scrollHeight Pc端H5端都适用

uniapp触底SDN链接如下(本人的另一篇博客) uniapp聊天时时触底链接 Pc端 模拟手机端H5 vue3写法 <template><div><!-- 聊天窗体 --><div class"test" id"gundong"><div class"text" v-for"p in chat"&…

SQL Server数据库 -- 表的高级查询

文章目录 一、子查询 嵌套子查询相关子查询二、查询运算 并运算union交运算intersect差运算except三、函数的使用 if语句while语句case语句四、总结 前言 高级子查询是对查询更灵活的运用&#xff0c;学会了高级查询将对数据库使用有很大的帮助。 一、子查询 1、子查询简介 在…

比亚迪海外市场势起

监制 | 何玺 排版 | 叶媛 海外市场正成为比亚迪新的增长点。 据媒体报道&#xff0c;从去年下半年至今&#xff0c;比亚迪已经在至少四个国家的纯电车型市场占据“销冠”位置。对于国内用户群体来说&#xff0c;比亚迪销量“霸屏”早已不是新闻&#xff0c;但在海外也保持这个…

易基因“多区域DNA甲基化检测探针设计及其检测方法”获专利授权!

大家好&#xff0c;这里是专注表观组学十余年领跑多组学科研服务的易基因。 DNA甲基化是表观遗传学研究中&#xff0c;修饰最为稳定&#xff0c;含量最为丰富&#xff0c;对基因调控最为活跃、途径最为广泛的一种修饰。不同基因区域或位点的修饰与胚胎发育、疾病发生和发展密切…

数据库--->MySQL(2)【事务、SQL优化】

文章目录 事务什么是事务&#xff1f;隔离性中的不同隔离级别事务实现的原理隔离级别的实现原理&#xff08;MVCC&#xff09;MySQL中的锁机制 SQL优化 事务 什么是事务&#xff1f; 事务就是逻辑上的一组操作&#xff0c;在同一个事务中&#xff0c;如果有多条sql语句执行&am…