渋谷ほととぎす通信

エンジニア社長によるUnityとAIのブログ & エンジニアの生存戦略

【Unity】C#からObjective-Cにアクセスする方法

【Unity】C#からObjective-Cにアクセスする方法

こんにちは、Unityエンジニアのオオバです。

お悩みさん
お悩みさん
  • UnityでC#からObjective-Cにアクセスできる?
  • iOSの機能にUnityからアクセスしたい
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    Unityでゲームを作っているとiOSが提供する機能にピンポイントでアクセスしたくなるときがあります。

    UnityがAPIとして提供してくれているなら何も問題は起きませんが、提供していない場合は 自分でネイティブプラグインを開発 する必要があります。

    本記事ではネイティブプラグイン開発初心者向けにUnity(C#)からiOSのAPIにアクセスする方法を紹介していきます。

    ネイティブプラグイン開発を始めてみたいという方はぜひ読んでみてください。

    本記事はiOS向けということでMac環境が必要なので注意です。Windows環境×C++でネイティブプラグインを始めてみたい方はこちらの記事を参考にしてみてください。

    👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

    C#(Unity)からObjective-Cと連携できるメリット

    C#とObjective-Cを連携できると多くのメリットを受けられます。具体的にはiOS開発のネイティブ機能を活用できます。例えば、

    • iOSネイティブUI操作
    • Face ID / Touch ID(生体認証)
    • ARKit(拡張現実)
    • HealthKit(ヘルスデータの取得)
    • CoreBluetooth(BLEデバイスとの通信)
    • Metal API(高性能なグラフィックスレンダリング)
    • App Extensions(ウィジェットやSiriショートカットの連携)
    • iOSのバックグラウンドタスクの活用
    • ネイティブ機能でパフォーマンスの最適化

    など。様々なUnityがサポートしていないiOSのネイティブ機能にアクセスすることが可能になります。

    Unityだけ触っていても時代とともに追加されるiOSの新機能にアクセスすることはできません。

    ※重要なものはUnity側もサポートはすると思います

    とはいえゲームにあまり関係ないネイティブ機能サポートの優先順位は低いはず。

    しかし、もしあなたがC#とObjective-Cの連携をできるのであれば、特に問題なくiOSの新機能にアクセスできるようになります。つまりエンジニアスキル向上に大きく繋がりますし、エンジニアとしての生存率も高めてくれます。

    ぜひ、この記事をきっかけてにC#とObjective-Cの連携を始めてみてもらえればと思います。

    C#(Unity)からObjective-Cを呼び出す全体像

    最初にUnityとObjective-Cを連携させる全体像を解説します。

    【Unity】C#からObjective-Cにアクセスする方法_0

    Unityプロジェクト内部で実装したObjective-CがiOSビルドした際にiOSネイティブ機能にアクセスします。

    しかし言語の仕様上 C#から直接Objective-Cにアクセスできません。 理由はビルド時にObjective-C側の関数をC#から特定できないため。

    そこで 「Objective-C++」 を使ってプラグインを開発します。

    お悩みさん
    お悩みさん
    Objective-C++って何?

    Objective-C++とはC++とObjective-Cを混ぜて使用するファイル形式です。本来拡張子は「.m」ですがObjective-C++は「.mm」になります。

    つまり以下のような処理フローになります。

    1. Unity(C#)からはObjective-C++内に記述されたC++関数を実行
    2. C++関数がObjective-Cの関数を実行

    また前提としてObjective-CはUnityエディタ上では動作しません。なぜならObjective-CはiOS、またはMacのネイティブ機能を参照するためです。つまりテストする際はビルドする必要があるということを覚えておきましょう。

    C#からObjective-Cを呼び出すUnityプロジェクト構成

    C#からObjective-Cを呼び出すUnityプロジェクトを構築していきます。今回使用するファイルは次の2つです。

    ファイル名内容
    UsePlugin.csプラグインを呼び出すC#
    SampleObjC.mmiOSプラグイン本体

    上記2つのファイルのUnityプロジェクト構成は↓こちら。

    Assets/  
    ├── UsePlugin.cs  
    └── Plugins/  
        └── iOS/  
            └── SampleObjC.mm  
    

    ポイントはObjective-Cファイルを Plugins/iOS ディレクトリに格納することです。

    以上で準備は完了したのでC#、Objective-Cそれぞれ実装していききます。

    今回実装する機能はC#からObjective-Cを呼び出しログを出力するといったシンプルな処理です。

    本ブログはベイビーステップを大事にしています。初めてやることは最も簡単な単位に分割して学ぶことで応用が効きやすくなります。

    それでは早速本編にいきましょう。

    今回はiOSのアラートウィンドウをUnityから呼び出すプログラムを作成していきます。具体的には以下のような感じです。

    【Unity】C#からObjective-Cにアクセスする方法_1

    起動したらUnityからiOSの機能を呼び出してアラートウィンドウが表示されるアプリを作っていきます。

    Unity(C#)からObjective-Cを呼び出す3つのステップ

    早速UnityからObjective-Cの関数を呼び出す処理を実装していきます。C#側、Objective-C側それぞれ処理を記述していますが、全体で3ステップです。

    Unity(C#)からObjective-Cを呼び出す3つのステップ

    ①Objective-C側の処理

    ②C#側の処理

    ③ビルドしてテスト

    1.Objective-C側の処理

    まずはObjective-C側の処理を実装していきます。C#からObjective-Cを呼び出す方法は、C++で作成したDLL内の関数を実行する方法と似ています。

    早速Objective-C側のソースコードを見ていきましょう。

    💻ソースコード : SampleObjC.mm
    #import <UIKit/UIKit.h>
    
    // C#から実行した関数をC++で定義  
    extern "C" void ShowAlert()  
    {
        // Objective-Cのアラートウィンドウ作成処理  
        UIAlertView* alert =  
            [[UIAlertView alloc]  
                initWithTitle:@"Title"  
                message:@"Hello from ObjC!"  
                delegate:nil  
                cancelButtonTitle:@"OK"  
                otherButtonTitles:nil  
            ];  
        // アラートウィンドウを開く  
        [alert show];  
    }
    

    ポイントはC#から呼び出したいC++関数「ShowAlert」に対して「extern "C"」を設定しているところです。

    UIAlertView というObjective-C側のクラスを呼び出してアラートウィンドウを作成しています。

    UIAlertViewやObjective-Cの細かい文法は一旦おいておきましょう。今回は初めてUnityからObjective-Cを呼び出す体験を優先しましょう。

    2.C#側の処理

    次にC#側の処理を実装していきます。C#側の役割はObjective-C側で作成したC++関数を呼び出すことです。

    早速C#のソースコードを確認していきます。

    💻ソースコード : CsToObjC.cs
    using System.Runtime.InteropServices;  
    using UnityEngine;  
    
    public class CsToObjC : MonoBehaviour  
    {
    #if UNITY_IOS && !UNITY_EDITOR
        [DllImport("__Internal")]  
        private static extern void ShowAlert();  
    #endif
    
        void Start()  
        {
    #if UNITY_IOS && !UNITY_EDITOR
            ShowAlert();  
    #endif
        }
    }
    

    Objective-C側で定義したC++関数と同名の 「ShowAlert」 に対して「static extern」の設定が重要です。

    今回はUnityのStartのタイミングでObjective-Cを呼び出しています。つまりアプリ起動時にアラートウィンドウが表示される感じです。

    お悩みさん
    お悩みさん
    #if UNITY_IOSって何?

    ソースコード内に登場する #if UNITY_IOS〜#endif「シンボル」 と呼ばれるC#の書式です。シンボルはビルドにソースコードを含めるかどうかを指定できます。

    例えば以下のコード内の関数「ShowAlert」の呼び出し処理はiOSプラットフォーム且つUnityエディタ外のみ採用されるという意味になります。

    #if UNITY_IOS && !UNITY_EDITOR
            ShowAlert();  
    #endif
    

    つまりiOSを選んでいない、またはUnityエディタ上で実行しても動作しないということです。

    Unity上でターゲットプラットフォームを選択するにはSwitch Platformを使用してください。

    Xcodeで実機ビルドしてテスト

    Objective-C、C#側のコードそれぞれ実装が完了したらXcodeでビルドしていきます。

    XcodeとはiOSアプリ、Macアプリを開発する際に使用するApple公式の開発ソフトです。Xcodeのインストールについてはこちらの記事を。

    UnityからiOSプロジェクトをビルドする方法はこちらの記事を参考にしてみてください。

    iOS実機でビルドする際にエラーが起きる場合はこちらの記事を参考にしてみてください。長年のトラブルシューティングが記述されています。

    ビルドが成功したらアプリ起動時にアラートウィンドウが表示されます。

    【Unity】C#からObjective-Cにアクセスする方法_2

    ビルド成功おめでとうございます!UnityがサポートしていないiOS機能を動かすと面白いですよね。

    Objective-Cの補完を効かせる方法

    iOSネイティブプラグインを開発するときに困るのはコードの補完です。UnityだったらVisual StudioやRiderといったC#のコードを保管してくれるエディタを使用して開発します。

    しかし、Unityプロジェクト内に格納したObjective-Cファイルは補完が効きません。今回のようなシンプルな処理ならまだ大丈夫ですが、複雑な機能を実装しようとしたら補完は必須です。

    そこでソースコードの補完が効くための環境整備をしていきます。

    Xcodeでプロジェクト新規プロジェクトを作成

    Objective-C開発時のコード補完を効かせるために、Xcode上でプラグイン開発用の新規プロジェクトを作成します。

    【Unity】C#からObjective-Cにアクセスする方法_3

    Xcodeの メニューFile から Project を選択します。

    【Unity】C#からObjective-Cにアクセスする方法_4

    テンプレート選択画面から「iOS」を選んで「Framework」を選択しNextボタンをクリックしてください。

    【Unity】C#からObjective-Cにアクセスする方法_5

    Product Nameを入力し、Language を「Objective-C」に設定して「Nextボタン」をクリックします。

    【Unity】C#からObjective-Cにアクセスする方法_6

    すると新規のプロジェクトが作成されます。 右クリック から 「New File from Template」 を選択してください。

    【Unity】C#からObjective-Cにアクセスする方法_7

    Objective-C File を選んで「Next」ボタンをクリックします。

    【Unity】C#からObjective-Cにアクセスする方法_8

    ファイル名を決めて「Next」ボタン。

    【Unity】C#からObjective-Cにアクセスする方法_9

    ↑このようにObjective-Cファイル(拡張子.m)が作られます。

    【Unity】C#からObjective-Cにアクセスする方法_10

    しかしObjective-CファイルのままではC++が記述できないため、拡張子を「.mm」にリネームします。

    【Unity】C#からObjective-Cにアクセスする方法_11

    以上でXcodeのコード補完が効くようになるためプラグインの開発がしやすくなります。Xcode上で作ったObjective-C++ファイルをUnityにコピペして開発を進めるという感じです。

    まとめ

    本記事では、Unity(C#)からObjective-Cを呼び出す方法について解説しました。C#とObjective-Cを連携させることで、iOSのネイティブ機能を利用できるようになり、Face IDやARKit、Metal APIなどUnityだけではアクセスできない機能を活用できます。

    C#から直接Objective-Cを呼び出すことはできない ためObjective-C++(.mmファイル)を経由することで連携を実現します。

    具体的にはC#側で DllImport("__Internal") を使ってObjective-C++の関数を呼び出しObjective-C側でiOSのアラートを表示する処理を実装しました。

    最後にXcodeでコード補完を有効にする方法についても解説し、開発をスムーズに進める環境構築の重要性を紹介しました。

    UnityでiOSの高度な機能を活用したい方は、ぜひObjective-Cとの連携にトライしてみてください。

    オススメ記事
    検証環境
    • Unity6000.0.32f1
    • Xcode 16.2
    • macOS 15.3.1
    • iOS18.3
    参考サイト