美文网首页
制作iOS SDK接入到Untiy项目,然后导出unitypac

制作iOS SDK接入到Untiy项目,然后导出unitypac

作者: LeLeBa | 来源:发表于2019-04-03 21:34 被阅读0次

    之前一直从事iOS开发工作,最近要做一个iOS SDK给Unity游戏项目使用,新手遇到很多问题,还好都自己解决了,记录一下;

    1、开发iOS SDK:之前因为对Unity接入iOS SDK和UnityPackage打包不熟,看网上说Unity不会自动复制Framework到Xcode工程,所以用的静态链接库,也就是.a形式;(其实Unity导出Xcode后接入SDK对iOS开发人员来说非常简单!但Unity项目希望能自动化处理,导出Xcode后可以不经任何修改,所以需要把iOS SDK做成UnityPackage包,在Unity开发环境简单、快捷接入)

    2、由于Untiy使用C#语言开发,所以iOS需要提供 C 接口给 Unity 调用,例如: mysdk.h

    ifdef __cplusplus //C++环境

    extern "C"{

    endif

               void usersdk(const char *param);
    

    ifdef __cplusplus //C++环境

    }

    endif

    然后在 mysdk.mm 文件实现:

    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# 文件,调用 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,内容如下:

    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 函数会在 Untiy编译成Xcode后自动执行!

    这里需要说明的是,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 这个函数会以 第一种方式加到工程文件;

    7、最后运行 Xcode工程,应该可以直接 run 起来了,测试无误后,进入下一步;

    8、在 Unity项目,选中 /Plugins/MySDK 文件夹,右键选择 Export Package ... 得到 MySDK.unitypackage包,把这个包给 Untiy项目,对方先打开他们自己游戏的Unity工程,然后双击我们的 MySDK.unitypackage包,点击 import 按钮,就可以导入到游戏的Unity工程,把 iosbulid.cs 里面的函数复制到游戏的相似地方,实现自动复制文件和资源功能;

    相关文章

      网友评论

          本文标题:制作iOS SDK接入到Untiy项目,然后导出unitypac

          本文链接:https://www.haomeiwen.com/subject/oxutiqtx.html