之前一直從事iOS開發(fā)工作烁落,最近要做一個iOS SDK給Unity游戲項目使用,新手遇到很多問題豌注,還好都自己解決了伤塌,記錄一下;
1轧铁、開發(fā)iOS SDK:之前因為對Unity接入iOS SDK和UnityPackage打包不熟每聪,看網(wǎng)上說Unity不會自動復制Framework到Xcode工程,所以用的靜態(tài)鏈接庫齿风,也就是.a形式;(其實Unity導出Xcode后接入SDK對iOS開發(fā)人員來說非常簡單药薯!但Unity項目希望能自動化處理,導出Xcode后可以不經(jīng)任何修改救斑,所以需要把iOS SDK做成UnityPackage包童本,在Unity開發(fā)環(huán)境簡單、快捷接入)
2脸候、由于Untiy使用C#語言開發(fā)穷娱,所以iOS需要提供 C 接口給 Unity 調(diào)用绑蔫,例如: mysdk.h
ifdef __cplusplus //C++環(huán)境
extern "C"{
endif
void usersdk(const char *param);
ifdef __cplusplus //C++環(huán)境
}
endif
然后在 mysdk.mm 文件實現(xiàn):
void usersdk(const char *param)
{
}
3、SDK分別針對真機和模擬器在Release模式編譯泵额,編譯后合并成通用.a配深,最后應該得到一些.h頭文件、.a二進制文件嫁盲、可能還有一些資源文件篓叶,比如 test.txt,image.xcassets圖片文件夾等;
4羞秤、新建 Unity 項目缸托,在Assets目錄下面新建 /Plugins/MySDK/iOS和Android文件夾,把第2步的文件和資源還有 mysdk.h 和 mysdk.mm 放到iOS目錄下瘾蛋;
5嗦董、在 Unity新建 C# 文件,調(diào)用 SDK 接口:
public class ECKChatSDK : MonoBehaviour {
#if UNITY_IOS && !UNITY_EDITOR
[DllImport("__Internal")]
void usersdk(string param);
#endif
void OnGUI() {
if (GUI.Button (new Rect (200, 150, 200, 50), "使用SDK")) {
#if UNITY_IOS && !UNITY_EDITOR
usersdk("param");
#endif
#if UNITY_ANDROID && !UNITY_EDITOR
#endif
}
}
}
Unity會自動匹配 string 和 const char *;
6瘦黑、新建 iosbulid.cs 自動復制文件和資源:
在 Unity 的 Assets 目錄下京革,新建目錄和文件 /Scripts/Editor/iosbulid.cs,內(nèi)容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.IO;
public class iOSBuild : MonoBehaviour {
[PostProcessBuild]
public static void OnPostprocessBuild(BuildTarget buildTarget, string path)
{
if (BuildTarget.iOS == buildTarget)
{
//復制資源文件夾
ECKCopyiOSResource(path);
//修改工程文件
ECKModifyPBXProject(path);
}
}
private static void ECKModifyPBXProject(string path)
{
string projPath = PBXProject.GetPBXProjectPath(path);
PBXProject proj = new PBXProject();
proj.ReadFromString(File.ReadAllText(projPath));
string target = proj.TargetGuidByName("Unity-iPhone");
//添加 -ObjC標記
proj.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC");
//引用資源文件夾
string resourceDirectoryPath = "Libraries/Plugins/ECKChatSDK/iOS/Resource";
ECKAddResourceGroupToiOSProject(path, proj, target, resourceDirectoryPath);
//引用資源文件夾幸斥,直接添加文件夾匹摇,以Create folder references 形式添加
/*
string resourcePath = "Libraries/Plugins/ECKChatSDK/iOS/Resource";
//string fileGuid = proj.AddFolderReference(Path.Combine(path, resourcePath), resourcePath, PBXSourceTree.Source);
string fileGuid = proj.AddFolderReference(Path.Combine(path, resourcePath), resourcePath);
proj.AddFileToBuild(target, fileGuid);*/
//保存工程文件
File.WriteAllText(projPath, proj.WriteToString());
}
//在工程文件添加資源文件夾引用,以 Create Group 形式加到工程文件
private static void ECKAddResourceGroupToiOSProject(string xcodePath, PBXProject proj, string target, string resourceDirectoryPath)
{
string dirFullPath = Path.Combine(xcodePath, resourceDirectoryPath);
//添加文件引用
string[] files = Directory.GetFiles(dirFullPath);
foreach (string s in files)
{
string fileExtension = Path.GetExtension(s);
if (fileExtension.Equals(".DS_Store")) {
continue;
}
string fileName = Path.GetFileName(s);
string targetFilePath = Path.Combine(resourceDirectoryPath, fileName);
string fileGuid = proj.AddFolderReference(targetFilePath, targetFilePath);
proj.AddFileToBuild(target, fileGuid);
}
//添加子文件夾
string[] subDirectorys = Directory.GetDirectories(dirFullPath);
foreach (string s in subDirectorys)
{
string fileName = Path.GetFileName(s);
string subDirPath = Path.Combine (resourceDirectoryPath, fileName);
string fileExtension = Path.GetExtension(s);
if (fileExtension.Equals (".xcassets")) {
string fileGuid = proj.AddFile(subDirPath, subDirPath);
proj.AddFileToBuild(target, fileGuid);
} else {
ECKAddResourceGroupToiOSProject (xcodePath, proj, target, subDirPath);
}
}
}
//復制ios多語言文件和圖片資源
private static void ECKCopyiOSResource(string path)
{
string fromDir = Application.dataPath+"/Plugins/ECKChatSDK/iOS/Resource/";
string targetDir = path + "/Libraries/Plugins/ECKChatSDK/iOS/Resource/";
ECKCopyDirectoryFiles (fromDir, targetDir);
}
/** 將文件夾下面的所有非.meta文件(不包括子文件夾)復制到iOS工程目錄下*/
private static void ECKCopyDirectoryFiles(string fromDir, string targetDir)
{
if (!Directory.Exists(targetDir))
{
Directory.CreateDirectory(targetDir);
}
//復制所有文件
string[] files = Directory.GetFiles(fromDir);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
string extension = Path.GetExtension(s);
if (extension.Equals(".meta"))
{
continue;
}
string fileName = Path.GetFileName(s);
string targetFilePath = Path.Combine(targetDir, fileName);
File.Copy(s, targetFilePath, true);
}
//復制所有子文件夾
string[] subDirectorys = Directory.GetDirectories(fromDir);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in subDirectorys)
{
string dirName = Path.GetFileName(s);
string targetDirPath = Path.Combine(targetDir, dirName);
ECKCopyDirectoryFiles (s, targetDirPath);
}
}
}
因為加了 [PostProcessBuild] 表情甲葬,這個 OnPostprocessBuild 函數(shù)會在 Untiy編譯成Xcode后自動執(zhí)行!
這里需要說明的是廊勃,Xcode工程添加文件夾有2種方式,第一種是 Create Groups经窖,第二種是 Create folder references坡垫,如果使用
/*
string resourcePath = "Libraries/Plugins/ECKChatSDK/iOS/Resource";
//string fileGuid = proj.AddFolderReference(Path.Combine(path, resourcePath), resourcePath, PBXSourceTree.Source);
string fileGuid = proj.AddFolderReference(Path.Combine(path, resourcePath), resourcePath);
proj.AddFileToBuild(target, fileGuid);*/
這段代碼,會以 第二種 Create folder references 形式加到工程文件画侣;
ECKAddResourceGroupToiOSProject 這個函數(shù)會以 第一種方式加到工程文件;
7冰悠、最后運行 Xcode工程,應該可以直接 run 起來了配乱,測試無誤后溉卓,進入下一步;
8搬泥、在 Unity項目桑寨,選中 /Plugins/MySDK 文件夾,右鍵選擇 Export Package ... 得到 MySDK.unitypackage包忿檩,把這個包給 Untiy項目尉尾,對方先打開他們自己游戲的Unity工程,然后雙擊我們的 MySDK.unitypackage包燥透,點擊 import 按鈕沙咏,就可以導入到游戲的Unity工程辨图,把 iosbulid.cs 里面的函數(shù)復制到游戲的相似地方,實現(xiàn)自動復制文件和資源功能;