Search Unity

build unity game from external app

Discussion in 'Scripting' started by chubbspet, Jun 13, 2011.

  1. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Hi there guys

    Is it possible to build and launch a unity 3d scene from a 3d party (calling) app without the user actually having unity installed on his computer? I have been looking at the command line arguments documentation, but I'm not sure if that can do what I need. Is there some "builder" app that I can call from a batch file? Btw, this is only for standalone and not web.

    Any help will be welcome

    Thanks
     
  2. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    In C# you can use the Process class to launch the app if you know the File path. So launching isn't too tough, although if you want to build from source assets they HAVE to have Unity installed (although it can be done through a batch file/php script). Well, in theory you could figure out how to do it but it'd be more work than it'd be worth it to try to build without Unity.
     
  3. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Thanks Ntero. The problem I'm sitting with is that I can't build my app before hand as the user is going to edit a "formulas" script, then only build the project through my 3rd party app. The process must be like this;

    User open 3rd party c# editor app. He do some coding and click on a launch button. When he click on this launch button the code he typed gets parsed to c# file in my Plugins directory (that part is done), and then the Unity3D app must automatically be built and launched.

    any ideas?
     
  4. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    C# has the ability to load external assemblies while running.

    This means that you can give them a base framework and API and have them write and compile their own mini-dll and import into the game after it's running. He won't be able to create MonoBehaviours (most likely). But if you provide him with a class that plugs into a MonoBehaviour that he can inherit from he could create those and add them in.

    In short to extend the code he doesn't need to rebuild the app, but rather you can make a simple C# compiler batch script and create a DLL in a special folder that will always be loaded on your apps startup.

    Hopefully http://www.java2s.com/Tutorial/CSharp/0240__Assembly/0080__Assembly-Load.htm Can get you started as well as a Google search for "C# loading external assembly" gives some good tips.

    Another addition: If it's a single template script you can still compile it separately and the process would be:
    He edits the Script and hits Run, it will take his C# script and compile it into an assembly
    http://msdn.microsoft.com/en-us/library/ms379563(v=vs.80).aspx has some command line functions.

    Then the Batch script will execute the Unity App, and the Unity App will look for a .dll in a special folder of you choosing (where you compiled the dll previously). It will load that .dll in and look for a specific Type, and instantiate it. http://msdn.microsoft.com/en-us/library/system.reflection.assembly.aspx
    Assembly.CreateInstance() creates object by name.

    Once it's loaded you can call it's functions and check it's variables as you normally would. Or via reflection if you don't have an interface in your Unity build to base it off of.
     
    Last edited: Jun 13, 2011
  5. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Thanks for this Ntero

    i just scanned through your thorough explanation and I get mostly what you said. I will have a look at those links just now.

    Thanks again...
     
  6. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Ntero

    Just to clarify what you mean by the above, here is a working example of what my users will be creating. it is actually JUST the part inside the method, the rest of the class is a template that gets created for them. Does the MonoBehaviour part in your quote mean I won't be able to do this?

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class mainLoop: MonoBehaviour
    4. {
    5. public static void calcPos()
    6. {
    7. obBehaviour temp0 = GameObject.Find("block1").GetComponent<obBehaviour>();
    8. obBehaviour temp3 = GameObject.Find("ball1").GetComponent<obBehaviour>();
    9. temp0.M=5;
    10. temp0.U=temp0.U+temp0.A*Time.deltaTime;
    11. temp0.A=userControls.userVector3["F"]/temp0.M;
    12. temp0.P=temp0.P+temp0.U*Time.deltaTime;
    13. temp3.P=userControls.userVector3["F"];
    14. }
    15. }
    Thanks for the help
     
  7. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    It seams to me that my challange is going to be to add monobehaviour to my assembly file - I hope I'm saying that right...

    Anyone has some ideas?
     
  8. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
  9. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    But you don't need to add a MonoBehaviour.

    You can make a MonoBehaviour that contains your external script and interacts with it.

    i.e. obBehaviour has 1 field and it's BaseExternalClass. Then you have it read BaseExternalClasses variables, and call it's functions, and the user will inherit from BaseExternalClass and override it's functions to be able to implement it's own custom behaviour. Ideally you can use Properties instead of fields so that they can be more easily overridden.

    This way the MonoBehaviour acts more as a container and controller for the calss they are creating that contains the actual mechanics/logic.

    Edit: You may be able to load MonoBehaviours still, but it's much more sketchy, Unity requires specific namespaces and linkages that could be overly arduous to implement, whereas making a Base class that is contained within a MonoBehaviour would be much easier/portable/extendable while still being controlled by you as to what can and can't be done.
     
  10. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    ok, i see what you are getting at - will try this and give some feedback for other users.
     
  11. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    i'm still not winning with this...

    my new problem is that mcs wont compile my dll saying that generis is not supprted and I should try gmcs. When I try that compiler I get a very unhelpfull arror illegal enum value 2051, whatever that might be.
     
  12. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
  13. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    Sorry I didn't get back to you in a while, but I posted a reply on messages. Lemme know if it helps.
     
  14. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    Forget that, the messages system is confusing me so I'll just post it here in case it didn't really send:

    Hey,
    I'm not too familiar with GMCS command line compiling, but this page says there is a reference Assembly command: http://manpages.unixforum.co.uk/man-pages/linux/suse-linux-10.1/1/gmcs-man-page.html

    look up -r and -L in that link.

    Then what you can do is include an Interface or an Abstract base class with Unity in a custom namespace, something like this:

    in Unity
    Code (csharp):
    1.  
    2. namespace MyNameSpace
    3. {
    4. public interface IMyClass
    5. {
    6. bool MyValue
    7. {get; private set};
    8. }
    9. }
    10.  
    And then in your script, you do this
    Code (csharp):
    1.  
    2. using MyNameSpace;
    3.  
    4. public class MyClass : IMyClass
    5. {
    6. public bool MyValue
    7. {
    8. get
    9. {
    10. return true;
    11. }
    12. private set
    13. {
    14.  
    15. }
    16.  
    17. }
    18.  
    Now when compiling this new Script you need to A, Compile as an Assembly, and B be sure to include the assembly located at [UnityProjectFolder]/Library/ScriptAssemblies/Assembly-CSharp.dll if using C#, unsure what the Boo/JS Script assemblies are called. This Assembly inclusion will allow you to use the Interface defined in Unity, or inherit from some class built in to the game.

    Then your MonoBehavior will contain an IMyClass object and you can access myValue from the compiled class.

    Make sure the new Class that is created, is public, and then you can do this:

    e.g.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MyMonoBehaviour: MonoBehaviour
    6. {
    7. IMyClass myClass;
    8.  
    9. Awake()
    10. {
    11. Assembly myAssembly = Assembly.Load(File.ReadAllBytes(myDLLLocation));
    12.         System.Type[] myTypes = myAssembly.GetExportedTypes();
    13.         for(int i = 0; i < myTypes.Length; i++)
    14.         {
    15.             if(myTypes[i].GetInterface("IMyClass") != null)
    16.             {
    17.                 myClass = myAssembly.CreateInstance(myTypes[i].FullName) as IMyClass;
    18. Debug.Log(myClass.MyValue);
    19.             }
    20.         }
    21. }
    22. }
    23.  
    Basically you get all publicly visible types and then instantiate the one you want. This works in MonoDevelop, so as long as you can get the proper linking (extension references the game assembly to get an interface, then the game loads the extension dll to load the inheritted type) it should be functional. It will avoid the need for shared types or any duplicates types in each assembly. It's been a while and I only did some rudimentary tests to double check it works, so let me know if there is anything that doesn't work with that (outside the command line compiler stuff, of which I probably won't be much help).

    Edit: The path listed for the assembly is going to have to work for both Editor, which I listed and Deployed, which is under the same name, but in a different folder relative to the .exe
     
    Last edited: Jun 18, 2011