Unity(iOS)プロジェクトのネイティブソースでのリソースの読み込み方法


はじめに

UnityのプロジェクトでiOSのネイティブのソースから画像などのリソースを読み込む方法を紹介します。

ここで紹介する方法はやり方がイケてるかは知らないけどとりあえず実現はできたという方法です。(Unity初心者なのでもっといい方法あればご教示ください)

やりたいこと

  • iOSビルドしてiOSのネイティブソースから画像などのリソースを読み込む

方法1(直接Images.xcassetsに入れる)

やり方

  • UnityプロジェクトのiOSビルドを行う
  • できたXcodeプロジェクトのImages.xcassetsに画像を入れる
  • ネイティブソースで画像を読み込む

画像の読み込み。今回はDataSetの方がよかったのでDataSetで扱っています。

if let data = NSDataAsset(name: "hogehoge")?.data {
    let image = UIImage(data: data)
}

これが一番簡単かと思いますが、毎回ビルド後に画像を入れないといけないので手間がかかります。

方法2(Documetsフォルダで共有)

やり方

  • UnityプロジェクトのAssets/Resourcesフォルダに画像を入れる
  • Unity側でDocumentsフォルダに画像を保存する
  • ネイティブソースでDocumentsフォルダに保存してある画像を読み込む

Unity側

Texture2D tex2d = Resources.Load("hogehoge") as Texture2D;
File.WriteAllBytes(Application.persistentDataPath+"/hogehoge.png",tex2d.EncodeToPNG());

ネイティブ側

let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let imagePath = "\(documentPath)/hogehoge.png"
if let data = FileManager.default.contents(atPath: imagePath) {
    let image = UIImage(data: data)
}

無駄にDocuments配下にファイルを置くのはどうなんだろう...

方法3(スクリプトでImages.xcassetsに入れる)

やり方

  • 適当なXcodeプロジェクトのxcassetsに画像を入れてdatasetを作る
  • UnityプロジェクトのAssets/Plugins/iOSフォルダに作ったdatasetを入れる
  • UnityプロジェクトのAssets/Plugins/iOS/Editorフォルダにスクリプトを入れる
  • ネイティブソースで画像を読み込む
  • UnityプロジェクトのiOSビルドを行う

下記のhogehoge.datasetをUnityプロジェクトに追加。

スクリプトはここを参考。

下記のスクリプトをUnityプロジェクトに入れる(Editorフォルダ配下であればどこでもいいようです)

using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;

public class XcodeSettingsPostProcesser
{
  [PostProcessBuildAttribute (0)]
  public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject)
  {
    if(target != BuildTarget.iPhone) return;

    CopyImages(pathToBuiltProject);
  }

  //Assets/Plugins/iOS配下の.datasetフォルダをXcodeプロジェクトのImages.xcassetsにコピーする
  private static void CopyImages(string xcodeProjectPath)
  {
    var destDirName = Path.Combine(xcodeProjectPath, "Unity-iPhone/Images.xcassets/");
    var path = Application.dataPath + "/Plugins/iOS"
    var sourceDirNames = Directory.GetDirectories(path, "*.dataset", SearchOption.AllDirectories);
    foreach(var sourceDirName in sourceDirNames)
    {
      var dirName = Path.GetFileName(sourceDirName);
      CopyDirectory(sourceDirName, Path.Combine(destDirName, dirName));
    }
  }

  public static void CopyDirectory(string sourceDirName, string destDirName)
  {
    //コピー先のディレクトリがないときは作る
    if (!System.IO.Directory.Exists(destDirName))
    {
      System.IO.Directory.CreateDirectory(destDirName);
      //属性もコピー
      System.IO.File.SetAttributes(destDirName,
          System.IO.File.GetAttributes(sourceDirName));
    }

    //コピー先のディレクトリ名の末尾に"\"をつける
    if (destDirName[destDirName.Length - 1] !=
        System.IO.Path.DirectorySeparatorChar)
      destDirName = destDirName + System.IO.Path.DirectorySeparatorChar;

    //コピー元のディレクトリにあるファイルをコピー
    string[] files = System.IO.Directory.GetFiles(sourceDirName);
    foreach (string file in files)
    {
      if(file.EndsWith(".meta")) continue; // metaファイルはコピーしない.
      System.IO.File.Copy(file, destDirName + System.IO.Path.GetFileName(file), true);
    }

    //コピー元のディレクトリにあるディレクトリについて、再帰的に呼び出す
    string[] dirs = System.IO.Directory.GetDirectories(sourceDirName);
    foreach (string dir in dirs)
      CopyDirectory(dir, destDirName + System.IO.Path.GetFileName(dir));
  }
}

iOSのビルド後下記のように画像が追加されている。

画像の読み込み

if let data = NSDataAsset(name: "hogehoge")?.data {
    let image = UIImage(data: data)
}

方法1のXcodeに画像を入れるのを自動化したのがこの方法。3つの中ではこの方法がいいかなと思います。

さいごに

画像を表示するだけなのに結構苦労しました...

ネイティブ側でごちゃごちゃやろうと思うと色々工夫がいるみたいです。

参考

Unity iOSで自動的に画像リソースを追加する