#How do i make this less repetitive and scaleable?

1 messages · Page 1 of 1 (latest)

celest spoke
#

I am trying to figure out a way to setup my data so I don't need to write repetitive code for each **need **that an agent requires.

For each new **need **, means I have to write another loop with largely the same code except for applying a different tag component. The repeitiveness of the code suggests to me there is probably a better way to set this up.

        EntityCommandBuffer _ecb;
        public void OnUpdate(ref SystemState ss)
        {
            _ecb = new(Unity.Collections.Allocator.Temp);
            float _rate = 0.01f;
            int _threshold = 20;

            var delta = SystemAPI.Time.DeltaTime * _rate;

            foreach (var (h, e) in SystemAPI.Query<RefRW<Hydration>>().WithEntityAccess()) { 

                var value = h.ValueRW.Value;
                value -= delta;
                value = math.clamp(value, 0f, 100f);
                h.ValueRW.Value = value;

                if (h.ValueRO.Value <= _threshold)
                    _ecb.AddComponent<ThirstyTag>(e);
                else
                    _ecb.RemoveComponent<ThirstyTag>(e);
            }
            foreach (var (h, e) in SystemAPI.Query<RefRW<Hunger>>().WithEntityAccess()) 
            { 
                var value = h.ValueRW.Value;
                value -= delta;
                value = math.clamp(value, 0f, 100f);
                h.ValueRW.Value = value;

                if (h.ValueRO.Value <= _threshold)
                    _ecb.AddComponent<HungryTag>(e);
                else
                    _ecb.RemoveComponent<HungryTag>(e);
            }

            _ecb.Playback(ss.EntityManager);
            _ecb.Dispose();
        }
slim aurora
#

You can make a shared interface (e.g. IDecayable). This IDecayable will have a {get; set;} field which represents your value. Then make a method that accepts generic TDecayable, TTag types. You restrict TDecayable to be unmanaged and IDecayable. Copy your repetitive code and additionally pass the SystemState, for SystemAPI to work. Done

raw oyster
#

if you're curious how i'd tackle something like this, here's a full implementation for my stat package (threw it together untested so dont try it, but i might actually add something like this to it)

#
    public partial struct IntrinsicModifySystem : ISystem
    {
        private EntityQuery query;
        private IntrinsicWriter.TypeHandle intrinsicWriterHandle;

        public void OnCreate(ref SystemState state)
        {
            this.query = IntrinsicWriter.CreateQueryBuilder().WithAll<IntrinsicModifier>.Build(ref state);
            this.intrinsicWriterHandle.Create(ref state);
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            this.intrinsicWriterHandle.Update(ref state);

            state.Dependency = new ModifyJob
            {
                Config = SystemAPI.GetSingletonBuffer<IntrinsicModifyConfig>(true).AsMap(),
                IntrinsicModifierHandle = SystemAPI.GetBufferTypeHandle<IntrinsicModifier>(),
                IntrinsicWriterHandle = this.intrinsicWriterHandle,
            }.ScheduleParallel(this.query, state.Dependency);
        }
    }```
#
    [BurstCompile]
    public struct ModifyJob : IJobChunk
    {
        [ReadOnly]
        public DynamicHashMap<IntrinsicKey, IntrinsicModifyConfig.Data> Config;

        public BufferTypeHandle<IntrinsicModifier> IntrinsicModifierHandle;

        public IntrinsicWriter.TypeHandle IntrinsicWriterHandle;

        public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
        {
            var intrinsicWriters = this.IntrinsicWriterHandle.Resolve(chunk);
            var intrinsicModifierAccessor = chunk.GetBufferAccessor(ref this.IntrinsicModifierHandle);

            for (var i = 0; i < chunk.Count; i++)
            {
                var intrinsicModifier = intrinsicModifierAccessor[i];
                if (intrinsicModifier.Length == 0)
                {
                    continue;
                }

                var intrinsicWriter = intrinsicWriters[i];

                for (var index = intrinsicModifier.Length - 1; index >= 0; index--)
                {
                    var modifier = intrinsicModifier[index];

                    if (!this.Config.TryGetValue(modifier.Intrinsic, out var config))
                    {
                        Debug.LogError($"Intrinsic {modifier.Intrinsic} modifying with associated config");
                        continue;
                    }

                    var result = intrinsicWriter.Add(modifier.Intrinsic, config.Rate);
                    if (config.RemoveDegenWhenZero && result <= 0)
                    {
                        intrinsicModifier.RemoveAtSwapBack(index);
                    }
                }
            }
        }
    }```
#
    [InternalBufferCapacity(0)]
    public struct IntrinsicModifier : IBufferElementData
    {
        public IntrinsicKey Intrinsic;
    }

    public struct IntrinsicModifyConfig : IDynamicHashMap<IntrinsicKey, IntrinsicModifyConfig.Data>
    {
        byte IDynamicHashMap<IntrinsicKey, Data>.Value { get; }

        public struct Data
        {
            public bool RemoveDegenWhenZero;
            public int Rate;
        }
    }```