#概要
iOS向けに開発したSDKをUnityアプリに対応させる場合、プラグインを作ってSDKとUnityアプリの橋渡しをしてやる必要があります。本記事ではUnity側のコードをC#、プラグイン側のコードをObjective-C++ (.mm)で記載するケースについて紹介します。
#補足
iOS, Android共通で使用するコードについては共通編を参考にして下さい。
#プラグイン側
まずはプラグイン側のコードの一例です。Sample, SampleDelegateといったクラスはSDK側で定義されており、それらのメソッドにUnity側からアクセスするために各Wrapperメソッドを実装しています。このコードはUnityプロジェクトのAssets/Plugins/iOSディレクトリ配下に入れておくと良いでしょう。
SamplePlugin.mm
#include <stdio.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <SampleSDK/SampleSDK.h>
#import <SapleSDK/SampleSDK-Swift.h>
#define kSample_DefaultCallbackGameObjectName @"Main Camera"
@interface SamplePlugin: NSObject
@end
SamplePlugin *__unityClientSharedInstance;
@interface SamplePlugin() <SampleDelegate>
@property(nonatomic, strong) NSString *callbackGameObjectName;
- (void)invokeUnityGameObjectMethod:(NSString *)methodName message:(NSString *)message;
@end
@implementation SamplePlugin
+ (SamplePlugin *)sharedInstance {
if (!__unityClientSharedInstance) {
__unityClientSharedInstance = [[SamplePlugin alloc] init];
}
return __unityClientSharedInstance;
}
# pragma mark - SampleDelegate
- (void)didStatusChange:(enum SampleStatus)status {
NSString *statusStr = [NSString stringWithFormat:@"%ld", status];
[self invokeUnityGameObjectMethod:@"_Sample_didStatusChange" message:statusStr];
}
# pragma mark - Private
- (void)invokeUnityGameObjectMethod:(NSString *)methodName message:(NSString *)message {
NSString *gameObject = self.callbackGameObjectName == nil ?
kSample_DefaultCallbackGameObjectName : self.callbackGameObjectName;
const char *gameObjectStr = [gameObject cStringUsingEncoding:NSUTF8StringEncoding];
const char *methodNameStr = [methodName cStringUsingEncoding:NSUTF8StringEncoding];
const char *messageStr = [message cStringUsingEncoding:NSUTF8StringEncoding];
UnitySendMessage(gameObjectStr, methodNameStr, messageStr);
}
@end
// Declare each wrapper methods
extern "C" {
void SPStart(const char *sampleCode);
void SPDoSomething();
int SPGetStatus();
int SPGetScore();
bool SPIsAvailable();
const char* SPGetSomeText();
}
extern UIViewController* UnityGetGLViewController();
extern void UnitySendMessage(const char* obje, const char* method, const char* msg);
void SPSetCallbackGameObjectName(char *gameObjectName) {
NSString *name = [NSString stringWithCString:gameObjectName encoding:NSUTF8StringEncoding];
SamplePlugin *client = [SamplePlugin sharedInstance];
client.callbackGameObjectName = name;
}
void SPStart(const char *sampleCode) {
NSString *sampleCodeStr = [NSString stringWithCString:sampleCode encoding:NSUTF8StringEncoding];
[[Sample sharedInstance] startWithSampleCode: sampleCodeStr];
[Sample sharedInstance].delegate = [SamplePlugin sharedInstance];
}
void SPDoSomething() {
[[Sample sharedInstance] doSomething];
}
int SPGetStatus() {
return [[Sample sharedInstance] getStatus];
}
int SPGetScore() {
return [[Sample sharedInstance] getScore];
}
bool SPIsAvailable() {
return [[Sample sharedInstance] isAvailable];
}
const char* SPGetSomeText() {
NSString *textStr = [[Sample sharedInstance] getSomeText];
const char *textChar = [textStr cStringUsingEncoding:NSUTF8StringEncoding];
return textChar ? strdup(textChar) : NULL;
}
#Unity側
Sample_iOS.cs
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
#if UNITY_IOS
public class Sample_iOS : ISample {
private Sample sampleGameObject;
private SampleEventListener listener;
[DllImport ("__Internal")]
protected static extern void SPSetCallbackGameObjectName(string gameObjectName);
public Sample_iOS(Sample sampleParent) {
sampleGameObject = sampleParent;
if (sampleParent.iosAppCode != null) {
Start(null);
}
CreateListenerObject();
}
private void CreateListenerObject() {
listener = sampleGameObject.gameObject.AddComponent<SampleEventListener>();
listener.SetNativeParent(this);
SPSetCallbackGameObjectName(sampleGameObject.gameObject.name);
}
[DllImport("__Internal")]
private static extern void SPStart(string sampleCode);
public void Start(string sampleCode) {
if (sampleGameObject.iosSampleCode != null) {
SPStart(sampleGameObject.iosSampleCode);
} else if (sampleCode != null) {
SPStart(sampleCode);
}
}
[DllImport("__Internal")]
private static extern void SPDoSomething();
public void DoSomething() {
SPDoSomething();
}
[DllImport("__Internal")]
private static extern int SPGetStatus();
public SampleStatus GetStatus() {
return (SampleStatus)SPGetStatus();
}
[DllImport("__Internal")]
private static extern int SPGetScore();
public int GetScore() {
return SPGetScore();
}
[DllImport("__Internal")]
private static extern bool SPIsAvailable();
public bool IsAvailable() {
return SPIsAvailable();
}
[DllImport("__Internal")]
private static extern string SPGetSomeText();
public string GetSomeText() {
return SPGetSomeText();
}
}
#endif
#参考
https://docs.unity3d.com/ja/540/Manual/PluginsForIOS.html