Are generic SystemBase supported?

Hello, new forum!

Are generic SystemBase supported? I’m attempting to create a netcode system in ECS and to avoid writing the same code over and over for commands and snapshots (not using Netcode for Entities) I want to use generic systems. I have gotten generic ISystems working but using the same assembly attribute doesn’t appear to work for SystemBase. The below code doesn’t work for me:

using MyNamespace;
using Unity.Burst;
using Unity.Burst.Intrinsics;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using UnityEngine;

[assembly: RegisterGenericSystemType(typeof(MyGenericSystem<MyComponent>))]
[assembly: RegisterGenericJobType(typeof(MyGenericJob<MyComponent>))]

namespace MyNamespace
{
    public interface IMyInterface
    {
        public int GetId();
    }
    
    public struct MyComponent : IComponentData, IMyInterface
    {
        public int Id;

        public int GetId() => Id;
    }
    
    public partial class MyGenericSystem<T> : SystemBase
        where T : unmanaged, IComponentData, IMyInterface
    {
        private EntityQuery _genericQuery;

        [ReadOnly] private ComponentTypeHandle<T> _typeHandle;
        
        protected override void OnCreate()
        {
            using var builder = new EntityQueryBuilder(Allocator.Temp);
            _genericQuery = builder.WithAll<T>().Build(EntityManager);

            _typeHandle = GetComponentTypeHandle<T>(true);
            
            EntityManager.AddComponentData(EntityManager.CreateEntity(), new MyComponent { Id = 1 });
            EntityManager.AddComponentData(EntityManager.CreateEntity(), new MyComponent { Id = 2 });
            EntityManager.AddComponentData(EntityManager.CreateEntity(), new MyComponent { Id = 3 });
        }

        protected override void OnUpdate()
        {
            Dependency = new MyGenericJob<T>
            {
                TypeHandle = _typeHandle
            }.ScheduleParallel(_genericQuery, Dependency);
        }
    }
    
    [BurstCompile]
    public struct MyGenericJob<T> : IJobChunk
        where T : unmanaged, IComponentData, IMyInterface
    {
        [ReadOnly] public ComponentTypeHandle<T> TypeHandle;
            
        public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
        {
            foreach (var component in chunk.GetNativeArray(ref TypeHandle))
            {
                Debug.Log($"Looping: {component.GetId()}");
            }
        }
    }
}

I get this error:

Unity.Entities.CodeGen.EntitiesILPostProcessors: (0,0): error error DC3002: MyNamespace.MyGenericSystem`1: [RegisterGenericJobType] requires an instance of a generic value type

Does anyone have an idea why this error was thrown? My guess is that source generation is generating a generic job that doesn’t have the concrete implementation registered but I’m not sure. Appreciate the help :slight_smile:

I didn’t know about this limitation but the error states requires an instance of a generic value type so I guess classes aren’t supported. Have you tried making the system abstract and inheriting from it for each concrete component type?

1 Like

Wow, that worked! Thanks for the advice. For reference, this is what worked:

public partial class MyConcreteSystem : MyGenericSystem<MyComponent> {}
    
public abstract partial class MyGenericSystem<T> : SystemBase
    where T : unmanaged, IComponentData, IMyInterface
{
    ...
}

I didn’t need the [assembly: attribute] definition either since this is now not a generic system.

1 Like