Search Unity

How to reference a core package in external projects

Discussion in 'Package Manager' started by jgbt, Nov 13, 2019.

  1. jgbt

    jgbt

    Joined:
    Nov 13, 2019
    Posts:
    8
    Hello all,

    I need to reference UnityEngine.Timeline in an external C# Dll project. The project is to generate a Dll file to be used in Unity 2019. Unlike in Unity 2018, where Timeline is a Dll file, it is a core package in Unity 2019. How can I get my project to reference it?

    Thanks!
     
  2. pahe4retro

    pahe4retro

    Joined:
    Aug 13, 2019
    Posts:
    33
    Wondered the same, you can find a "solution" to this here.
     
  3. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    Package stuff get stored under Library/PackageCache. When compiled, they get stored in Library/ScriptAssemblies. So you can get a reference to a dll straight from there. I think linking directly to such a file is better, so long as you remain in the same Unity major version. If the package gets updated, that assembly will be too, so it's like a link to the last version of the assembly.
     
    TildeAsterisk likes this.
  4. jgbt

    jgbt

    Joined:
    Nov 13, 2019
    Posts:
    8
    Your solution is different than our usual way of delivery of our product, but thanks for the information.

    For some unknown reason, there is no "com.unity.timeline" sub-directory in Library/PackageCache directory. However, there is a Unity.Timeline.dll (not UnityEngine.Timeline.dll) in Library/ScriptAssemblies. I've tried referencing a copied version of it that sits inside our project. It compiles. However, when the generated Dll file is imported into a test project, the following message occurs:

    Assembly 'Assets/<OUR_PLUGIN>.dll' will not be loaded due to errors:
    Unable to resolve reference 'UnityEngine.Timeline'. Is the assembly missing or incompatible with the current platform?
    Reference validation can be disabled in the Plugin Inspector.

    If I deselect "Validate References" option in the plugin's Import Settings, the error message goes away. Is there a programmatic way to disable the option?
     
    TildeAsterisk likes this.
  5. pahe4retro

    pahe4retro

    Joined:
    Aug 13, 2019
    Posts:
    33
    This is the first time I've got to distribute code that way and we're not very happy with that, so if you find a better way, please let me know.

    Can you still build without the dll only in your Packages folder?

    Normally DLLs outside of the projects Assets folder are not compiled, so if you can't build you can copy that dll into your Assets/Plugins folder and then it should work.
     
  6. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    You're right, there's no Timeline folder in PackageCache. It's probably distributed as a dll only, just like in 2018 cycle.
    Check you're not using IL2CPP as backend in Unity. If you are then they probably won't be compatible.
    I got it working pretty easily. As you can see I can use Timeline stuff and the compiler does not nag me.

    compiles.png
     
  7. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    If we're talking about Unity dlls or Unity code, especially code that gets managed/distributed through UPM, then it's probably a bad idea to add it to the Assets folder as well. It's like having two files with the same class definition inside, in two different locations in the folder structure, which both get compiled. The compiler is bound to nag it doesn't know which one to use since they have the same definition. It'd be a different case though, if you were to use the dll in the Assets/Plugins and then go and remove the package from the manifest, so it only exists in Assets/Plugins.
    But still, you're bound to lose the ability to update it if updates get rolled out through the Package Manager.
     
  8. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    Hold on, I might have misread/misunderstood stuff.

    I thought you needed to reference the Timeline dll in a non Unity plain c# project. If so, just reference it through Browse(don't copy it over to the c# project) and do whatever. After you build, you only need the dll from your external C# library(e.g. MyLibrary.dll) and then to use it in a separate Unity project, just add your own dll in the Assets/Plugins and then go to the PackageManager and download the Timeline if it's not already in the project(make sure to use the correct version if Timeline has changed a lot in between versions). That will resolve the dependency from MyLibrary.dll to Timeline.

    Did I understand correctly?

    Also are you actually using the external C# lib in non-Unity projects(e.g. WinForms, Console, WPF)? If not, why don't you just write a custom package? You can enforce Timeline version through package.json dependencies. That way you know if you need to change your lib code or not.

    If you already know the following, just ignore them.
    Also if you have a server of your own, you can use something like Verdaccio and host a scoped registry which means you can just download your library through PackageManager to any project you like. Also much easier to roll updates to your library and deploy them.
     
  9. jgbt

    jgbt

    Joined:
    Nov 13, 2019
    Posts:
    8
    I'm not sure what you mean by that.

    I only need the reference of the Dll so that the code can compile. The compiled Dll file gets put into clients' Unity 2019 projects. Timeline is part of Unity 2019. We are not to ship Timeline code/Dll.

    This is what I'm trying to do, but I suppose you were talking to pahe4retro.

    By doing this, there is the issue of Unity being unable to resolve reference, as described above.

    By the way, our Dll does not have to be in Plugins directory. Is the directory name still a requirement?
     
  10. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    Got confused since there was mention of Assets and Plugins in previous posts.

    Whatever, one solution is you write a custom package inside Unity, whose dependencies are nicely resolved by Unity PackageManager and you don't have to ship Timeline(the dependency is stored in the package.json).

    The other is to do what you were trying to do. You'll need a Unity 2019(since you're targeting 2019) project with Timeline downloaded. Reference it in your C# project and compile. If the compiler is complaining, it's probably architecture differences between then. So check your plain C# project and the scripting backend+arch of the Unity project match(e.g. both C#, so no IL2CPP, and both x64 etc). Previously I posted a thumbnail where I did just that and it compiled properly. So it's definitely doable.

    The Plugins folder still holds, so this is probably where you need to deploy your managed dll once compiled. Packages are stored in Library and are only managed by Package Manager so you can't deploy there unless it's a package. Otherwise you might be able to reference the dll from a different folder, under Assets, than Plugins, by configuring any existing AsmDefs to include it.
     
  11. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    The dll is named Unity.Timeline.dll but the namespace is UnityEngine.Timeline.

    Out of curiosity, I tried throwing the dll of a library referencing Timeline in a Unity project. No errors whatsoever.
    The only way I got to reproduce your message was to remove Timeline from the project. Reinstalling the package from the PackageManager resolves the issue.
     
  12. jgbt

    jgbt

    Joined:
    Nov 13, 2019
    Posts:
    8
    Just to confirm, reference what? Unity.Timeline.dll in Library/ScriptAssemblies folder?

    Do you have any idea why our Dll files don't have to be in Plugins folder?

    I suppose the Unity project had not had Timeline package installed in Package Manager. Correct?

    The error message was for our custom Dll file. What file was the error message for in your case?
     
    Last edited: Nov 18, 2019
  13. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    Yes. When adding the reference, choose Browse and navigate to that folder in any Unity 2019 project that has Timeline installed.

    Plugins folder is mainly used for native plugins. Yours is a managed one. You can throw it anywhere you like under Assets and it will work(so long as dependencies are met, e.g. Timeline is installed). I typically put everything under Plugins so I have a singular point of reference when searching for dlls. To be honest, I'm not sure if there's any detriment to having managed dlls inside Plugins, but I haven't encountered one so far.
    That said, if you were to create a custom package for your custom dll or deploy the dll in a project using a Custom Package(perhaps you have Unity code and/or assets for a package that need your custom dll), then the dll would be imported under Library/PackageCache/<the package>/....relative-path-to-dll. It'll still be usable anywhere in the solution(same way Timeline which resides in Library folder is accessible in scripts under Assets). If though, you have already copied the dll under Assets, the package manager will not import the dll again inside Library. So you shouldn't get error messages complaining about dll existing twice in the project.

    That's what I think, or at least it's the only reasonable explanation I can give since I tried it and I reproduced the error that way. You have but to check the project that the error pops up in. If it's not installed, install it. The error should go away.
    If that wasn't the case, reply back.
    Though, I am hesitant. Timeline is usually installed by default in new projects. Unless someone had intentionally removed it (e.g. to cut down on packages loaded if unneeded and thus make project load faster), I think it might be a different issue. Well...unless the Unity version of the project you're testing your dll in, is not compatible. Make sure you have the same Unity version in both the project you're referencing Timeline from and the project you're testing your dll in. Also check the Timeline package version is the same in both.

    Indeed, since your custom dll is the one referencing a non existent assembly. The source of the error is going to be in your custom dll.
     
  14. jgbt

    jgbt

    Joined:
    Nov 13, 2019
    Posts:
    8
    It turns out that I had been using UnityEngine.Timeline.dll of Unity 2018 (and it worked!). I replaced it with Unity.Timeline.dll of Unity 2019, the compilation of our custom Dll failed with the following errors:

    error CS0012: The type 'PlayableAsset' is defined in an assembly that is not referenced. You must add a reference to assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
    error CS0039: Cannot convert type 'UnityEngine.Playables.PlayableAsset' to 'UnityEngine.Timeline.TimelineAsset' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion


    Adding reference to UnityEngine.CoreModule.dll led to compilation failure, too, complaining about conflicts between UnityEngine and UnityEngine.CoreModule.

    Removing reference to UnityEngine led to even more errors.

    It seems that I have to use UnityEngine.Timeline.dll of Unity 2018.

    We have a native Dll alongside the managed Dll.
     
    Last edited: Nov 19, 2019
  15. pahe4retro

    pahe4retro

    Joined:
    Aug 13, 2019
    Posts:
    33
    This is what I'm trying to tell you :) You can't reference the Timeline.DLL of the 2019 Unity project, as that DLL is compiled in a different way than that of 2018!

    The "solution" to this is, that you have to reference Timeline as a package! And that's only possible if you have a package by yourself.

    If it works for you or you figure out how you can without a package, please let me know, as we're in the same bad spot.
     
  16. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    Seems like it. Unfortunately I don't have the time to investigate. Weirdly, I figured out which dlls need to be included for the project to compile outside Unity, but Unity complains about the dll itself. I wonder if you have to replace some of the core dlls used as references( VS by default adds some core dlls even if you remove them as a safety hack, e.g. System.Core, Microsoft.CSharp).
     
  17. jgbt

    jgbt

    Joined:
    Nov 13, 2019
    Posts:
    8
    How exactly?

    As I stated above, I achieved it by using UnityEngine.Timeline.dll of Unity 2018. The only issue was the error when the unitypackage was imported into Unity 2019 project. And it could be resolved by unchecking Validate References in the import settings.

     
  18. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    https://docs.unity3d.com/Manual/CustomPackages.html
    I mentioned that as well in my earlier posts. This is how many parts in Unity are distributed now. Cinemachine and TextMeshPro are good examples( as they are not compiled into dlls but remain as readonly cs scripts, effectively compiled by Unity upon package installation/update).

    Sure but referencing 2018 assemblies while targeting 2019 Unity which has newer versions of it means it might break if Timeline is updated in those projects(breaking changes to Timeline which do happen when you change major versions 2018->2019).

    PS: Some tech savvy person might probably figure out how to reference 2019 assemblies outside Unity projects and work with them but Custom Packages are the way to go from now on. Even AssetStore will eventually converge to packages and the engine itself slowly does(See Built-In packages in UPM). Not to mention, if you use an npm-like registry for your company packages, it'll make reuse easier. That said, you can also use Git URLs(if a registry/server is not possible) and soon, you will also install/update them through UPM UI as well. UPM is definitely worth the time to get accustomed to.
     
    pahe likes this.