Slide 1

Slide 1 text

製作 Unity Plugin for iOS Johnny Sung 2014.09.11 @ CocoaHeads Taipei

Slide 2

Slide 2 text

https://fb.com/j796160836 Johnny Sung Mobile devices Developer https://plus.google.com/+JohnnySung http://about.me/j796160836

Slide 3

Slide 3 text

我是不是來錯場合了? 這裡是CocoaHeads...

Slide 4

Slide 4 text

Unity的概念 • GameObject • Component

Slide 5

Slide 5 text

GameObject GameObject

Slide 6

Slide 6 text

GameObject Component

Slide 7

Slide 7 text

⼀一個空⽩白的 Component ⻑⾧長這樣 using UnityEngine;
 using System.Collections;
 
 public class testComponent : MonoBehaviour {
 
 // Use this for initialization
 void Start () {
 
 }
 
 // Update is called once per frame
 void Update () {
 
 }
 }

Slide 8

Slide 8 text

MonoBehaviour 的⽣生命週期 • Awake() 創造時初始化 • Start() 執⾏行時初始化 • Update() 繪圖迴圈 (依效能⽽而定,例60fps) • FixedUpdate() 物理迴圈

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

http://docs.unity3d.com/ScriptReference/

Slide 11

Slide 11 text

說好的 iOS Plugin 呢?

Slide 12

Slide 12 text

Unity Plugin 的呼叫⽅方式 C# (呼叫的接⼝口) C
 (⾃自定義的接⼝口) Objective-C Objective-C
 UnitySendMessage() C#
 (對應的接⼝口) (Unity Engine) (Native)

Slide 13

Slide 13 text

! #import #import ! extern UIViewController* UnityGetGLViewController(); extern "C" void UnitySendMessage(const char*, const char*, const char*); ! @interface MyViewPlugin : NSObject @property (nonatomic, strong) UIView* myView; @property (nonatomic, strong) NSString* gameObjectName; @end MyViewPlugin.mm Get Started !

Slide 14

Slide 14 text

! @implementation MyViewPlugin ! - (id)initWithGameObjectName:(const char*)gameObjectName_ { self = [super init]; UIView* view = UnityGetGLViewController().view; self.myView = [[UIView alloc] initWithFrame:view.frame]; self.myView.backgroundColor = [UIColor blueColor]; [view addSubview:self.myView]; self.gameObjectName = [NSString stringWithUTF8String:gameObjectName_]; return self; } ! - (void)dealloc { [self.myView removeFromSuperview]; } ! @end ! ! MyViewPlugin.mm 就只是⼀一個藍⾊色的View ( ˊ_>ˋ )

Slide 15

Slide 15 text

⾃自訂 C語⾔言 接⼝口 ! extern "C" { void* _MyViewPlugin_Init(const char* gameObjectName); void _MyViewPlugin_Destroy(void* instance); } ! void* _MyViewPlugin_Init(const char* gameObjectName) { id instance = [[MyViewPlugin alloc] initWithGameObjectName:gameObjectName]; return (__bridge void*)instance; } ! void _MyViewPlugin_Destroy(void* instance) { MyViewPlugin* myViewPlugin = (__bridge MyViewPlugin*)instance; myViewPlugin = nil; } MyViewPlugin.mm

Slide 16

Slide 16 text

跟Unity相連接!

Slide 17

Slide 17 text

! public class MyViewObject : MonoBehaviour
 {
 IntPtr myView;
 
 #if UNITY_IPHONE
 [DllImport("__Internal")]
 private static extern IntPtr _MyViewPlugin_Init(string gameObject);
 [DllImport("__Internal")]
 private static extern int _MyViewPlugin_Destroy(IntPtr instance);
 #endif
 
 public void Init()
 {
 #if UNITY_IPHONE
 myView = _MyViewPlugin_Init(name);
 #endif
 }
 
 void OnDestroy()
 {
 #if UNITY_IPHONE
 if (myView == IntPtr.Zero)
 return;
 _MyViewPlugin_Destroy(myView);
 #endif
 }
 } MyViewObject.cs C#對應的接⼝口

Slide 18

Slide 18 text

! public class SampleMyView : MonoBehaviour
 {
 MyViewObject myViewObject;
 
 void Start()
 {
 myViewObject =
 (new GameObject("MyViewObject")).AddComponent();
 myViewObject.Init();
 }
 } SampleMyView.cs 配合⽣生命週期 並使⽤用之 建⽴立⼀一個GameObject 增加⼀一個MyViewObject這個Component

Slide 19

Slide 19 text

從 Unity 呼叫 Obj-C ⽅方法 C# 傳送 Objective-C 接收 MyViewObject.cs MyViewPlugin.mm C 宣告 ! [DllImport("__Internal")]
 private static extern int _MyViewPlugin_Destroy(IntPtr instance); extern "C" { void _MyViewPlugin_Destroy(void* instance); } C# 宣告 _MyViewPlugin_Destroy(myView);
 void _MyViewPlugin_Destroy(void* instance) { ! } MyViewObject.cs MyViewPlugin.mm

Slide 20

Slide 20 text

從Obj-C 回傳 Unity 資料 UnitySendMessage([self.gameObjectName UTF8String], "CallFromObjC", [@"Hello" UTF8String]); public void CallFromObjC(string message)
 {
 Debug.Log (message);
 } C# 接收 Objective-C 傳送 extern "C" void UnitySendMessage(const char*, const char*, const char*); MyViewObject.cs MyViewPlugin.mm C 宣告

Slide 21

Slide 21 text

從Obj-C 回傳 Unity 資料 UnitySendMessage(const char*, const char*, const char*); GameObject Name Method Name Parameter

Slide 22

Slide 22 text

打包執⾏行

Slide 23

Slide 23 text

打包Obj-C進Unity (1/2) • 路徑設定 (需⾃自⾏行開⽴立資料夾) • Assets/Plugins/iOS • 放⼊入Obj-C的程式碼 • .mm • .a • Unity編譯! (產⽣生xcode專案)

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

打包Obj-C進Unity (2/2) • 加⼊入所需的Framework • 調整Complier Flags ( -fobjc-arc ) • 依需求調整所需的設定 • Framework Search Paths • Other Linker Flags • Info-plist • xcode專案編譯

Slide 27

Slide 27 text

調整Complier Flags

Slide 28

Slide 28 text

放上 Asset Store 賺外快!

Slide 29

Slide 29 text

Demo Project https://github.com/j796160836/Unity-iOSPlugins

Slide 30

Slide 30 text

Q & A

Slide 31

Slide 31 text

Great References • Unity Webview • https://github.com/gree/unity-webview • Building Plugins for iOS • http://docs.unity3d.com/Manual/PluginsForIOS.html • Plugins (Pro/Mobile-Only Feature) • http://docs.unity3d.com/Manual/Plugins.html • 懂點Unity Plugin,替荷包省點錢!(iOS篇) • http://www.unityin.com/2013/05/%E6%87%82%E9%BB%9Eunity-plugin%EF %BC%8C%E6%9B%BF%E8%8D%B7%E5%8C%85%E7%9C%81%E9%BB %9E%E9%8C%A2%EF%BC%81ios%E7%AF%87/

Slide 32

Slide 32 text

Thanks !

Slide 33

Slide 33 text

補充:Unity 畫⾯面的按鈕 public class buttonUI : MonoBehaviour {
 
 void OnGUI ()
 {
 if (GUI.Button (new Rect (20, 10, 100, 40), "ButtonText")) {
 Debug.Log("Clicked!");
 }
 }
 }

Slide 34

Slide 34 text

補充:MonoBehaviour 的⽣生命週期 • Awake():⽤用於在游戲開始之前初始化變量或游戲狀態,在程式整個⽣生命周期內僅被執⾏行⼀一次。Awake 在所有GameObject初始化之後執⾏行,因此可以在⽅方法中安全地與GameObject進⾏行通信。 • Start():僅在所有程式的Update⽅方法第⼀一次被呼叫前執⾏行,且僅在程式實例被啟⽤用時執⾏行。Start在所 有程式的Awake⽅方法全部執⾏行完成後才執⾏行。 • Update():在每次渲染新的⼀一個Frame時執⾏行。由於該⽅方法呼叫的頻率與設備性能、被渲染對象有關, 導致同⼀一游戲在不同機器的效果不⼀一致(因為Update⽅方法的執⾏行時間間隔不⼀一致)。 • FixedUpdate():在固定的時間間隔執⾏行,不受游戲幀率(FPS)的影響。所以處理RigidBody時最好⽤用 FixedUpdate。FixedUpdate的時間間隔可在⼯工程設置中更改(Edit --> Project Setting --> Time)。 • LateUpdate():所有程式的Update⽅方法呼叫後執⾏行。例如相機跟隨即是在LateUpdate⽅方法中實現。 • OnGUI():在渲染和處理GUI事件時執⾏行。 • Reset():⽤用⼾戶點擊屬性監視⾯面板(Inspector)的Reset按鈕或⾸首次添加該組件時執⾏行,僅在編輯模式下執 ⾏行。 • OnDestroy():當GameObject將被銷毀時執⾏行。 http://www.cnblogs.com/lunarfire/p/3494716.html

Slide 35

Slide 35 text

補充:有關const char * const char * const myString; 指標所指向的記憶體位置 指向記憶體位置的內容

Slide 36

Slide 36 text

補充:有關const char * • char * myString; • 都可以改 • const char * myString; ( 或 char const * myString; ) • 字串內容不能動,但指向的位址可以改 • char * const myString; • 指的位址不能動,但是位址裡的字串可以改 • const char * const myString; • 都不能改 http://www.programmer-club.com.tw/ShowSameTitleN/c/37760.html

Slide 37

Slide 37 text

void * 與 id • void * • a reference to some random chunk o' memory with untyped/ unknown contents • ⼀一個任意指標,可⽤用來指向任何型別或內容的
 記憶體區塊 • id • a reference to some random Objective-C object of unknown class • ⼀一個任意指標,可以指向 Obj-C 中的物件 http://justlink-linus.blogspot.tw/2012/11/id-void-void-pointer.html http://stackoverflow.com/questions/1304176/objective-c-difference-between-id-and-void

Slide 38

Slide 38 text

補充:Assets資料夾保留字 • Standard Assets • Editor • Plugins • Plugins/x86 • Plugins/Android • Plugins/iOS • Resources http://wiki.unity3d.com/index.php/Special_Folder_Names_in_your_Assets_Folder

Slide 39

Slide 39 text

Unity 應⽤用領域 https://www.facebook.com/groups/581769871867384 想做遊戲?