Unity×iOS

【Unity×iOS】カメラロールから画像を選択して表示・アップロードする方法|Objective-C連携で実現

使用環境

・Unity Editor:2021.3.18f1

この記事で分かること

  • iOSのネイティブUIを使って画像を選ばせる方法
  • UIImagePickerControllerをUnityから使う手順
  • 【コピペOK】Objective-C++連携+Texture2D変換コード
  • カメラロールから選択した画像をUnityで表示・アップロードする方法

写真アプリからアップロードする方法とは?

ピッグダディ

SNS投稿やプロフィール変更で「ユーザーに写真を選ばせたい」っていう機能、アプリではよく見かけるよね。Unityでも同じように実装できたら便利だと思わない?

ピッグボーイ

めっちゃ思います!
でもUnityって、iPhoneのカメラロールを開けたりしないですよね?

ピッグガール

それってたぶんネイティブ連携が必要なんじゃ…
Objective-Cとか使うやつ?

ピッグダディ

そのとおり!
今回はObjective-C++とUnity C#を組み合わせて、カメラロールから写真を選んでTexture2Dに変換する方法を、コピペOKで丁寧に解説するよ!

Unityだけではできない?→ネイティブ連携が必要

Unity標準ではiOSの「写真アプリ」を開いたり、ユーザーに画像選択させるUIは用意されていません。
そこで必要になるのが、Objective-C++ で UIImagePickerController を使い、画像の選択をネイティブ側で処理し、結果をUnityに返す方法です。

【コピペOK】写真選択プラグインの作成手順

.mmファイルを作成

Assets/Plugins/iOS/ImagePicker.mm

#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import "UnityAppController.h"

@interface ImagePickerDelegate : NSObject <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@end

@implementation ImagePickerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    NSData *imageData = UIImagePNGRepresentation(image);
    NSString *base64String = [imageData base64EncodedStringWithOptions:0];

    UnitySendMessage("ImageReceiver", "OnImageSelected", [base64String UTF8String]);

    [picker dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:nil];
}

@end

static ImagePickerDelegate* pickerDelegate = nil;

extern "C" void OpenImagePicker()
{
    UIViewController *rootVC = UnityGetGLViewController();
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    picker.delegate = pickerDelegate = [[ImagePickerDelegate alloc] init];

    [rootVC presentViewController:picker animated:YES completion:nil];
}

Unity C#側の受け取りスクリプト

  • “ImageReceiver” という名前のGameObjectに OnImageSelected を呼び出します
  • Base64経由でデータを受け取って、Texture2Dに変換
using UnityEngine;
using System.Runtime.InteropServices;

public class ImageReceiver : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void OpenImagePicker();

    public Renderer targetRenderer;

    public void PickImage()
    {
#if UNITY_IOS && !UNITY_EDITOR
        OpenImagePicker();
#else
        Debug.Log("実機でのみ動作します。");
#endif
    }

    public void OnImageSelected(string base64)
    {
        byte[] imageData = System.Convert.FromBase64String(base64);
        Texture2D texture = new Texture2D(2, 2);
        texture.LoadImage(imageData);
        targetRenderer.material.mainTexture = texture;
    }
}

使用例(ボタンから写真選択 → GameObjectに貼る)

public class UIController : MonoBehaviour
{
    public ImageReceiver imageReceiver;

    public void OnPickPhotoButtonPressed()
    {
        imageReceiver.PickImage();
    }
}

注意点・補足

項目解説
実機テストが必須エディタやAndroidでは動作しません
ユーザーに写真アクセスの許可を求める必要ありInfo.plistに設定が必要(例:NSPhotoLibraryUsageDescription)
UnitySendMessageの受信対象GameObject名に注意大文字小文字やスペルミスが多い

まとめ

ユーザーに画像を選ばせたいアプリでは、
この仕組みで写真アップロード・表示が実現できます!

ポイント内容
Unityだけでは写真選択は不可
Objective-Cで画像を選択 → Base64経由でUnityに渡す
Texture2Dに変換してそのまま使える
Info.plistでパーミッション設定も忘れずに