So I have a C# project that generates a dll that is shared by client and server. I reference libraries like mathematics in this project. I’ve been referencing it from ScriptAssemblies, so I know the reference is always up to date with the package Unity is using.
But Unity complains about that saying it’s not able to reference the package. It eventually sorts it out as there are no compile errors. So I’m assuming the package dll’s are at some point either built or copied to ScriptAssemblies during start or reload?
So what is the correct way to reference packages from other projects?
You got the gist of it. The assemblies under ScriptAssemblies are generated by the Unity compilation pipeline.
Some context: scripts in packages are compiled with assembly definitions, which play a role in the compilation pipeline similar to Visual Studio projects (e.g. .csproj). When assemblies are compiled from assembly definitions and their scripts, the generated DLLs are copied to the ScriptAssemblies directory.
When a project is first opened, that folder does not exist (unless it was put under source control, which is strongly discouraged). It gets populated with the assemblies built from code in packages and your project Assets. In addition, there are situations where they will be rebuilt and re-copied, which might provide a tiny window where the DLL files are missing.
In addition, we don’t currently support pre-compiled assemblies (DLL files built outside Unity, and imported from your Assets or in packages) referencing assemblies built with assembly definitions. While this can work, there will be situations where the precompiled DLL cannot has TypeLoadExceptions (for instance) as a referenced DLL has not been compiled yet; this seems to be your case, if I understand correctly.
So assuming both your client and server are built with Unity, the simplest solution is to also use assembly definitions with the scripts directly under your Unity project, rather than building it outside of Unity. Since assembly definitions declare references to other assembly definitions, the compilation order is guaranteed, and it also ensures that your DLL won’t be loaded without its dependencies being compiled first.
Thanks for the info. The server is not Unity. While you could put the shared code under Unity in cases like this and copy dll’s to the server, it’s generally problematic. Like if you actually do unit testing the compile/test flow in VS is clearly superior and faster. Unity also has no first class support for Nuget and we make use of things like T4 templates and also build pipeline hooks.
Are there plans to support pre-compiled assemblies referencing assemblies built with assembly definitions? This would be extremely valuable for our team, for reasons similar to what @snacktime mentioned.
Use cases like yours are not that rare, so this is something we’re looking into. However I cannot make any guarantees about this nor provide any ETA at this time.
An update would be great @maximeb_unity . We’re currently facing a similar problem where we’re referencing a generated package dll in our custom DLL.
I’ve posted a thread here , but never got a response. Now that I found this post, I at least know that it’s a common problem.
Edit:
I would also take an alternative approach to the problem. All I need to achieve is to get the (Addressables) package scripts into my visual studio project, without copying them in the best case (which is what we’re doing at the moment and which is pain af!)
All created DLLs are copied into the Unity projects Plugins folder. This works fine for all DLLs except for Z. Z needs one of the packages (e.g. com.unity.ugui) and as we can’t simply reference the automatically generated DLL from the UnityProject/Library/ScriptAssemblies folder we come to our problem.
The solution to this problem is to exclude the logic Z project from the logic solution, make a custom package for the UPM out of it and add the dependency to the package then. This would lead to an updated structure like:
Now this leaves the only problem open when Z also needs to scripts from the Unity project (e.g. when importing a plugin from the Assetstore which comes with scripts you want to reference). You can’t simply convert the imported plugin into a package and even if you move it outside of the project, create a custom package file for it,… Z can’t reference to other local packages at the moment, as the UPM isn’t able to setup such local dependencies.
Would be nice to know if and when the UPM would allow those local dependencies, but actually I’d prefer if packages would compile into DLLs which then could be reference from my outside DLL projects.
Is there any update on this? I’m having a similar issue.
I have an external solution with several projects which I can’t put inside Unity because they have T4 templates.
At the moment, in each of my projects, I have to reference the path for each assembly of Unity, but since some of those assemblies are inside Library it produces several issues. The most common one is UnityEngine.UI sometimes become missing and is very difficult to fix it (because, obviously, we are depending on dlls made by the Unity compilation pipeline).
The solution is to copy the dlls to another location, and reference the copies. I got that working with analytics in a dll (I just needed to delete the extra analytics dll that was output with my dll build).
Of course, the caveat to this is that the dll will always expect that package to exist, and will fail the engine build if it doesn’t (it’s already compiled, so you can’t add additional compiler symbols for the build).
[EDIT] Oh I just realized this thread is about dlls from a Unity build being used in a program entirely outside Unity. My use case was for a dll brought into Unity. My bad.
@maximeb_unity Curious if there’s been any movement on allowing plugin DLLs to reference DLLs from assembly definition files (or, more generally, from UPM packages). This might help my current use case:
I have a custom UPM package that contain a DLL. Some of the types in that DLL use attributes from the popular Odin Inspector asset to improve their Inspector UI. I’ve declared odininspector as a dependency of my UPM package, requiring consumer projects to install Odin as a UPM package itself (specifically, as an embedded package). Unfortunately, none of these Odin attributes are working. I’ve verified that the attributes exist in the built DLL using a decompiler, so the issue is clearly that my custom DLL cannot reference Odin’s types. I’ve looked into setting but that would require altering Unity-generated csproj files, which would be annoying to version control. The answer on this StackOverflow post suggested adding -property:ReferencePath=... to the actual MSBuild execution, which I could possibly add to a csc.rsp file, but no luck yet (and I would prefer not to make consumers of my package mess with .rsp files). Most of the Odin types that I need are actually inside a DLL inside the Odin package (Sirenix.OdinInspector.Attributes.dll), so this should be a direct DLL->DLL reference, but I’m not sure where Unity adds embedded packages in the script compilation order?