vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

【Unity5】【iOS】UnityのView上にUIViewを出したり消したり

諸事情から、Unityの画面上にUIView(UIImageView)を出してみる実験をしてみました。

ちなみにタイトルにわざわざUnity5と付けているのは、無料ユーザーでもiOSプラグインが使えるからですw 確認はしていませんが、おそらく4系でも動くと思います。

やったこと

  • Unity上のOpenボタンを押すと、画面上部に画像を表示する。
  • Closeボタンを押すと画像を非表示にする。
  • 表示する画像はiOS用のプラグインを作成して、UIImageViewを画面に追加することで実現する

Unityプロジェクトの作成

とりあえず画像を表示するためのGUIボタンを作成し、ついでにScene上にCubeを追加しておきます。

なお、今回Cubeは特に使用しないため、追加しなくても良いです。

CtrlUnityView.cs

using UnityEngine;
using System.Collections;

public class CtrlUnityView : MonoBehaviour
{
    void Start()
    {
        // プラグインを初期化.
        CtrlPlugins.Init();
    }
    void OnGUI()
    {
        if(GUI.Button(new Rect(50f, 400f, 100f, 100f), "Open 0"))
        {
            CtrlPlugins.Open(0);
        }
        if(GUI.Button(new Rect(200f, 400f, 100f, 100f), "Open 1"))
        {
            CtrlPlugins.Open(1);
        }
        if(GUI.Button(new Rect(50f, 600f, 100f, 100f), "Close"))
        {
            CtrlPlugins.Close();
        }
    }
}
  • 「CtrlPlugins.〜」の部分からプラグインを呼び出します。

プラグインを呼び出す

プラグインにアクセスするコードを、Unity側、iOS側でそれぞれ作成して連携する、という流れになります。

Unity側

Assets > Pluginsに、以下のようなコードを追加します。

CtrlPlugins.cs

using UnityEngine;
using System.Runtime.InteropServices;

public class CtrlPlugins : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void init_();
    [DllImport("__Internal")]
    private static extern void open_(int intImageNum);
    [DllImport("__Internal")]
    private static extern void close_();

    public static void Init()
    {
        init_();
    }
    public static void Open(int intImageNum)
    {
        open_(intImageNum);
    }
    public static void Close()
    {
        close_();
    }
}
  • 「private static extern void init_()」の部分はiOS側のメソッド名を指定します。

で、Unity側からは「public static void Init()」にアクセスしてプラグインメソッドを実行する感じです。

iOS

Assets > Plugins > iOSに、以下のようなコードを追加します。

PluginConnector.mm

#import "ViewController.h"

extern "C"{
  ViewController *vwcView;

  void init_()
  {
    vwcView = [[ViewController alloc] init];
    [vwcView initImageView];
  }
  void open_(int intImageNum)
  {
    [vwcView addImageView: intImageNum];
  }
  void close_()
  {
    [vwcView removeImageView];
  }
}
  • Cのコードと、Objective-Cのコードを使用するため、ファイルの拡張子は.mmにしておく必要があります。
  • このコードはUnityでビルドしてXcodeで開くと、Libraries > Plugins > iOSの中に配置されます。
    なおXcodeで内容を変更しても問題ありませんが、Unityでビルドするたびに元に戻るため、保存しておきたい内容はUnity側で変更したほうが良いです。

以上でUnityEditorを使って行う作業は終了です。

BuildSettingsからPlatformをiOSに変更してビルドします。

Xcode上でコードを追加

ビルドが終わったら、実際にView上に画像を追加・削除するViewController.h / ViewController.mを作成します。

ViewController.h

@interface ViewController: NSObject
- (void) initImageView;
- (void) addImageView: (NSInteger)intImageNum;
- (void) removeImageView;
@end

ViewController.m

#import "ViewController.h"

@interface ViewController()
@property (strong, nonatomic)UIViewController *vwcUnityView;
@property (strong, nonatomic)NSArray *aryImage;
@property (strong, nonatomic)UIImageView *imvImageView;
@end
@implementation ViewController
- (void) initImageView
{
    // 画像を配列に追加する.
    UIImage *imgBeer = [UIImage imageNamed:@"beer.png"];
    UIImage *imgTrain = [UIImage imageNamed:@"train.png"];
    _aryImage = [NSArray arrayWithObjects:imgBeer, imgTrain, nil];
}
- (void) addImageView: (NSInteger)intImageNum
{
    // 前に追加したViewを削除する.
    [self removeImageView];
        // 追加するImageViewの設定.
    _imvImageView = [[UIImageView alloc] initWithImage:(UIImage *)[_aryImage objectAtIndex:intImageNum]];
    _imvImageView.frame = CGRectMake(50, 10, 150, 150);

    // UnityのViewを取得して、SubViewとして追加する.
    _vwcUnityView = UnityGetGLViewController();
    [_vwcUnityView.view addSubview:_imvImageView];
}
- (void) removeImageView
{
    // UnityのViewから
    [_imvImageView removeFromSuperview];
}
@end

コメントの通りなのですが、注目すべきところは「UnityGetGLViewController()」で、これがUnityアプリで表示されるViewなのですね。

これに対してSubViewを追加・削除することで項目の表示・非表示ができると。

今回はUnityのView上にXcodeでViewを追加しましたが、逆にUIView上にUnityのViewを表示するのも試してみたいところです。

参考