Unity-Technologies / multiplayer-community-contributions

Community contributions to Unity Multiplayer Networking products and services.
MIT License
421 stars 161 forks source link

Enet DllNotFoundException on iOS #164

Open trevorbye opened 2 years ago

trevorbye commented 2 years ago

This transport is working fine on standalone and Android, but I'm having a lot of trouble getting it working on iOS. For Android we have the compiled libs in Assets/Plugins/Android/lib with subdirs for each architecture, and a .so file in each one of those subdirs. I built enet from source for iOS following these instructions which results in a file libenet.a which I put in Assets/Plugins/iOS and set to iOS only and arm64. After building in Unity, in the XCode project under UnityFramework Link Binary With Libraries I can see libenet.a so it is in the project, it just can't find it at runtime for some reason.

I'm not sure if there is a different way I need to be compiling this for iOS, a different file extension, or if I'm putting it in the wrong folder/need to change inspector settings in Unity, but I've tried quite a few permutations of all these and when running on iOS, it keeps giving this stack trace:

DllNotFoundException: Unable to load DLL 'enet': The specified module could not be found.
  at ENet.Native.enet_host_create (System.IntPtr address, System.IntPtr peerLimit, System.IntPtr channelLimit, System.UInt32 incomingBandwidth, System.UInt32 outgoingBandwidth, System.Int32 bufferSize) [0x00000] in <00000000000000000000000000000000>:0 
  at ENet.Host.Create (System.Nullable`1[T] address, System.Int32 peerLimit, System.Int32 channelLimit, System.UInt32 incomingBandwidth, System.UInt32 outgoingBandwidth, System.Int32 bufferSize) [0x00000] in <00000000000000000000000000000000>:0 
  at ENet.Host.Create (System.Int32 peerLimit, System.Int32 channelLimit) [0x00000] in <00000000000000000000000000000000>:0 
  at Netcode.Transports.Enet.EnetTransport.StartClient () [0x00000] in <00000000000000000000000000000000>:0 
  at Unity.Netcode.NetworkManager.StartClient () [0x00000] in <00000000000000000000000000000000>:0 

Am I building enet for iOS correctly? There aren't really docs for any of this so I'm giving my best guesses/trial and error, but hopefully someone has an idea of anything else I can try. I also tried putting libenet.a in the runtime dir of the actual transport under Packages but no luck there either. I've also looked for any sample code/projects that used this transport for iOS, so if anyone has any links that would be helpful.

trevorbye commented 2 years ago

I figured out this library will not actually work out of the box on iOS. The problem is ENet-CSharp.dll which is a compiled version of the actual source file ENet.cs.

This file should have never been compiled into a DLL, it's meant to be used as source, because it has Unity compile attributes inside...this is so obvious to me now but I just didn't see it initially. These compile attributes are supposed to tell Unity to, when on iOS platform, look for DLLs by the name __Internal rather than the actual lib name (enet in this case). Because it was compiled outside Unity into a DLL, this never happens on iOS and so it will never find your native enet lib for iOS.

I was going to submit a PR, but this package needs a complete refactoring to use ENet.cs properly and I'm unsure what the intended direction is here. But here's what I did to get it working on iOS:

  1. Install the transport normally
  2. Delete ENet-CSharp.dll here and replace it with ENet.cs. Yes it is that easy, the namespace is the same so it will just pick up the refs
  3. Comment out the version checks here and in the function below it. This is the part I'm not super clear on, this check seems fairly contrived and doesn't seem to make a difference. Proceed at your own risk, but it's working fine for us thus far.
  4. Building enet from source for iOS is the next thing you need to do. Run the build script build-ios.sh here (you will need a mac with xcode installed and may also need to run xcode-select --install to get the cli tools). This produces a file libenet.a which is the static iOS library. Put this in Assets/Plugins/iOS/ in Unity and set to iOS only and ARM64.

After doing the above and building/running in xcode, it should find the static enet lib.