Search Unity

Referenging package dll's in external projects

Discussion in 'Package Manager' started by snacktime, Jan 8, 2019.

  1. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    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?
     
  2. maximeb_unity

    maximeb_unity

    Unity Technologies

    Joined:
    Mar 20, 2018
    Posts:
    556
    Hi @snacktime,

    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.
     
    pahe4retro likes this.
  3. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    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.
     
  4. astorms

    astorms

    Joined:
    Jan 31, 2018
    Posts:
    50
    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.
     
  5. maximeb_unity

    maximeb_unity

    Unity Technologies

    Joined:
    Mar 20, 2018
    Posts:
    556
    Hi @astorms,

    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.
     
    twobob likes this.
  6. farshidhss2

    farshidhss2

    Joined:
    Sep 19, 2019
    Posts:
    6
    Is there any update on this? we have a very similar use case.
     
  7. pahe4retro

    pahe4retro

    Joined:
    Aug 13, 2019
    Posts:
    33
    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!)
     
    Last edited: Nov 8, 2019
  8. pahe4retro

    pahe4retro

    Joined:
    Aug 13, 2019
    Posts:
    33
    So, I spend the weekend with the problem and I found a kinda solution at least to one of our problems:

    Our project structure looks like:
    Code (csharp):
    1. - <logic solution>.sln
    2. -- <logic A>.csproj   (no unity references)
    3. -- <logic B>.csproj   (no unity references)
    4. -- ...
    5. -- <logic Y>.csproj   (unity referenced)
    6. -- <logic Z>.csproj   (unity and unity packages referenced)
    7.  
    8. - Unity Project
    9. -- Assets
    10. --- Plugins
    11. -- Packages
    12. --- <package1>   (e.g. com.unity.ugui)
    13. --- ...
    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:

    Code (csharp):
    1. - <logic solution>.sln
    2. -- <logic A>.csproj   (no unity references)
    3. -- <logic B>.csproj   (no unity references)
    4. -- ...
    5. -- <logic Y>.csproj   (unity referenced)
    6.  
    7. - Unity Project
    8. -- Assets
    9. --- Plugins
    10. -- Packages
    11. --- <package1>   (e.g. com.unity.ugui)
    12. --- <package logic Z>   (added dependency to com.unity.ugui)
    13. --- ...
    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.
     
    nirvanajie likes this.
  9. Enderlook

    Enderlook

    Joined:
    Dec 4, 2018
    Posts:
    53
    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).
     
  10. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    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.
     
    Last edited: Oct 9, 2020
  11. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    4 years later - still broken?
     
  12. Rabadash8820

    Rabadash8820

    Joined:
    Aug 20, 2015
    Posts:
    94
    @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 <AssemblySearchPaths/> 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?
     
    Last edited: Aug 6, 2023