Dots 对象池

官方原文是说 I am not saying pooling as a general strategy when using game objects or other things that allocate GC memory is not useful. I am saying that pooling instantiated entities in Unity.Entities has no real merit because we solved the problem at the root by having pooling of chunks internally + very fast instantiation when done in batch.
There are no GC allocations if you take the recommended fast paths. Specifically if you only have shared components + struct IComponentData. Then instantiating entities will allocate zero GC memory.
As an example. A few years back in the Nordeus large battle field demo. We were spawning 10.000 arrows per frame. That was not doing any pooling at all...


class IComponentData does exist, if you actually use them, then yes there is GC memory allocations and that means it would be useful to do pooling. But the point here is, if you care about performance & GC memory pressure, then don't use class components in your game at all for this and many other reasons. They can be convenient in some cases but they are not performance by default....


Hence the recommendation when working with entities is that you use struct components + don't do pooling as a default approach. And measure specific cases where thats not enough.

但是某些特殊情况(比如大量实例粒子之类的)有对象池优化起来还是方便点,所以整了个,大多数情况还是不建议使用对象池

 

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;

namespace DOTS.Extensions
{
    [BurstCompile]
    public partial struct AddBulletEntity : IJobEntity
    {
        public EntityCommandBuffer.ParallelWriter ECB;
        public BufferLookup<PoolBuffer> PoolBufferLookAt;
        public ComponentLookup<PoolEntity> PoolEntityLookAt;

        public void Execute(Entity entity, in ToAfterTransform after) {
            var hasInit = PoolEntityLookAt.TryGetComponent(entity, out var tag);
            if (!hasInit) {
                Debug.LogError("是不是忘记初始化了1");
            }

            if (!PoolBufferLookAt.TryGetBuffer(tag.Tag, out var buffer)) {
                Debug.LogError("是不是忘记初始化了2");
            }

            buffer.Add(new PoolBuffer(entity));

            ECB.RemoveComponent<ToAfterTransform>(0, entity);
            ECB.SetEnabled(0, entity, false);
        }
    }

    public partial struct RemoveToPool : ISystem
    {
        private BufferLookup<PoolBuffer> _poolBufferLookAt;
        private ComponentLookup<PoolEntity> _poolEntityLookAt;

        [BurstCompile]
        public void OnCreate(ref SystemState state) {
            state.RequireForUpdate<ToAfterTransform>();
            _poolEntityLookAt = state.GetComponentLookup<PoolEntity>();
            _poolBufferLookAt = state.GetBufferLookup<PoolBuffer>();
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state) {
            _poolBufferLookAt.Update(ref state);
            _poolEntityLookAt.Update(ref state);
            using var ecb = new EntityCommandBuffer(Allocator.TempJob);
            var job = new AddBulletEntity
            {
                PoolBufferLookAt = _poolBufferLookAt,
                PoolEntityLookAt = _poolEntityLookAt,
                ECB = ecb.AsParallelWriter(),
            };
            state.Dependency = job.Schedule(state.Dependency);
            state.Dependency.Complete();
            ecb.Playback(state.EntityManager);
        }
    }
}
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;

namespace DOTS.Extensions
{
    public struct ToAfterTransform : IComponentData
    {
    }

    public struct PoolEntityTag : IComponentData
    {
    }

    public struct PoolEntity : IComponentData
    {
        public Entity Tag;
    }

    public struct PoolBuffer : IBufferElementData
    {
        public Entity Val;

        public PoolBuffer(Entity val) {
            Val = val;
        }
    }

    public static class EntityPool
    {
        public static void InitPool(this Entity entity, EntityCommandBuffer.ParallelWriter ecb) {
            var e = ecb.CreateEntity(0);
            ecb.AddComponent<PoolEntityTag>(0, e);
            ecb.AddBuffer<PoolBuffer>(0, e);
            ecb.AddComponent(0, entity, new PoolEntity
            {
                Tag = e
            });
        }

        /// <summary>
        /// 创建对象
        /// </summary>
        /// <param name="entity">对象</param>
        /// <param name="ecb">ECB</param>
        /// <param name="poolLookAt"></param>
        /// <param name="bufferLookAt">对象池</param>
        /// <param name="updateTransform">是否自定义LocalTransform</param>
        /// <param name="transform">自定义的LocalTransform</param>
        /// <returns></returns>
        public static Entity Spawn(this Entity entity, EntityCommandBuffer.ParallelWriter ecb,
            ComponentLookup<PoolEntity> poolLookAt, BufferLookup<PoolBuffer> bufferLookAt, bool updateTransform = false,
            LocalTransform transform = default) {
            Entity e;
            var hasInit = poolLookAt.TryGetComponent(entity, out var tag);
            if (!hasInit) {
                Debug.LogError("是不是忘记初始化了");
            }

            if (hasInit && bufferLookAt.TryGetBuffer(tag.Tag, out var buffer) &&
                buffer.Length > 0) {
                var lastIndex = buffer.Length - 1;
                e = buffer[lastIndex].Val;
                buffer.RemoveAt(lastIndex);

                ecb.SetEnabled(0, e, true);
            }
            else {
                e = ecb.Instantiate(0, entity);
            }

            if (!updateTransform) {
                transform = new LocalTransform
                {
                    Position = float3.zero,
                    Scale = 1,
                    Rotation = quaternion.identity
                };
            }

            ecb.SetComponent(0, e, transform);
            return e;
        }

        private static readonly float3 Float3Out = new(100000, 100000, 100000);

        /// <summary>
        /// 回池
        /// </summary>
        /// <param name="entity">回池对象</param>
        /// <param name="ecb">ECB</param>
        /// <param name="poolLookAt">池子对象</param>
        /// <param name="bufferLookAt">对象池</param>
        public static void Despawn(this Entity entity, EntityCommandBuffer.ParallelWriter ecb) {
            ecb.SetComponent(0, entity, new LocalTransform
            {
                Position = Float3Out,
                Scale = 100
            });
            ecb.AddComponent<ToAfterTransform>(0, entity);
        }
    }
}

用起来也很简单 先将需要对象池控制的Entity入池 

Entity.InitPool(ecbCreate.AsParallelWriter());

然后使用Entity.Spawn和Entity.Despawn创建销毁(创建用原始对象,销毁用需要被销毁的对象)

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
weixin102旅游社交微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
Unity DOTS(DOTS: Data-Oriented Technology Stack)是Unity的一种数据导向技术堆栈,它旨在提高游戏性能和可扩展性。它基于实体组件系统(Entity-Component-System,ECS)的概念,其中游戏对象被拆分为实体(Entity)和组件(Component),并通过系统(System)进行处理。 在Unity DOTS中,可以使用实体组件系统来管理和处理游戏对象。通过将游戏对象转换为实体和组件的形式,可以实现高效的数据处理和并行计算。例如,在创建实体时,可以使用GameObjectConversionUtility.ConvertGameObjectHierarchy函数将GameObject转换为Entity,并使用IConvertGameObjectToEntity接口进行自定义转换。然后,可以使用系统(System)对实体和组件进行处理,例如旋转方块事件。 Unity DOTS的优势包括更高的性能,更好的可扩展性和更方便的并行计算。通过采用数据导向的设计,可以减少内存访问和数据处理的开销,从而提高游戏的帧率和响应性。 总而言之,Unity DOTS是一种数据导向的技术堆栈,通过实体组件系统和并行计算来提高游戏性能和可扩展性。它可以通过转换游戏对象为实体和组件的形式,并使用系统进行处理来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [UnityDots技术入门](https://blog.csdn.net/m0_37920739/article/details/108181541)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Unity DOTS简明教程](https://blog.csdn.net/mango9126/article/details/105219215)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值