Tasharen Entertainment Forum
Support => NGUI 3 Support => Topic started by: jwalker on May 08, 2012, 05:53:43 PM
-
Has anyone else tried using NGUI on a Unity project that puts scripts into pre-built assemblies? For scalability reasons we are building our game this way. See this video from Unite 11 for the full explanation of why this is a good idea and why more developers are starting to do this:
http://video.unity3d.com/video/3708530/unite-11-scaleable-game
We are having a problem with NGUI when using this approach. Since all of our game code resides in scripts that are compiled into pre-built assemblies, using NGUI requires putting all the NGUI code into a pre-built assembly as well and then referencing it from our assemblies. We have done this, but we run into problems with NGUI code that uses "#if UNITY_EDITOR" to do conditional compilation. Since the code is compiled externally (by Visual Studio in our case, but you can also do it with MonoDevelop), we have to compile the DLL with or without UNITY_EDITOR defined. We cannot compile a single DLL that has the option of running with or without this define. If we define UNITY_EDITOR during compilation, then everything works fine in the Editor but building a stand-alone player fails due to the calls to UnityEditor.dll which is not allowed. If we do NOT define UNITY_EDITOR then we end up with some missing/incorrect behavior of NGUI within the editor. I see two possible solutions to this problem:
1. Remove all "#if UNITY_EDITOR" from the NGUI code and use events/delegates to decouple the editor-specific stuff and place it in a separate assembly. There would be no calls to the UnityEditor.dll API within NGUI.dll at all. A separate NGUIEditor.dll would contain everything that is editor-specific. This would register to the events broadcasted by NGUI.dll and perform any editor-specific stuff at the right time. Since NGUIEditor.dll is not present in a stand-alone build, nothing would be listening to those events and no UnityEditor.dll calls would ever be made.
2. Maintain two different build configurations of NGUI.dll, one for the editor with UNITY_EDITOR defined, and one for stand-alone builds without UNITY_EDITOR defined. We would use the editor version of NGUI.dll until ready to do a stand-alone build, at which time we'd need to replace NGUI.dll in the Unity project's Assets/Assemblies folder with the stand-alone version. This option seems like the easiest solution for the short term since we don't have to modify any NGUI code, but it comes with the ongoing nuisance of maintaining different versions of NGUI.dll.
Before we go ahead with option 2, I wanted to see if anyone else using NGUI has had to deal with this, and if so, what they did. It's possible that we are the first ones to try using NGUI in this manner. Unity has some known issues with scripts in pre-built assemblies that call the Unity API in certain ways. Most things work fine but there are a few gotchas. It would be reassuring to know that the developers of NGUI are aware of this usage scenario and are testing that all aspects of NGUI work as designed when the NGUI code is compiled into pre-built assemblies. We (Idol Minds) have purchased a NGUI professional license, if that makes a difference.
Best regards,
Jeremy Walker, Senior Programmer
Idol Minds, LLC
-
I can tell you with a fair certainty that you won't have any easy way of doing this.
I ran into this same problem when creating a DLL for the free version, and there is simply no easy way around it. If you have two versions of NGUI in a DLL, then it means that you will have two sets of scripts. The two won't work together, and scripts attached using code from one DLL won't automatically update to scripts of another DLL when you replace it. You'll just end up with missing references.
The only way to keep references was to create "dummy classes" -- empty classes that derive from DLL-stored classes. These dummy classes were used instead when attaching scripts to objects.
Removing UNITY_EDITOR defines from NGUI will break a lot of its functionality -- from gizmos to performance optimizations to even basic highlighting of a widget on selection. NGUI Free users don't have widget selection for this very reason, for example.
And then there is the problem of getting updates... by changing the code so much and moving it into a DLL you're almost certainly going to have to go through hell when you want to update to the latest version.
There is simply no elegant way to solve this. Or even a decent way. Only the horribly hacky way.
The whole "scalable game" is only suitable if you're a hardcore dev who doesn't mind bypassing half of Unity's features. I know because I've tried following the same route in 2009.
-
Hi ArenMook,
Thanks for the info. Were you using the external source control feature of Unity that creates the .meta files? We have found that as long as the GUID inside the MyAssembly.dll.meta file remains the same, you can replace MyAssembly.dll with a different version and all the script references are preserved correctly. We are doing this with many of our own DLLs and it has worked no problem. Yes, we do fall into that category of a hardcore developer, but so far the scalable approach using pre-built assemblies hasn't caused us to lose any substantial features of Unity. It does present a few ongoing challenges that one must get familiar with, however.
It's possible that Unity has improved in this regard since 2009. Perhaps that's why it didn't work when you last attempted it? I will give option 2 a try today. If it does indeed work, then my only remaining concern is whether the NGUI developers are testing this usage scenario with their releases or not.
Jeremy
-
Yup, it works. I just have an "Editor" configuration of the NGUI.dll project in Visual Studio that defines UNITY_EDITOR. I can use this version of the DLL while working in the Editor, and then replace it with the "WindowsStandAlone" version of NGUI.dll before building the Windows Standalone Player, and it builds a working player.
Jeremy
-
Ah, curious. Thanks for letting me know. I assume this still won't work when going from a DLL solution to a code solution though, only DLL to DLL.
-
That's correct. You can only reference DLL scripts from other DLLs scripts, and you can only reference loose scripts in the Unity project from other loose scripts in the Unity project.
-
Howdy
My 2 cents about accessing NGUI from external DLLs.
I've come to a bit different solution:
1. Compile NGUI into DLL but only it's "realtime" part, that is folders: Interraction, Internal, Tweening, UI.
2. Left source files of "Editor" part right were they are in "Assets/NGUI/Scripts", the same with "Resources".
3. Delete every other NGUI source file from Unity, to avoid double references.
4. After succesfull build copy "ngui.dll" to Unity.
So right now I can access NGUI objects from my DLLs and (a bit of surprise) editor scripts are working fine with "realtime" NGUI in DLL.
Of course after such radical replacement of scripts with DLL, every already made gui hierarchy has lost references to scripts, but for me it was not problem to recreate it from scratch.
Regards,
RafaĆ Kamraj
Ten Square Games Sp. z o.o.
-
riffraff's approach seems interesting and I might end up going with that approach. If it is good, it would be great to have this officially supported.
I did an initial experiment using GetComponent(typeof(Component)) to get a UILabel, and then C# reflection to get the text property, and set it. Of course reflection slows things down but not a problem (yet) since I am just setting menu GUIs at the moment (it may be a bigger problem for in-game HUDs).
-
Another approach I have started trying lately is adding interfaces to the loose NGUI files, such as IUILabel. The interface is defined in a custom DLLs which Unity picks up as a DLL reference for loose script files. In my own code in a separate DLL, I can then use var label = GetComponent(typeof(IUILabel)) and call label.text = "123";. Perhaps another option for Aren (or others) to consider is to create an interface DLL. I only need to set a few properties so it is not a big deal to make the interfaces myself but if this is a good approach for interop with DLLs it might be nice to just do all the interfaces once and for all.
-
Inspired by an entry in another forum I successfully tried a different approach. All my own scripts are developed with visual studio using a couple of projects. So only the tools like NGUI reside as loose scripts in unity.
Unity compiles these scripts into the Assembly-CSharp-dll which you can find in the
<root>\Temp\StagingArea\assets\bin\Data\Managed directory.
In my VS projects I reference this Assenbly-CSharp dll and so I have access to all NGUI classes.
Until now this works fine.
Regards
Christof