New and improved answer:
I finally figured out a better solution for this….
only TWO assemblies (DLL’s) are created, one to run in the player, one to run in the editor.
In the assembly that will run in the player, we define inside our class, a (few) public static delegate.
using UniyEngine;
/// <summary>
/// This class allows player dlls to compile in the player (where UnityEditor.dll may not be referenced) while accessing certain Editor-only Functions.
/// When NOT being run in the editor these functions will immidiately return with a default value.
/// But if running in the Editor, they will invoke the approate Editor-only function.
/// </summary>
static public class EditorAdapterFunctions
{
public delegate void DoSomethingReturnNothingDelegate();
public delegate string GetStringUsingObjectDelegate(Object o);
static public DoSomethingReturnNothingDelegate EditorRepaintAllViews = null;
static void RepaintAllViews()
{
if (EditorRepaintAllViews != null)
EditorRepaintAllViews();
}
static public GetStringUsingObjectDelegate GetAssetPathEditor = null;
static string GetAssetPath(Object obj)
{
if (GetAssetPathEditor != null)
return GetAssetPathEditor(obj);
return "";
}
static public DoSomethingReturnNothingDelegate RefreshHierarchyEditor = null;
static public void RefreshHierarchy()
{
if (RefreshHierarchyEditor != null)
RefreshHierarchyEditor();
}
}
These funtions will obviously invoke NOTHING, unless we do something else.
So next we define an EDITOR based class, that will be included in the Editor (only) dll.
using UnityEditor;
public class EditorAdapterFunctionsEditorComponent
{
[InitializeOnLoadMethod]
static private void Init()
{
EditorAdapterFunctions.EditorRepaintAllViews = UnityEditorInternal.InternalEditorUtility.RepaintAllViews;
EditorAdapterFunctions.GetAssetPathEditor = AssetDatabase.GetAssetPath;
EditorAdapterFunctions.RefreshHierarchyEditor = RefreshHierarchy;
}
static public void RefreshHierarchy()
{
EditorApplication.DirtyHierarchyWindowSorting();
EditorApplication.RepaintHierarchyWindow();
}
}
Now, when the Editor is loaded, this class simply assigns the Editor only functions to the delegates in our Non-editor class.
RESULT:
When the Editor DLL’s are NOT in use (like when building the final project), the delegate remains null, and the function is not invoked.
When the Editor DLL’s ARE in use, the editor function gets invoked via the assigned delegate.
OLD ANSWER:
Here is one non-ideal workaround I came up with.
Define the class(es) TWICE; once for the editor dll, and once for the non-editor dll. (So, both DLL project’s will have a reference to the same file)
I mentioned this in the OP. But, to avoid compilation errors, we define each version of the class in different namespaces, using the compile-time pragma.
(DLL code)
#if UNITY_EDITOR
namespace UnityExtensionsEditor //the editor version DLL will compile this
#else
namespace UnityExtensions //the non-editor version DLL will compile this
#endif
class GameObjectExtensions....
Now, in the using-project, the user can simply specify:
(using-project code)
#if UNITY_EDITOR
using UnityEditor;
using UnityExtensionsEditor //the editor version of the project will compile this
#else
using UnityExtensions //the non-editor version of the project will compile this
#endif
This way, the appropriate GameObjectExtensions class (either UnityExtensionsEditor.GameObjectExtensions
or UnityExtensions.GameObjectExtensions
) will be used in the compiled (using-project) code.
I feel like the fact that I’m defining the same class name(s) in two different namespaces, is going to cause problems. Is it acceptable in this case?
Note: Using the (DLL code) above directly in a unity project will lead to errors unless a copy (yuk) of the file is put in the unity project’s editor folder.
Also worth noting is that BOTH DLL’s will need to go in a non-editor folder of the using-project.