#Why does this baking system not work the way I expect it?

1 messages · Page 1 of 1 (latest)

kind palm
#

I was having issues with using Shader.PropertyToID in my bursted code, and I couldn't put it in a readonly static int because unity complains if I call it from a static constructor. Instead of just getting it in OnCreate I ended up creating this:

    public struct ShaderProperties : IComponentData
    {
        public int GoalAlpha;
        public int WireColor;
    }

    [WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]
    public partial struct ShaderPropertiesBakingSystem : ISystem
    {
        public void OnUpdate(ref SystemState state)
        {
            if (SystemAPI.HasSingleton<ShaderProperties>()) return;
            state.EntityManager.CreateSingleton(
                new ShaderProperties
                {
                    GoalAlpha = Shader.PropertyToID("_GoalAlpha"),
                    WireColor = Shader.PropertyToID("_WireColor"),
                }
            );
        }
    }

Which worked fine until I made a build. After I made a build none of the systems with a dependency on the component manage to find it for some reason.
If I remove SystemAPI.HasSingleton then unity complains that it can't be created because there already is an entity with that component type.

I feel like I've misunderstood something about how bakers work since this isn't working. I assume I can just make a regular baker that spawns it based on a monobehaviour, it just felt a bit excessive to make an authoring component that'll just be empty.

sweet bear
#

Ooops deleted wrong message let me start again

#

PropertyToID can't be baked, it is application instance specific

#

The first call of the app assigns id = 1, second call id = 2, etc

#

Internally it just caches this string, int in a dictionary or something like that

#

For example
GoalAlpha = Shader.PropertyToID("_GoalAlpha") = 1
WireColor = Shader.PropertyToID("_WireColor") = 2
Shader.PropertyToID("_SomeOtherProperty") = 3

#

but in a build your baker isn't running, some other shader property is going to get id = 1 as it will be called in a different order

#

Each name of shader property (for example, _MainTex or _Color) is assigned an unique integer number in Unity, that stays the same for the whole game. The numbers will not be the same between different runs of the game or between machines, so do not store them or send them over network.

open cairn
#

Alternatives:
-just create these values @ runtime in OnCreate, either in a singleton as you are doing or as simple fields in each system that uses these named properties as necessary
-use a SharedStatic populated in a RuntimeInitializeOnLoadMethod

#

Oh yeah, trying to bake these would totally break an existing serialized subscene on a reloaded editor, eh

sweet bear
#

(Ran into this exact same mistake a couple of months ago)

kind palm
#

tertle to the rescue as always

kind palm
#

Though even then it's the 5th result for me, rest being ECS forum posts from before 2021

#

Though I'm still confused why the singleton doesn't exist at all in the world, rather than existing with the wrong values, or erroring

open cairn
# kind palm Though I'm still confused why the singleton doesn't exist at all in the world, r...

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/baking-baking-systems-overview.html

Baking systems can alter the world in any way, including creating new entities. However, any entities you create in a baking system won't end up in a baked entity scene. You can create an entity in a baking system to transfer data between baking systems, but if you want the entity to end up in the baked entity scene, you must create it in a baker. When you create an entity in a baker, CreateAdditionalEntity configures the entity to properly work with baking and live baking.

lusty flicker
#

Just use a static table for shader IDs. Simple, effective, and I got it from Unity themselves who also uses a rather extensive static class full of this.

sweet bear
#

slightly annoying though as you can't access these from burst

#
        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            if (this.query.IsEmpty)
            {
                return;
            }

            var shaderIds = new NativeHashMap<FixedString32Bytes, int>(16, state.WorldUpdateAllocator);

            new CreateShaderIDsJob
                {
                    VisualEffectPresentationInitializeHandle = SystemAPI.GetBufferTypeHandle<VisualEffectPresentationInitialize>(true),
                    VisualEffectPresentationUpdateHandle = SystemAPI.GetBufferTypeHandle<VisualEffectPresentationUpdate>(true),
                    ShaderProperties = shaderIds,
                }
                .Run(this.query);

            // Break out of burst to write Ids
            this.getShaderProperties.Invoke(ref shaderIds);

            // ...```

```cs
        [AOT.MonoPInvokeCallback(typeof(GetShaderPropertiesDelegate))]
        public static void GetShaderProperties(ref NativeHashMap<FixedString32Bytes, int> shaderIds)
        {
            using var s = shaderIds.GetEnumerator();
            while (s.MoveNext())
            {
                s.Current.Value = Shader.PropertyToID(s.Current.Key.ToString());
            }
        }```

I actually had to write a break to grab them
#

i don't actually know what shader properties want to be used, completely data driven

#

(Where Name is the shader property)