Sunday, 15 August 2010

objective c - How to build Unity3d Plugin for iOS -



objective c - How to build Unity3d Plugin for iOS -

i have tiny objective-c library built ios , want export unity. understand basic process of writing csharp wrapper marshals invocations native library, have no thought start. please explain step-by-step how create unity bundle library distribute other developers.

unity3d documentation pretty brief , not explain anything.

thanks.

okay, after playing few days unity3d on mac figured out. code in guide dummy. have written stuff in 15 minutes or so, don't bothered mistakes , typos.

1) open unity, create new project (file -> new project) , save somewhere

2) when project generated has next structure:

projectname/assets (that's need) projectname/library (nevermind what's there) projectname/projectsettings (you don't care it) projectname/projectname.sln (monodevelop project)

3) go projectname/assets , create next folders: plugins/ios, in end you'll have folder construction this: projectname/assets/plugins/ios

4) set compiled library (.a) file , necessary headers within of projectname/assets/plugins/ios or re-create source code of library there (.mm, .h, .m, etc..). remember, can access c-functions c#, you'll have wrap objective-c stuff in c-code somehow, in case objective-c objects implemented in form of singleton wasn't hard create c-style wrapper around, instance:

cwrapper.h:

extern "c" void mysdkfoobarcfunction();

cwrapper.mm

#import "cwrapper.h" #import "myobjectiveclibrary.h" // actual ios library header void mysdkfoobarcfunction() { [myobjectiveclibrary dosomestuff]; }

5) go projectname/assets , create folder csharp wrapper class(es), phone call whatever want, example: projectname/assets/mysdk

6) within of mysdk folder create mysdk.cs file, dummy illustration of c# wrapper this:

using unityengine; using system; using system.runtime.interopservices; public class mysdk { // import single c-function our plugin [dllimport ("__internal")] private static extern void mysdkfoobarcfunction(); // wrap imported c-function c# method public static void foobarcfunction() { // won't work in editor, don't run there if(application.platform != runtimeplatform.osxeditor) { mysdkfoobarcfunction(); } } }

7) create shell script pack stuff .unitypackage , set next project folder (not inside). adjust export_path , project_path variables in script needs.

#!/bin/sh workdir="$( cd "$( dirname "${bash_source[0]}" )" && pwd )" unity_bin="/applications/unity/unity.app/contents/macos/unity" export_path="${workdir}/projectname.unitypackage" project_path="${workdir}/projectname" assets_path="assets" $unity_bin -batchmode -quit \ -logfile export.log \ -projectpath $project_path \ -exportpackage $assets_path $export_path

8) run created bash script bundle build. stuff assets included in xcode project unity project when generate via file -> build settings in unity editor. can utilize generated bundle distribute code other developers can include library unity projects double clicking on bundle file.

don't forget shutdown unity editor when run script, otherwise may fail build package.

if have issues , bundle not show up, script prints log export.log

next steps create sense if want create demo unity project library (good testing @ least)

9) can set created unity project (projectname.unity) assets/mysdkdemo have demo within of package.

10) create simple script demo unity3d scene @ assets/mysdkdemo/mysdkdemo.cs, example:

using unityengine; using system; using system.collections; public class mysdkdemo : monobehaviour { private guistyle labelstyle = new guistyle(); private float centerx = screen.width / 2; // utilize initialization void start () { labelstyle.fontsize = 24; labelstyle.normal.textcolor = color.black; labelstyle.alignment = textanchor.middlecenter; } void ongui () { gui.label(new rect(centerx - 200, 20, 400, 35), "mysdk demo", labelstyle); if (gui.button(new rect(centerx - 75, 80, 150, 35), "dostuff")) { mysdk.foobarcfunction(); } } }

11) go unity editor. find "main camera" in left sidebar in unity editor, select , in bottom of inspector panel (right sidebar) click on addcomponent, select scripts -> mysdkdemo script

12) build xcode project , run on device.

few notes

1) plugins don't work in unity editor, because they're not compiled in real-time, well, not sure until utilize c# in plugins, c# stuff gets linked immidiately , works in editor environment.

2) post not cover marshaling, or data/memory management between native <-> managed code, documented.

interop native libraries @ mono project

3) callbacks c# c can passed using c# delegates, on c-side utilize standard functions declarations, on c# side declare delegates same signature. seems booleans, integers , strings (c: char*) marshalled flawlessly (i don't talk memory management policy , who's responsible release memory or homecoming value policies).

however not work on ios builds out-of-box due platform limitations, c#-to-c callbacks still can implemented using monopinvokecallbackattribute, useful links on topic:

reverse callbacks @ xamarin docs monopinvokecallbackattribute illustration @ xamarin forums

actually in unity 4 there's aot.monopinvokecallbackattribute implemented, it's limited static delegates can passed unmanaged code, still improve nothing.

4) there's way unity rootviewcontroller using unitygetglviewcontroller function. declare function in implementation file, i.e.:

extern uiviewcontroller *unitygetglviewcontroller();

and utilize unitygetglviewcontroller() whenever need access rootviewcontroller.

5) there's much more magic , ugly stuff in details, maintain c interfaces simple possible otherwise marshalling can become nightmare , maintain in mind managed-to-unmanaged expensive.

6) utilize frameworks in native code , don't want linker problems. example, if utilize keychain in library need include security.framework xcode project.

i suggest give seek xuporter, helps unity integrate additional dependencies xcode project.

good luck!

ios objective-c unity3d

No comments:

Post a Comment