colyseus / colyseus-unity-sdk

⚔ Colyseus Multiplayer SDK for Unity
https://docs.colyseus.io/getting-started/unity-sdk/
MIT License
375 stars 102 forks source link

Schema-derived types will have their default constructors stripped by Unity's Managed code stripping setting medium or above #135

Open tonygiang opened 3 years ago

tonygiang commented 3 years ago

Unity has a feature called managed code stripping to reduce the size of a build. During this process, if the setting is set to Medium or High, all types derived from Colyseus.Schema.Schema will have their default constructors stripped because Unity's linker determine that they are unreachable code, which leads to MissingMethodException during runtime handshaking.

Schema-derived types include all types generated by schema-codegen and also the built-in types used by Colyseus Unity client such as Colyseus.Schema.ReflectionField, Colyseus.Schema.ReflectionType and Colyseus.Schema.Reflection.

While adding the UnityEngine.Scripting.Preserve attribute to each Schema-derived types will preserve their default constructors, it will lead to a "Local schema mismatch from server" exception on High managed code stripping setting, which technically is a different issue from this, but until there is an official fix, the safe option for users of Colyseus Unity client for now is to build with managed code stripping setting set to Low or disabled.

devPryze commented 3 years ago

thanks for the heads up!

endel commented 3 years ago

Thanks for the heads up @tonygiang!

(I'm just documenting here my findings for future reference, as this issue is not super high priority)

I've tried to configure Managed Code Stripping right now and couldn't make it work for both "Medium" and "High", even if using [UnityEngine.Scripting.Preserve] on every Schema-related structure (both on core classes, and classes generated via schema-codegen)

Screen Shot 2021-05-28 at 19 54 43

Maybe using a link.xml file could be easier to configure.

Possible solutions could be:

Cheers!

tonygiang commented 3 years ago

I just encountered this issue out of nowhere but with code stripping set to Low. Now it seems like the only safe choice is no code stripping.

Edit: nope, disabling code stripping doesn't work either. Something else is causing the issue and I can't tell what.

I'm starting to think you need to reconsider the reflection approach to schema checking.

tonygiang commented 3 years ago

Apparently IronSource SDK could cause problem with Schema types' constructors being stripped as well. I don't know how but it does.

burhanyilmaz commented 3 years ago

Hi @endel, There is no problem with the development. After I build a project for WebGL, when I join the room, I receive this error.

 MissingMethodException: Default constructor not found for type Colyseus.Schema.ReflectionType
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic) [0x00000] in <00000000000000000000000000000000>:0 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <00000000000000000000000000000000>:0 
endel commented 3 years ago

Hi @burhanyilmaz, which level of Code Stripping are you using? Low, Medium, or High? EDIT: Also if you can provide the version of Unity that can be helpful!

burhanyilmaz commented 3 years ago

@endel Thanks for the response! unity version is 2020.3.12f1 strip engine code ✅ manage stripping level : Low

burhanyilmaz commented 3 years ago

I tried these. But I am not sure that these are correct or not :/

MyState.cs

// 
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
// 
// GENERATED USING @colyseus/schema 1.0.25
// 
using UnityEngine.Scripting;
using Colyseus.Schema;

[Preserve]
public partial class MyState : Schema
{
    [Preserve]
    [Type(0, "string")]
    public string currentTurn = "";
}

link.xml

<linker>
  <assembly fullname="Colyseus">
    <type fullname="Colyseus.Schema.ReflectionType" preserve="all"/>
  </assembly>
</linker>

Thanks!

burhanyilmaz commented 3 years ago

When the target platform is macOS, there is no problem. I connected to the room and received messages. it is related to WebGL build.

burhanyilmaz commented 3 years ago

@endel @tonygiang I fixed this issue https://github.com/colyseus/colyseus-unity3d/pull/163

tonygiang commented 3 years ago

Not so fast. This issue affects all C# types generated by schema-codegen. It will be fixed when schema-codegen is fixed.

endel commented 2 years ago

Relevant to this discussion, a Discord user has reported this comment: (building for Android)

i can't compile il2cpp because unity only has low striping for il2cpp and not disable.. but it works on Mono backend which has the disable function stripping