Unity DOTS如何优雅地实现ECS框架下的定时器Timer系统(无对象池,零GC)

无对象池,零GC的ECS定时器Timer系统
摘要由CSDN通过智能技术生成

实现定时器并不复杂,就是写个类存放回调,再写个类来统一管理这些回调类。但是ECS写代码的方式变了,所以还是有些区别的。

实现过程中需要注意的几点:
1、由于IComponentData不能存放managed类型的数据,所以无法用常规的ECS方式来存放定时器数据,只能用一个NativeHashMap作为SystemBase里的一个字段来存数据了。

2、常规来说,NativeList肯定比NativeHashMap的内存占用小的,但是用过后发现List要在遍历过程中删除元素实在是不好看,就只能用Map了。不过影响不大。

3、试过回调的保存用c#官方的delegate,但是打包WASM到浏览器上运行,报了个错“function signature mismatch”。没有深入处理,直接放弃了该用法。也试过用Unity.Burst自带的FunctionPointer函数指针,但是有个限制,函数不能作为类的实例方法,只能是static的静态方法,而static方法遍历IComponentData很不方便,也只能放弃。

4、目前的实现方法有个小小的瑕疵,但不影响功能。就是每个SystemBase里只能实现一个定时器回调,如果需要实现一个每2秒执行一次的回调,和一个每1秒执行一次的回调,就不行,只能分开在两个SystemBase里。由于SystemBase是class来的,太多的话,创建和销毁会涉及到GC,对性能有一点影响。

不过新版的Entities有了ISystem,是struct类型的,可以随便创建删除,且可以完全BurstCompile的。ProjectTiny无法更新到新版,只能先这样用着。用法跟MonoBehavior实现的差不多,可以添加任意间隔,重复执行的回调,也可以添加指定执行几次或间隔执行一次的回调。看代码:

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using System.Runtime.CompilerServices;
using System;

namespace wangtal.ClockSystem {
   
    #pragma warning disable 660, 661
    [BurstCompile]
    public readonly struct ClockHandle : IEquatable<ClockHandle>{
   
        private static uint _uid = 1;
        internal static uint uid => _uid++;
        public static ClockHandle Null = new ClockHandle(0);

        private readonly uint Id;

        internal ClockHandle(uint id) {
   
            Id = id;
        }

        bool IEquatable<ClockHandle>.Equals(Tiny3D.ClockHandle other) {
   
            return this == other;
        }

        public static bool operator ==(ClockHandle left, ClockHandle right) {
   
            return left.Id == right.Id;
        }

        public static bool operator !=(ClockHandle left, ClockHandle right)
        {
   
            return left.Id != right.Id;
        }

        public override string ToString() {
   
            return $"id:{
     Id}";
        }

        public override int GetHashCode()
        {
   
            return Id.GetHashCode();
        }
    }
    #pragma warning restore 660, 661

    public interface IClockExecutor {
   
        void Execute();
    }

    // public delegate void Callback(/*EntityManager entityManager*/);

    [BurstCompile]
    internal struct Clock {
   
        internal readonly ClockHandle Handle;

        // function signature mismatch
        // internal readonly /*FunctionPointer<Callback>*/Callback FunctionPointer;
        internal readonly IClockExecutor Executor;

        // 负数代表无限循环,0代表结束循环了,大于0代表重复执行次数
        internal int Repeat;

        // 毫秒数
        internal double StartTime
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值