docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Define and manage system data

    When defining how to structure your system level data, you should organize it as component level data, rather than as fields within the system type.

    Using public data on systems isn't best practice. This is because public data access in systems requires a direct reference or pointer to the system instantiation which has the following consequences:

    • It creates dependencies between systems, which conflicts with data oriented approaches
    • It can't guarantee thread or lifetime safety around accessing the system instance
    • It can't guarantee thread or lifetime safety around accessing the system’s data, even if the system still exists and is accessed in a thread-safe manner

    Store system data in components

    You should store publicly accessible data in systems in components rather than as fields in the system type. An example of this is in the World namespace’s Get and Create system APIs such as GetExistingSystem<T>. They return an opaque SystemHandle handle to the system rather than direct access to the system’s instance. This applies for both managed SystemBase and unmanaged ISystem systems.

    As an example, in a typically implemented object-oriented code, a type's data is part of the type's definition:

    /// Object-oriented code example
    public partial struct PlayerInputSystem : ISystem
    {
        public float AxisX;
        public float AxisY;
    
        public void OnCreate(ref SystemState state) { }
    
        public void OnUpdate(ref SystemState state)
        {
            AxisX = [... read controller input];
            AxisY = [... read controller input];
        }
    
        public void OnDestroy(ref SystemState state) { }
    }
    

    An alternate, data-oriented version of the PlayerInputSystem above might look something like this:

    public struct PlayerInputData : IComponentData
    {
        public float AxisX;
        public float AxisY;
    }
    
    public partial struct PlayerInputSystem : ISystem
    {
        public void OnCreate(ref SystemState state)
        {
            state.EntityManager.AddComponent<PlayerInputData>(state.SystemHandle);
        }
    
        public void OnUpdate(ref SystemState state)
        {
            SystemAPI.SetComponent(state.SystemHandle, new PlayerInputData {
                AxisX = [...read controller data],
                AxisY = [...read controller data]
            });
        }
    
        // Component data is automatically destroyed when the system is destroyed. 
        // If a Native Container existed in the component, however, OnDestroy could be used to
        // ensure memory is disposed.
        public void OnDestroy(ref SystemState state) { }  
    }
    

    This defines a data protocol for the system which is separate from the system functionality. These components can exist in either a singleton entity, or they can belong to a system-associated entity through EntityManager.GetComponentData<T>(SystemHandle) and similar methods. You should use the latter when you want the data lifetime to be tied to the system lifetime.

    When you use this technique, you can access the system's data in the same way as any other entity component data. A reference or pointer to the system instance is no longer necessary.

    Choosing system or singleton entity components

    Using the singleton APIs is similar to using system data in an entity component, but with the following differences:

    • Singletons aren't tied to the system's lifetime
    • Singletons can only exist per system type, not per system instance

    For more information, see the documentation on singleton components.

    Direct access APIs

    The Entities package contains several APIs you can use to directly access system instances, in exceptional circumstances, as follows:

    Method name ISystem SystemBase
    World.GetExistingSystemManaged<T> No Yes
    World.GetOrCreateSystemManaged<T> No Yes
    World.CreateSystemManaged<T> No Yes
    World.AddSystemManaged<T> No Yes
    WorldUnmanaged.GetUnsafeSystemRef<T> Yes No
    WorldUnmanaged.ResolveSystemStateRef<T> Yes Yes
    In This Article
    • Store system data in components
    • Choosing system or singleton entity components
    • Direct access APIs
    Back to top
    Copyright © 2024 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)