Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Dec 8, 2022, between 7 am & 7 pm EST, in the DOTS Dev Blitz Day 2022 - Q&A forum, Discord, and Unity3D Subreddit to learn more about DOTS directly from the Unity Developers.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Question Call managed DLL function in editor only circumstance?

Discussion in 'Scripting' started by AerionXI, Nov 6, 2022.

  1. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    How would I call a VS2019 function from my managed, editor-only C# DLL with an #if UNITY_EDITOR statement?

    I need to call an editor-only function.

    How would I do this?
     
    Last edited by a moderator: Nov 25, 2022
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,104
    You need to call a "VS2019 function"... what is that?

    You say a "C# dll" are you saying you've compiled your code into a dll? If so, the compiler directives (see: #if UNITY_EDITOR) won't matter since you've already compiled it into a dll. Those directives are used at time of turning it into a dll.

    ...

    So... lets back up, and you answer some questions.

    1) What function do you need to call? If there is many, and you need a general use scenario, give an example of a function you need to call. Saying "VS2019 function" doesn't really make sense in this context.

    2) Are you attempting to precompile a dll that is brought into Unity?
     
  3. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    1) I need to call my quit function for not only windows but webgl as well as in editor mode.

    2) yes. i built the compiled C# DLL.
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    2,435
    Those two contradict each other. If the method is an editor only function, you can not use it at all ouside the editor. Why are you asking such a cryptic question? Can't you explain what function exactly. What does your "quit" function do?
     
    lordofduct likes this.
  5. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    The quit function allows for not only windows platforms to promptly quit execution, but also when in editor play mode as well.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,104
    Your description is contradictory.

    If a function is "editor-only", which the sentence "I need to call an editor-only function." This would imply that the function is available only in the editor.

    Which this sentence then contradicts: "I need to call my quit function for not only windows but webgl as well as in editor mode."

    If the function was available in places that aren't just the editor (windows and webgl). Well then it's not "editor-only". Either you can't call it cause by definition it's editor-only, or if it's not editor-only then why call it editor-only?

    ...

    I still have no idea what you're trying to describe. So how about you share the code you have and we work from there.
     
    Bunny83 likes this.
  7. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    ok, here it is @lordofduct

    Code (CSharp):
    1. #define UNITY_EDITOR
    2. #define UNITY_EDITOR_64
    3. #define UNITY_EDITOR_WIN
    4. #define UNITY
    5.  
    6. using System;
    7. using System.Diagnostics;
    8. using System.IO;
    9. using System.Collections;
    10. using System.Collections.Generic;
    11. using System.Reflection;
    12. using System.Runtime.CompilerServices;
    13. using System.Security;
    14. using System.Security.Permissions;
    15. using System.Threading.Tasks;
    16. using UnityEngine;
    17.  
    18. #if UNITY_EDITOR || UNITY_EDITOR_64 || UNITY_EDITOR_WIN || UNITY
    19.     using UnityEditor;
    20. #endif
    21.  
    22. using MySpecialLib;
    23.  
    24. namespace MyLibEdit {
    25.  
    26.     public class MyEditorCommands : EditorWindow {
    27.  
    28.         #if UNITY_EDITOR || UNITY_EDITOR_64 || UNITY_EDITOR_WIN || UNITY
    29.             /// <summary>URL to quit WebGL Instance.</summary>
    30.             public static string webplayerQuitURL = "";
    31.         #endif
    32.  
    33.         /// <summary>Quits this instance.</summary>
    34.         public static void Quit ( ) {
    35.  
    36.             #if UNITY_EDITOR || UNITY_EDITOR_64 || UNITY_EDITOR_WIN || UNITY
    37.                 UnityEditor.EditorApplication.isPlaying = false;
    38.             #elif UNITY_WEBPLAYER
    39.                 Application.OpenURL ( webplayerQuitURL );
    40.             #else
    41.                 Application.Quit ( );
    42.             #endif
    43.  
    44.         }
    45.  
    46.     }
    47.  
    48. }
    Note I reference "MySpecialLib" so my main library can read this code and call the Quit ( ) function in MySpecialLib.dll
     
    Last edited: Nov 7, 2022
  8. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    80
    We’ve gone over this before. The preprocessor #if will remove inapplicable code at compile time and you’ll have to make separate DLLs for each target use case. You don’t need to make a DLL for a simple script like this. You’re over-complicating things. Just add that to your unity project as a source file.
     
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,104
    So remember when I said:
    You've said you're precompiling this into a dll. So that dll isn't going to dynamically change which method it calls... you need to compile a different dll for each mode, include each in your project, and then configure them for which platform each compiled version is for.

    Next. As to your code.

    You lead your code file with:
    Code (csharp):
    1. #define UNITY_EDITOR
    2. #define UNITY_EDITOR_64
    3. #define UNITY_EDITOR_WIN
    4. #define UNITY
    This means you've set all of these as defined/true at the start of the file. This means every time you say something like this in the code file:
    Code (csharp):
    1. #if UNITY_EDITOR || UNITY_EDITOR_64 || UNITY_EDITOR_WIN || UNITY
    It always resolves as true since all 4 of those are defined at the top.

    Now I'm betting you defined them at the top because you have this in a separate Visual Studio project from your Unity project and if you don't define them then they always resolve as false!

    I'm betting you assume that you need to define them there, and then in Unity, Unity will pick up on it and toggle which is true based on its target platform.

    ... but that's not how compiler directives work.

    They're called "compiler directives" because they direct the compiler as to what code should be compiled at compile time.

    Unity does not compile your dll.

    YOU compile your dll and then import it into Unity.

    ...

    You have 2 options here:

    1) import this library as actual *.cs files. Either as a unitypackage, or through the package manager (following the package manager formatting), or literally just copy them into a folder in your assets directory. Strip those defines from the top as unity defines them as necessary, and then unity will compile them for you, respecting the compiler directives.

    2) The 2nd option is much more complicated so I'm putting it in spoiler tags:
    Remove those defines from the top...
    Open up the configuration manager:
    upload_2022-11-7_18-19-8.png

    Under 'Active Solution Configuration' create new configurations for each target platform (editor, webgl, windows).

    Then go into your project properties and on the build tab:
    upload_2022-11-7_18-20-14.png

    Each of your target platforms will show in that configuration dropdown. For each one individually configure what compilation symbols should be active for each in that line that says "Conditional Compilation Symbols".

    NOTE - the names of these directives don't necessarily have to mirror the ones in unity because you're compiling them here. You can make them match for consistency sake, but it's not necessary!

    Finally build for EVERY target creating a new dll for each individual platform.

    Then when you copy them into your unity solution you'll need to go to each dll for each platform and select them:
    upload_2022-11-7_18-24-55.png

    And here you'll have to configure which dll is used for which platform. This example I show above shows a dll used for "any platform", you'll have to uncheck the "Any Platform" and then you can select which platforms to include.
     
    Bunny83 likes this.
  10. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    What would be the "configuration symbols" for like WebGL vs Windows, etc?
     
  11. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,104
    They are whatever you'd like them to be.

    If you put "DERP" in the configuration symbols.

    Then in your code you say:
    #if DERP
    //do stuff
    #endif

    Then the //dostuff will only be compiled when you've compiled for the configuration that includes DERP.

    Usually you select words that describe it well. That's why say for editor Unity uses UNITY_EDITOR. It's very self explanatory as to what it means.
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    29,825
  13. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    2,868
    I'm astounded OP has been banging their head against this for months now. They still haven't explained why they are doing things this way as well.
     
  14. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    14,962
    You don't need a DLL for this. It is making life harder for you. Just put your code in a normal Unity script.
     
    Bunny83 and spiney199 like this.
  15. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    2,435
    Exactly. Unity is your build tool that splits the output into the different supported target platforms. If you want to use pre-compiled code you have to pre-split it yourself. In such a case it makes no sense at all to put code like that into a seperate assembly.
     
  16. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    So I put "DERP" in VS Studio2019 like this

    Conditional-compilation-symbols.png

    in my editor-only code ( which i compiled into a DLL with "Editor" as the custom "Configuration" ),

    I put the following code

    Top of code

    Code (CSharp):
    1. #if UNITY_EDITOR
    2.     using UnityEditor;
    3. #endif
    4. #if DERP
    5.     using MyLib;
    6. #endif
    Update function
    Code (CSharp):
    1. public void Update ( ) {
    2.     if ( Input.GetKey ( KeyCode.Escape ) ) {
    3.         #if DERP
    4.             Debug.Log ( $"DERP!" );
    5.             MyEditor.KillApp ( killTimerSeconds );
    6.         #endif
    7.     }
    8. }
    and it compiles, but does nothing... What am I doing wrong here and how to fix?

    Thank you & HAPPY THANKSGIVING EVERYONE! <3
     
    Last edited: Nov 23, 2022
  17. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    2,868
    Using pre-compiled assemblies when you really don't need to.
     
  18. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    If you are not here to help, then please move on... I will do this the way I need to do it. I'm just trying to get something done.
     
    Last edited: Nov 23, 2022
  19. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    2,435
    Well, he just tried to help you, you just decided to ignore it. So that's not our problem. Do you understand what pre-processor tags are in code? They do not exist after compilation. They are processed before the compilation and essentially exclude certain parts of your code. So those tags inside the DLL have the exact same function as if you just delete everything between an #if and the corresponding #endif when the symbol you check for does not exist at compile time. Those symbols are not part of the compiled assembly in any shape or form. It's literally a pre processing step. You can really think of it like you send the source code of your DLL to a co worker and tell him which tags are defined and which are not. He then deletes all those #if - #endif constructs from the code as if they never existed. He then gives the now cleaned code back to you so you can compile your DLL. Again, the compiled DLL does not contain any kind of preprocessor tags of defines.

    Source code in a Unity project is compiled by the Unity editor itself. The Unity Editor also has a place where you can define custom define symbols for the code that is compiled by Unity. However imported assemblies which are already compiled have absolutely nothing to do with defines.

    I don't know how we can explain it any more clear. It was already stated that you overcomplicate the whole structure of your project.

    Just once more: a compiled DLL can not change its already compiled code based on some external symbols. It's already compiled. A DLL just is what it is.
     
    Kurt-Dekker likes this.
  20. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    2,868
    You've never told why you need to do it in this particular way. And...

    You've spent months on this and still don't understand the core principles being explained to you ad nauseum. Whatever reason you have, it's not worth it.

    All this hassle when it could just be one script in your project; you could have been done with this trivial task ages ago.
     
  21. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    and i am going to continue working on it until a straight explanation is given.
     
  22. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    29,825
    You can stop now then. The straight explanation has been given many times already, in this thread and others.

    Now it is time for you to cut up a few pieces of paper, call one the source code, one the predefines, one the compiler, and use them to make a DLL, which is a brand-new piece of paper.

    Now burn the source code paper, the predefines and the compiler.

    Keep only the DLL paper.

    Now go use the DLL.

    Note how there are NO predefines anywhere to be seen.

    Repeat this until you understand why the predefines don't work the way you want them to.
     
  23. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    I put "DERP" in "Conditional compilation symbols" in VS2019 for my Editor DLL. In the main.cs code for my game, I did this

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3. using MyLib;
    4. #if UNITY_EDITOR
    5.     using UnityEditor;
    6. #endif
    7. #if DERP
    8.     using MyEditor;
    9. #endif
    10. private void Update ( ) {
    11.     if ( Input.GetKey ( KeyCode.Escape ) ) {
    12.         #if DERP
    13.            MyEditor.KillApp ( killTimerSeconds );
    14.            Debug.Log ( $"DERP A!" );
    15.         #else
    16.            MyLib.KillApp ( killTimerSeconds );
    17.            Debug.Log ( $"DERP A1!" );
    18.         #endif
    19.     }
    20. }
    It kills the app in compiled mode and WebGL mode but does not kill the app when in Editor Play mode. I thought I was following the instructions here to a T.
     
  24. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    2,868
    Yes because you still don't understand. You need to compile multiple .dlls. One for shipping with the game, one to use when in the editor.
     
  25. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    @spiney199 right, so how do i do that? i thought that making an Editor DLL and a separate library DLL would work.
     
  26. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    2,868
  27. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
  28. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    2,868
  29. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    i read that, and here's my settings for the Editor DLL. DLL-Issue-2.png
     
  30. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    2,435
    But... your main.cs is a script file inside Unity, right? It also uses define symbols. Did you define any symbols in Unity? Because it does not matter what you set in Visual studio. Unity compiles scripts itself and has it's own compiler symbols. As it was mentioned countless of times, the compiled DLL does not contain or define any symbols itself. If you have code that checks if a certain symbol exists, this symbol has to be defined inside the compilation environment. For C# scripts inside Unity, that is the Unity editor itself. DLLs are precompiled. They are not changed or altered in any way, just loaded and referenced.

    You have two debug log statements in your code, which one does actually fire? If the wrong one fires, you haven't setup the define correctly inside Unity.
     
  31. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    @Bunny83 so do i just have to do #define DERP at the top of the script in main.cs in Unity?

    EDIT : I just put "DERP" into the define compilation symbols in Unity.
     
  32. Escharum

    Escharum

    Joined:
    Sep 2, 2021
    Posts:
    5
    Sounds like everyone's mind has been made up on this matter. Still, it's good to see people are still willing to help you with this needless overengineering. Is this the fabled mythiria, your pride and joy? I see some possible reasons here that you could be so hell-bent on doing it this way. It's hard to discern whether you won't speak on the matter out of some misplaced sense of secrecy or embarrassment, but here's some general advice nonetheless.
    1. The software needs to be portable between projects? C# source files + assembly definitions can be placed in the package formats supported by Unity, and provide a superset of functionality that built managed assemblies do. The code is just as portable shipped as source files as it is being a DLL, it's just a folder instead of a file.
    2. The compilation times in Unity are long? Tell me about it. There's supposed to be improvements happening in new versions, but it seems to be hit-and-miss whether the upgrades to the core platform actually improve times in production projects. Yes, iteration time is paramount for games development.
    3. Obfuscation for distribution? This is pretty much an anti-pattern which often gets in the way of using packages. Imagine a bug appears in a library which you don't have the sources for. The user has to go through the rigmarole of running the assembly through an IL decompiler and make a possibly very simple fix themselves to carry on with their development, or possibly have to put a number of things on hold for a week or longer waiting for a package publisher to update the package. Very inconvenient compared to having sources.
    4. Code specialization based on platform etc.? You should be aware by now, platform scripting defines are available for use in code anywhere you want. You can gate any special feature behind these symbols seamlessly (painlessly) when these are used in C# sources in Unity projects. Perhaps you want a library to be agnostic between Unity and some other platform using C#? That's fair, but again, you can use #define / #if compiler directives however you see fit in C# sources and still get the multi-ecosystem support you want. As long as the other platform features are put behind #if for symbols that are set on the other platform (or specify a common set there yourself which you know are always there), you can still use source files and have the benefits of complex, different code behavior on Unity Windows Standalone vs. Unity XBOX vs. Unity Editor vs. some external ecosystem.

    If you used your own symbols to specify how the editor and player versions of the assemblies would differ, ultimately you don't need to use that symbol in the C# code you use in Unity that interfaces with that library. Assuming that you did correctly set the symbols, as Bunny quite clearly said, you can just use #if UNITY_EDITOR (editor code) #else (player code) #endif. Using your own custom symbol to differentiate player and editor compilation could cause mistakes and are again unnecessary since Unity already has the vast majority of the symbols you would need.
     
  33. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    Right, I don't have to use the custom symbols. I just want to call my Editor function inside the DLL in main.cs using #if UNITY_EDITOR
     
  34. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    I would prefer simply using "#if UNITY_EDITOR" when calling an Editor only function from my Editor-only managed DLL in main.cs
     
  35. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    380
    Is that possible?