Can't find "Use baked scripts" (managed code stripping)

Hi, I’m experiencing a few problems when trying to play on a windows build. Basically I have the following setup:

  • Using Rooms.

  • When all players are connected, I set a few [Sync] variables to share the saved information of all connected players (only once). In editor, this is working fine, but in the build they aren’t in sync.

  • I have tried to delete the baked folder and bake the scripts again, but the error persists.

Setting the Coherence log to debug and info we get the following:

Player.log

[...]

12:12:43.046 (coherence) CoherenceSync: Couldn't load baked script for '[REMOVED](Clone)' (type 'Coherence.Generated.CoherenceSync[REMOVED]_4299c6ae792d7e746b5c7f48af6d2ea5, Assembly-CSharp'). Falling back to reflection. 
UnityEngine.Logger:Log(LogType, Object, Object)
UnityEngine.Debug:LogWarning(Object, Object)
Coherence.Log.Targets.UnityConsoleTarget:Log(LogLevel, String, ValueTuple`2[], Logger)
Coherence.Log.Logger:BuildAndPrintLog(LogLevel, String, ValueTuple`2[])
Coherence.Log.Logger:LogImpl(LogLevel, String, ValueTuple`2[])
Coherence.Log.UnityLogger:Warning(String, ValueTuple`2[])
Coherence.Toolkit.CoherenceSync:UpdateBakedScriptReference()
Coherence.Toolkit.CoherenceSync:Awake()
UnityEngine.Object:Instantiate(Object, Vector3, Quaternion)
Coherence.Toolkit.DefaultInstantiator:Instantiate(SpawnInfo)
Coherence.Toolkit.EntitiesManager:InstantiateCoherenceSync(ICoherenceSync, SpawnInfo, NetworkEntityState)
Coherence.Toolkit.EntitiesManager:InstantiateNetworkedEntity(ICoherenceSync, SpawnInfo, Entity, EntityUpdate)
Coherence.Toolkit.<>c__DisplayClass50_0:<CreateNetworkedEntity>b__0(ICoherenceSync)
Coherence.Toolkit.EntitiesManager:CreateNetworkedEntity(Entity, EntityUpdate, Boolean&)
Coherence.Toolkit.EntitiesManager:<SetClient>b__45_0(Entity, EntityUpdate)
Coherence.Core.ClientCore:HandleReceivedCreate(EntityUpdate&)
Coherence.Core.ClientCore:OnEntityUpdates(List`1)
Coherence.Core.InConnection:FlushChangeBuffer()
Coherence.Core.InConnection:ProcessIncomingPacket(IInOctetStream, AbsoluteSimulationFrame)
Coherence.Core.ClientCore:ReceiveAndProcessPackets()
Coherence.Toolkit.CoherenceBridge:ReceiveFromNetworkAndUpdateTime()
Coherence.Toolkit.PlayerLoop.CoherenceReceiver:ReceiveFromNetwork()

12:12:43.046 (coherence) CoherenceSyncUpdater: We can only synchronize 1 variables of type Byte[] on the same game object when using reflection. This binding will not be synced: [REMOVED]. Try switching to 'Use baked scripts' in the inspector. 
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:LogWarning(Object)
Coherence.Log.Targets.UnityConsoleTarget:Log(LogLevel, String, ValueTuple`2[], Logger)
Coherence.Log.Logger:BuildAndPrintLog(LogLevel, String, ValueTuple`2[])
Coherence.Log.Logger:LogImpl(LogLevel, String, ValueTuple`2[])
Coherence.Log.UnityLogger:Warning(String, ValueTuple`2[])
Coherence.Toolkit.CoherenceSyncUpdater:MapGenericPool()
Coherence.Toolkit.CoherenceSync:ConnectToBridge()
Coherence.Toolkit.CoherenceSync:OnEnable()
UnityEngine.Object:Instantiate(Object, Vector3, Quaternion)
Coherence.Toolkit.DefaultInstantiator:Instantiate(SpawnInfo)
Coherence.Toolkit.EntitiesManager:InstantiateCoherenceSync(ICoherenceSync, SpawnInfo, NetworkEntityState)
Coherence.Toolkit.EntitiesManager:InstantiateNetworkedEntity(ICoherenceSync, SpawnInfo, Entity, EntityUpdate)
Coherence.Toolkit.<>c__DisplayClass50_0:<CreateNetworkedEntity>b__0(ICoherenceSync)
Coherence.Toolkit.EntitiesManager:CreateNetworkedEntity(Entity, EntityUpdate, Boolean&)
Coherence.Toolkit.EntitiesManager:<SetClient>b__45_0(Entity, EntityUpdate)
Coherence.Core.ClientCore:HandleReceivedCreate(EntityUpdate&)
Coherence.Core.ClientCore:OnEntityUpdates(List`1)
Coherence.Core.InConnection:FlushChangeBuffer()
Coherence.Core.InConnection:ProcessIncomingPacket(IInOctetStream, AbsoluteSimulationFrame)
Coherence.Core.ClientCore:ReceiveAndProcessPackets()
Coherence.Toolkit.CoherenceBridge:ReceiveFromNetworkAndUpdateTime()
Coherence.Toolkit.PlayerLoop.CoherenceReceiver:ReceiveFromNetwork()

[...]

This is the coherence sync component:

I’m not sure why this is happening since at first glance, everything looks ok.

Appreciate any help to understand why the baked scripts can’t be loaded and how to switch to ‘Use baked scripts’ in the inspector.

Let me know if you need any extra details.

Thanks. :slightly_smiling_face:

Hey, welcome to the forums!

Hmm, it’s not clear from here what it could be. Can you show us the Config panel, or provide a list of the synced variables and methods?

And in the CoherenceSyncConfigRegistry (the SO that’s in the coherence folder), do all network entities have the green checkmark?

Hi Ciro.

Can you show us the Config panel, or provide a list of the synced variables and methods?

Sure, I will condense all variables into one class. All the components are on the root prefab object, at the same level as the CoherenceSync component. (Child objects are only used for graphics)

CoherenceSync Objects

public class Example : MonoBehaviour
{
    [NonSerialized, Sync] public string Example1;
    [NonSerialized, Sync] public byte Example2 = byte.MaxValue;
    [NonSerialized, Sync] public byte Example3;
    [NonSerialized, Sync] public byte[] ExampleIndexes1;
    [NonSerialized, Sync] public byte[] ExampleIndexes2;  
    [NonSerialized, Sync] public byte[] ExampleIndexes3;  
    [NonSerialized, Sync] public byte[] ExampleIndexes4;
    [NonSerialized, Sync] public byte[] ExampleIndexes5;
    [NonSerialized, Sync] public byte[] ExampleIndexes6;
    [NonSerialized, Sync] public byte[] ExampleIndexes7;
    [NonSerialized, Sync] public byte[] ExampleIndexes8;
    [NonSerialized, Sync] public byte[] ExampleIndexes9;
    [NonSerialized, Sync] public byte[] ExampleIndexes10;
    [NonSerialized, Sync] public byte[] ExampleIndexes11;
    [NonSerialized, Sync] public byte[] ExampleIndexes12;
    [NonSerialized, Sync] public byte[] ExampleIndexes13;
    [NonSerialized, Sync] public byte[] ExampleIndexes14;
    [NonSerialized, Sync] public byte[] ExampleIndexes15;
    [NonSerialized, Sync] public byte[] ExampleIndexes16;
    [NonSerialized, Sync] public byte[] ExampleIndexes17;
    [NonSerialized, Sync] public byte[] ExampleIndexes18;

    // Runtime Variables
    [NonSerialized, Sync] public bool Example4;
    [NonSerialized, Sync] public bool Example5;
    [NonSerialized, Sync] public bool Example6;

    //Component A
    [Command]
    public void ExampleMethod01() { }
    
    //Component B
    [Command]
    public void ExampleMethod02(byte arg) { }
    
    [Command]
    public void ExampleMethod03(byte arg, byte arg2, Vector3 arg3) { }
    
    [Command]
    public void ExampleMethod04(byte arg, byte arg2, Vector3 arg3, Vector3 arg4) { }
    
    [Command]
    public void ExampleMethod05(byte arg, byte arg2) { }

    //Component C
    [Command]
    public void ExampleMethod06() { }
    
    [Command]
    public void ExampleMethod07(float arg) { }

    //Component D
    [Command]
    public void ExampleMethod08(CoherenceSync arg, float arg2) { }

    //Component E
    [Command]
    public void ExampleMethod09(ushort arg, float arg2) { }

    //Component F
    [Command]
    public void ExampleMethod10(byte[] arg, byte arg2) { }
    
    [Command]
    public void ExampleMethod11() { }
    
    [Command]
    public void ExampleMethod12(Vector3 arg) { }
    
    [Command]
    public void ExampleMethod13(byte arg) { }
}

the CoherenceSyncConfigRegistry (the SO that’s in the coherence folder), do all network entities have the green checkmark?

Yes, all entries have a green checkmark.

I’m not sure if this is relevant, but if you click on “Update bindings” the console prints the following error:

ArgumentException: An item with the same key has already been added. Key: (Coherence.Toolkit.Bindings.Descriptor, Head (Entity))
System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <605bf8b31fcb444b85176da963870aa7>:0)
System.Collections.Generic.Dictionary`2[TKey,TValue].Add (TKey key, TValue value) (at <605bf8b31fcb444b85176da963870aa7>:0)
Coherence.Toolkit.CoherenceSync.GetBindingForDescriptor (Coherence.Toolkit.Bindings.Descriptor descriptor, UnityEngine.Component component) (at ./Library/PackageCache/io.coherence.sdk@1.1.3/Coherence.Toolkit/CoherenceSync.cs:2497)
Coherence.Toolkit.EditorCache.UpdateBindings (Coherence.Toolkit.CoherenceSync sync) (at ./Library/PackageCache/io.coherence.sdk@1.1.3/Coherence.Editor/Toolkit/EditorCache.cs:373)
Coherence.Toolkit.EditorCache.UpdateAllCoherenceSyncResourcesPrefabsBindings (Coherence.Toolkit.CoherenceSync[] syncs) (at ./Library/PackageCache/io.coherence.sdk@1.1.3/Coherence.Editor/Toolkit/EditorCache.cs:180)
Coherence.Toolkit.EditorCache.UpdateNetworkPrefabs () (at ./Library/PackageCache/io.coherence.sdk@1.1.3/Coherence.Editor/Toolkit/EditorCache.cs:84)
Coherence.Toolkit.EditorCache.UpdateBindingsAndNotify () (at ./Library/PackageCache/io.coherence.sdk@1.1.3/Coherence.Editor/Toolkit/EditorCache.cs:75)

Thanks for trying to help.

Update: I have removed all variables of type byte[ ], and now it looks like this:

public class Example : MonoBehaviour
{
    [NonSerialized, Sync] public string Example1;
    [NonSerialized, Sync] public byte Example2 = byte.MaxValue;
    [NonSerialized, Sync] public byte Example3;

    // Runtime Variables
    [NonSerialized, Sync] public bool Example4;
    [NonSerialized, Sync] public bool Example5;
    [NonSerialized, Sync] public bool Example6;

    //Component A
    [Command]
    public void ExampleMethod01() { }

    //Component B
    [Command]
    public void ExampleMethod02(byte arg) { }

    [Command]
    public void ExampleMethod03(byte arg, byte arg2, Vector3 arg3) { }

    [Command]
    public void ExampleMethod04(byte arg, byte arg2, Vector3 arg3, Vector3 arg4) { }

    [Command]
    public void ExampleMethod05(byte arg, byte arg2) { }

    //Component C
    [Command]
    public void ExampleMethod06() { }

    [Command]
    public void ExampleMethod07(float arg) { }

    //Component D
    [Command]
    public void ExampleMethod08(CoherenceSync arg, float arg2) { }

    //Component E
    [Command]
    public void ExampleMethod09(ushort arg, float arg2) { }

    //Component F
    [Command]
    public void ExampleMethod10(byte[] arg, byte arg2) { }

    [Command]
    public void ExampleMethod11() { }

    [Command]
    public void ExampleMethod12(Vector3 arg) { }

    [Command]
    public void ExampleMethod13(byte arg) { }

    [Command]
    public void ExampleMethod14(byte[] arg) { }
}

The setup doesn’t seem to have anything wrong… I will ask the rest of the team too!

1 Like

Actually, I just remembered this…

(from our FAQ)

When binding a byte[] field, the field will not be synced when changed by someField[x] = y . The only way to actually update the field, is through someField = new byte[]... which assigns a new reference.

Might that be your case?

Unfortunately, I don’t think so, the main problem seems to be the:

Since the last update:
I have refactored it so we don’t have sync variables of type byte[] in the code anymore.

Regarding the exception thrown when clicking on the “Update bindings”, it was a prefab, removing the CoherenceSync component and adding it again, seems to solve the problem.

The only thing that remains is the message saying CoherenceSync couldn't load the baked script for X. Falling back to reflection.

I will keep investigating what could be the cause, but at least for now, we have a functional build. :+1:

Is this still popping up? If so, it is showing both on Editor and Players?

Is your prefab called [REMOVED], or are you setting that name at some point at runtime?

Some context:

On 1.1.x the gathered schema (Assets/coherence/Gathered.schema) stores the names of the prefabs as part of the definition names, which can be troublesome, specially if the GameObjects have names with non alphanumeric characters.

On 1.2.0 we’re moving away from that, and (re)naming GameObject at will poses no problem for the baking mechanism.

Is this still popping up? If so, it is showing both on Editor and Players?

Yes, but only on the build in the Player.log file. Couldn’t reproduce this in the editor.

Is your prefab called [REMOVED] , or are you setting that name at some point at runtime?

No, the prefab is called Player-Survivors (The [REMOVED] in the message was used just as an example). The name is never changed in runtime. The original message was this:

12:12:43.046 (coherence) CoherenceSync: Couldn't load baked script for 'Player-Survivors(Clone)' (type 'Coherence.Generated.CoherenceSyncPlayer45Survivors_4299c6ae792d7e746b5c7f48af6d2ea5, Assembly-CSharp'). Falling back to reflection.

On 1.1.x the gathered schema (Assets/coherence/Gathered.schema) stores the names of the prefabs as part of the definition names, which can be troublesome, specially if the GameObjects have names with non alphanumeric characters.

Oh, we make extensive use of hyphens, like Player-Survivors or Global-Client-For-Multiplayer. but this problem also happens in prefabs without hyphens like the following prefab Lizard uses a single word and generates this:

09:55:14.374 (coherence) CoherenceSync: Couldn't load baked script for 'Lizard(Clone)' (type 'Coherence.Generated.CoherenceSyncLizard_e968f21a5d58e8e4a9ac1066ee44db7f, Assembly-CSharp'). Falling back to reflection.

Ah right, I got misled by this. Then it’s likely not a problem in the direction I was digging.

Shouldn’t be a problem, since we mangle non-alphanumeric characters.

And definitely won’t be a problem on 1.2.x since we no longer use prefab names for codegen (baked scripts) nor for the gathered schema.

Are you using code stripping?

Yes, the project was set to use code stripping on level High.

I just did a build with the stripping level ‘Minimal’ and everything is working. No reports of problems in the Player.log I think this solves the problem.

Thank you @ciro and @frarees have a great week. :smiley:

2 Likes

Awesome. We’re getting proper code stripping support for 1.2.0 too, which we’re documenting officially. In any case link.xml will still be required to make sure Unity doesn’t strip a few .NET types.

If you care about stripping, you can give this a go.

Create a link.xml file with the following contents anywhere in your project (Assets/coherence/link.xml for example):

<linker>
  <assembly fullname="System">
    <type fullname="System.Net.Configuration.ConnectionManagementSection" />
    <type fullname="System.Net.Configuration.ConnectionManagementElementCollection" />
    <type fullname="System.Net.Configuration.NetSectionGroup" />
  </assembly>

  <assembly fullname="System.Configuration">
    <type fullname="System.Configuration.ExeConfigurationHost" />
  </assembly>
  
  <assembly fullname="Assembly-CSharp">
    <type fullname="Coherence.Generated.Definition" />
    <type fullname="Coherence.Generated.Binding*" />
    <type fullname="Coherence.Generated.CoherenceSync*" />
  </assembly>
</linker>

With code stripping it’s always hit or miss, and highly depends on your project and on the third-party libraries its using. But with the linker definitions listed above, Unity shouldn’t strip what’s necessary for coherence to work.

If you give it a try, report back with your findings. Good luck!

2 Likes

I took the liberty of editing the thread’s title to add “managed code stripping”, so anyone who has a problem with this might stumble into this conversation and find a fix, until we make it more automatic.

Hope it’s ok!

2 Likes

I did another build setting the code stripping level back to High, using this link.xml and it worked just fine, with no problem in the Player.log. :slightly_smiling_face:

That’s ok, I hope this helps others too.

Thank you all for the support.

2 Likes