SystemAPI.GetSingleton causing crash in build Windows / Android

As title says using SystemAPI.GetSingleton causing crash in build. Full code bellow. Baker mono used as separate gameobject inside subscene. Commenting var animationSettings = SystemAPI.GetSingleton<AnimationSettings>(); line fixes issue. Also in editor in edit / play mode all works fine.

System code

sing NSprites;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;

#pragma warning disable CS0282 // I guess because of DOTS's codegen
// https://discussions.unity.com/t/875104 page-2#post-8512268

[BurstCompile]
public partial struct MovableAnimationControllSystem : ISystem
{
    [BurstCompile]
    private partial struct ChangeAnimation : IJobEntity
    {
        public int setToAnimationID;
        public double time;

        public void Execute(ref AnimationIndex animationIndex, ref AnimationTimer timer, ref FrameIndex frameIndex, in AnimationSetLink animationSetLink)
        {
            // find animation by animation ID
            ref var animSet = ref animationSetLink.value.Value;
            var setToAnimIndex = 0;
            for (int i = 1; i < animSet.Length; i++)
                if (animSet[i].ID == setToAnimationID)
                {
                    setToAnimIndex = i;
                    break;
                }

            if (animationIndex.value != setToAnimIndex)
            {
                animationIndex.value = setToAnimIndex;
                // here we want to set last frame and timer to 0 (equal to current time) to force animation system instantly switch
                // animation to 1st frame after we've modified it
                frameIndex.value = animSet[setToAnimIndex].FrameDurations.Length;
                timer.value = time;
            }
        }
    }
    private struct SystemData : IComponentData
    {
        public EntityQuery gotUnderWayQuery;
        public EntityQuery stopedQuery;
    }
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
        var systemData = new SystemData();
        var queryBuilder = new EntityQueryBuilder(Allocator.Temp)
            .WithNone<CullSpriteTag>()
            .WithAll<AnimationIndex>()
            .WithAll<AnimationTimer>()
            .WithAll<FrameIndex>()
            .WithAll<AnimationSetLink>()
            .WithAll<Destination>()
            .WithAll<MoveTimer>();
        var gotUnderWayQuery = state.GetEntityQuery(queryBuilder);
        gotUnderWayQuery.AddOrderVersionFilter();
        systemData.gotUnderWayQuery = gotUnderWayQuery;

        queryBuilder.Reset();
        _ = queryBuilder.WithNone<CullSpriteTag>()
            .WithAll<AnimationIndex>()
            .WithAll<AnimationTimer>()
            .WithAll<FrameIndex>()
            .WithAll<AnimationSetLink>()
            .WithAll<Destination>()
            .WithNone<MoveTimer>();
        var stopedQuery = state.GetEntityQuery(queryBuilder);
        stopedQuery.AddOrderVersionFilter();
        systemData.stopedQuery = stopedQuery;

        _ = state.EntityManager.AddComponentData(state.SystemHandle, systemData);

        queryBuilder.Dispose();
    }

    public void OnDestroy(ref SystemState state)
    {
    }
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var systemData = SystemAPI.GetComponent<SystemData>(state.SystemHandle);
        // next line causing crash in build
        var animationSettings = SystemAPI.GetSingleton<AnimationSettings>();
        var time = SystemAPI.Time.ElapsedTime;
    }
}

Component and baker code

using Unity.Entities;

namespace NSprites
{
    public struct AnimationSettings : IComponentData
    {
        public int IdleHash;
        public int WalkHash;
    }
}
using Unity.Entities;
using UnityEngine;

namespace NSprites
{
    public class AnimationSettingsAuthoring : MonoBehaviour
    {
        private class AnimationSettingsBaker : Baker<AnimationSettingsAuthoring>
        {
            public override void Bake(AnimationSettingsAuthoring authoring)
            {
                AddComponent(new AnimationSettings
                {
                    IdleHash = Animator.StringToHash("idle"),
                    WalkHash = Animator.StringToHash("walk")
                });
            }
        }
    }
}

Also generated code looks completely normal for me, can’t figure out what is problem here.

#pragma warning disable 0219
#line 1 "E:\UnityProjects\NSprites-Dev\Temp\GeneratedCode\Assembly-CSharp\MovableAnimationControllSystem__System_1455874136.g.cs"
using NSprites;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;

[global::System.Runtime.CompilerServices.CompilerGenerated]
public partial struct MovableAnimationControllSystem : Unity.Entities.ISystem, Unity.Entities.ISystemCompilerGenerated
{
    [Unity.Entities.DOTSCompilerPatchedMethod("OnUpdate_ref_Unity.Entities.SystemState")]
    void __OnUpdate_6E994214(ref SystemState state)
    {
            #line 84 "E:\UnityProjects\NSprites-Dev\Assets/Sources/Rome/Systems/MovableAnimationControllSystem.cs"
            state.EntityManager.CompleteDependencyBeforeRO<MovableAnimationControllSystem.SystemData>();
            #line hidden
            __MovableAnimationControllSystem_SystemData_RO_ComponentLookup.Update(ref state);
            #line hidden
            var systemData = __MovableAnimationControllSystem_SystemData_RO_ComponentLookup[state.SystemHandle];
        #line 85 "E:\UnityProjects\NSprites-Dev\Assets/Sources/Rome/Systems/MovableAnimationControllSystem.cs"
        var animationSettings = __query_920542869_0.GetSingleton<AnimationSettings>();
        #line 86 "E:\UnityProjects\NSprites-Dev\Assets/Sources/Rome/Systems/MovableAnimationControllSystem.cs"
        var time = state.WorldUnmanaged.Time.ElapsedTime;
    }

    Unity.Entities.EntityQuery __query_920542869_0;
    Unity.Entities.ComponentLookup<MovableAnimationControllSystem.SystemData> __MovableAnimationControllSystem_SystemData_RO_ComponentLookup;
    public void OnCreateForCompiler(ref SystemState state)
    {
        __query_920542869_0 = state.GetEntityQuery(new Unity.Entities.EntityQueryDesc{All = new Unity.Entities.ComponentType[]{Unity.Entities.ComponentType.ReadOnly<NSprites.AnimationSettings>()}, Any = new Unity.Entities.ComponentType[]{}, None = new Unity.Entities.ComponentType[]{}, Options = Unity.Entities.EntityQueryOptions.Default | Unity.Entities.EntityQueryOptions.IncludeSystems});
        __MovableAnimationControllSystem_SystemData_RO_ComponentLookup = state.GetComponentLookup<MovableAnimationControllSystem.SystemData>(true);
    }
}

Also using this API in other parts of project doesn’t cause any issues in build.

Resolve: the problem was in accessing singleton component which is not loaded yet by subscene loading system because system just runs before loading done. Be careful, because systems update always by default. So SystemAPI.TryGetSingleton with early out solves the problem. Also it can be solved by adding any require query / singleton for system to filter its update.

What crash dump shows you? If you‘ll put require for update for that singleton type it will solves your issue? I’m 100% sure the issue is not yet loaded singleton in build

Somehow

Yep, just a moment ago I was trying to use SystemAPI.TryGetSingleton + early out on fail and build works and system doesn’t perform logic, so as you mentioned singleton not loaded in build. What can be a reason? It works in editor, so baker works fine.

UPD: Was my fault with inverted if, so with SystemAPI.TryGetSingleton build works. Does it mean that system runs before subscene loaded?

Yes this can happen. You can work around it if you know how, but I’m not sure and can’t check right now cause I’m just using some code @tertle gave me to prevent systems running until subscenes are loaded :smile:.

1 Like

Yes it can, because subscene loading is async.
8693745--1173105--upload_2022-12-30_10-18-24.png

1 Like