Search Unity

Assembly Defintions are unfriendly

Discussion in 'Scripting' started by Tomer-Barkan, Jun 15, 2020.

  1. Tomer-Barkan

    Tomer-Barkan

    Joined:
    Jul 31, 2012
    Posts:
    150
    So I tried using assembly definitions to reduce compile time, but they're very unfriendly.

    Given, I have to make sure that in my own code, they are ordered so one assembly depends on another but not both ways. That makes sense, and I did that.

    However, it seems that Unity is unable to handle dependencies within itself. For example, if I have a separate assembly and it makes use of UnityEditor, then it won't run. Many of my classes have editor-related stuff in them. Also, if I make use of TextMeshPro, which is pretty much any UI feature I have, then it won't work.

    These are the kinds of things I'd expect to work out of the box. I just want to take my project, split it into smaller parts to save compilation time, and have each one of them work as they did before. Any behaviors that differs from this default, that should be manually specified.

    For example, I'd expect all scripts in Editor folders to stay in the Editor assembly, even if one of their parent dirs has an assembly definition file. That should be the default behavior. Editor scripts tend to not work outside of the editor assembly. If I want to override this behavior, let me, that's fine.

    Same with packages. Why do I have to define package versions per assembly? I already chose my versions in the package manager, why shouldn't that apply to all my assemblies?

    I wonder if there's any logic to these decisions, if not, my feedback is - please change it and make it easier to setup separate assemblies out of the box without working too hard.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    What version are you on?

    I just tested and I was able to reference UnityEditor from within my assembly. Of course I wrap it in #if UNITY_EDITOR so that it is only done in editor specific compilation:
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. #if UNITY_EDITOR
    7. using UnityEditor;
    8. #endif
    9.  
    10.  
    11.  
    12. public class Blargh : MonoBehaviour
    13. {
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.      
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.      
    24.     }
    25.  
    26.  
    27. #if UNITY_EDITOR
    28.  
    29.     private void OnDrawGizmos()
    30.     {
    31.         Gizmos.color = Color.red;
    32.         Gizmos.DrawSphere(this.transform.position, 5f);
    33.     }
    34.  
    35. #endif
    36.  
    37. }
    38.  
    This worked 100% when in a folder with an AssemblyDefinition.


    This makes sense, your assembly needs to have a reference to TextMeshPro assembly so that Unity knows to include it as a dependency.

    In your AssemblyDefinition under "Assembly Definition References" add a new entry.
    Then in the project window navigate to Packages/TextMesh Pro/Scripts/Runtime/Unity.TextMeshPro

    This is the assemblydef for TMPro. Drag it into that added slot on your assembly definition. Like so:
    upload_2020-6-15_18-22-4.png


    I'd agree the documentation could be better on Unity's part.

    Personally how I do this is I layout my custom assembly folders in a similar fashion to the TextMesh Pro folder. Note how it has a "Scripts" folder in which it has "Editor" and "Runtime" folders (I forego the scripts folder, but the editor/runtime folders is what I emulate). The "Runtime" folder gets the assemblydef, but the editor does not.
    upload_2020-6-15_18-24-9.png

    Here is mine:
    upload_2020-6-15_18-31-28.png

    I'm not sure to what you're referring too...

    Well the first thing I already demonstrated is not so.

    As for the need to add dependencies... well... you have to. How would unity know what packages to add dependency references too? The options are add ALL (which could create dependency circles) OR have you configure it (well I guess technically speaking it could write an extension to Visual Studio and watch as you add 'using' statements and dynamically add references if you type it in... but this would only work if you used Visual Studio and has added overhead. I guess there could be other hook locations, but again, overhead and support complexity that could cause it to be buggy as all heck). Personally I'd prefer Unity not mucking around with my dependency tree and I take care of it. It's relatively straight forward how to do it.

    As for the 'editor' folder. The assembdef is overriding that folder hierarchy specifically. Just organize your folder out to account for it like I described. It's not too complicated and results in nice organization.
     
  3. Tomer-Barkan

    Tomer-Barkan

    Joined:
    Jul 31, 2012
    Posts:
    150
    I guess, I'd mainly want the assemblies I define, by default, to behave the same way that the default Assembly-CSharp does. Have the same references. TMPro is a built-in unity package, why not reference it by default?

    As for the editor issue, it's because of the Editor folder not being put in the Assembly-CSharp-Editor assembly like it would have without the assembly definition file. It was missing dependencies such as the AssetPostprocessor.

    I get what I did wrong and how to fix it, I just feel that out-of-the-box behavior should be more in-line with how the Assembly-CSharp behaves, unless there is good reason not to, that I'm unaware of?
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Well, no, technically it's not built-in. It's part of the package system and needs to be added. I believe by default it is added, but it's not defacto part of your project like the UnityEngine.dll is.

    I'd argue it make a weird hierarchy. Where my assembly contains directories that aren't in my assembly. I know I and many others have honestly criticized Unity's "magic folders" for a long time, I don't know if said criticisms led to their choice or not, but I feel like it is one of their attempts at moving in the direction of a more mature project structure rather than a lot of the hand-holding "magic" stuff they implemented in early/legacy version of Unity which the "Editor/Resources/etc" folder naming comes from.

    Good reason is a subjective thing here.

    It's good in that it allows for better control over your organization that is in line with how developers/programmers like myself are familiar with and used to rather than Unity pulling strings behind closed doors on our behalf to make our lives ever so slightly easier in a very short moment (like setting up an assembdef), but causing headaches in the long wrong (when that automated system keeps adding dependencies to something I don't want it to and I can't stop it from doing because it's all automated).

    Of course this breaks a trend that Unity established early on in its product career. Which benefits those who like the magic string pulling on their behalf because "it just works" for them.

    The balance between those 2 is a hard think to hit for developers, especially one with such a diverse group of developers.
     
    Lurking-Ninja likes this.