unity 与oc交互

"$(PROJECT_DIR)"代表了工程的根目录
unity 与oc交互主要在于数据间的传递,unity传递的值到了oc这里可以用c接收并解析。基础的一些数据类型对应可以看下如下:

数据类型 Unity(C#) Object-C
int int int
float float float
bool bool bool
string string const char *
long long long long

在Object-C的工具里面吧***.mm写好,放到Unity项目的Assets/Plugins/iOS下面。(Unity2018及以上只要放在任意iOS的夹下即可)
在C#里面写上代static extern的 函数,与C里面的函数同名。
一.基础的调用参数,无传参
ocClass.mm

extern "C" {
    //从C#调用
    void CallOC() {
        NSLog(@"Object-c Called.");
    }
}

CsharpCallOC.cs

using System.Runtime.InteropServices;

public class CsharpCallOC {
    //调用ocClass.mm里面的同名函数
    [DllImport("__Internal")]
    private static extern void CallOC();
}

二.传递参数
ocClass.mm

extern "C" {
    //从C#调用
    void CallOC(int val1, float val2, bool val3, const char *val4) {
        NSLog(@"Object-c Called. val1=%d, val2=%f, val3=%d, val4=%s", val1, val2, val3, val4);
}

CsharpCallOC.cs

using System.Runtime.InteropServices;

public class CsharpCallOC {
    //调用ocClass.mm里面的同名函数
    [DllImport("__Internal")]
    private static extern void CallOC(int val1, float val2, bool val3, string val4);
}

三.OC回调Unity
1.使用函数指针接口方法进行回调,可以传参,也可以带返回参数,调用灵活。(推荐使用)
2.UnitySendMessage()需要有固定的游戏物体,按名称查找,并且是激活状态,不能隐藏(不推荐,无法灵活使用)。

extern "C" {
    // C#函数的函数指针
    typedef void (*cs_callback)(int);

    void CallOC(cs_callback callback) {
        callback(999);
    }
}

using System.Runtime.InteropServices;
using AOT;

public class CsharpCallOC {
    delegate void callback_delegate(int val);

    [DllImport("__Internal")]
    private static extern void sampleMethod4(callback_delegate callback);

    //回调函数,必须MonoPInvokeCallback并且是static
    [MonoPInvokeCallback(typeof(callback_delegate))]
    private static void cs_callback(int val) {
        UnityEngine.Debug.Log ("cs_callback : " + val);
    }

    private static void sampleMethod4Invoker() {
        //直接把函数传过去
        sampleMethod4 (cs_callback);
    }
}

此处记录unity编辑器打包xcode自动化脚本。大部分的目录与属性都可以个性成功。至于复制文件以Groud的方式,还有一些问题。需要处理多余引用资源的问题。工具可以后期考虑集成方式,做成成品工具。方便多元化出包。

using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System;
#if UNITY_EDITOR_OSX
using UnityEditor.iOS.Xcode;
#endif
using System.IO;

public class XcodeProjectMod : MonoBehaviour
{
#if UNITY_EDITOR_OSX
    [PostProcessBuild]
    public static void OnPostprocessBuild(BuildTarget buildTarget, string path)
    {
        if (buildTarget == BuildTarget.iOS)
        {
            string projPath = PBXProject.GetPBXProjectPath(path);
            PBXProject proj = new PBXProject();

            proj.ReadFromString(File.ReadAllText(projPath));
            string target = proj.TargetGuidByName("Unity-iPhone");
            string rootPath = projPath.Replace("Unity-iPhone.xcodeproj/project.pbxproj", "");

            //复制sdk接口文件
            var iosLibPath = "Sdk/IOSLib";
            var classes = "Classes";
            var fileName = "UnityAppController.mm";
            var filePath = Path.Combine(iosLibPath, fileName);
            var targetFilePath = Path.Combine(path, Path.Combine(classes, fileName));
            File.Copy(filePath, targetFilePath, true);

            fileName = "UnityAppController.h";
            filePath = Path.Combine(iosLibPath, fileName);
            targetFilePath = Path.Combine(path, Path.Combine(classes, fileName));
            File.Copy(filePath, targetFilePath, true);

            //创建swift桥接
            fileName = "File.swift";
            filePath = Path.Combine(iosLibPath, fileName);
            targetFilePath = Path.Combine(path, fileName);
            File.Copy(filePath, targetFilePath, true);
            proj.AddFileToBuild(target, proj.AddFile(fileName, fileName, PBXSourceTree.Source));

            fileName = "Unity-iPhone-Bridging-Header.h";
            filePath = Path.Combine(iosLibPath, fileName);
            targetFilePath = Path.Combine(path, fileName);
            File.Copy(filePath, targetFilePath, true);
            proj.AddFileToBuild(target, proj.AddFile(fileName, fileName, PBXSourceTree.Source));

            //复制sdk文件到xcode目录下
            var sdkPath = Application.dataPath.Replace("Assets", "") + "Sdk/IOSLib/SDK";
            var sdkFolder = "SDK";
            var sdkDir = Path.Combine(path, sdkFolder);
            CopyOldLabFilesToNewLab(sdkPath, sdkDir);
            //以Group方式添加文件夹引用到工程
            //AddResourceGroupToiOSProject(path, proj, target, sdkFolder);

            // 添加依赖库
            proj.AddFrameworkToProject(target, "AdServices.framework", true);
            proj.AddFrameworkToProject(target, "AppTrackingTransparency.framework", false);
            proj.AddFrameworkToProject(target, "AppsFlyerLib.framework", false);
            proj.AddFrameworkToProject(target, "Accounts.framework", false);

            proj.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
            proj.SetBuildProperty(target, "SWIFT_VERSION", "5.0");

            //设置包名
            proj.SetBuildProperty(target, "PRODUCT_BUNDLE_IDENTIFIER", "com.baplay.${PRODUCT_NAME:rfc1034identifier}");
            proj.SetBuildProperty(target, "PRODUCT_NAME", "st");

            //添加链接库
            string linkerFlags = "$(inherited) -ObjC -lsqlite3.0 -lc++ -lstdc++ -lz -weak_framework Accelerate -weak-lSystem -weak_framework CoreMotion -weak-lSystem";
            proj.SetBuildProperty(target, "OTHER_LDFLAGS", linkerFlags);
            //string[] linkerFlagsToAdd = { "-lsqlite3.0", "-ObjC", "-lc++", "-lstdc++", "-lz", "-weak_framework", "Accelerate", "-weak-lSystem", "-weak_framework", "CoreMotion", "-weak-lSystem" };
            //string[] linkerFlagsRemove = null;//删除的链接库
            //proj.UpdateBuildProperty(target, "OTHER_LDFLAGS", linkerFlagsToAdd, linkerFlagsRemove);

            string[] codeSignEntitlements = { "$(PROJECT_DIR)/SDK/Resource/Play.entitlements" };
            proj.UpdateBuildProperty(target, "CODE_SIGN_ENTITLEMENTS", codeSignEntitlements, null);

            //添加库引用路径
            string[] FrameworkSearchPaths = { "$(PROJECT_DIR)/SDK/OtherLibs",
                    "$(PROJECT_DIR)/SDK/OtherLibs/GoogleSignIn_5.0.2",
                    "$(PROJECT_DIR)/SDK/OtherLibs/AF-iOS-SDK_v5.1" };
            proj.UpdateBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", FrameworkSearchPaths, null);

            //添加资源引用路径
            string[] LibrarySearchPaths = { "$(PROJECT_DIR)/SDK/OtherLibs/inMobi_5.0.1",
                    "$(PROJECT_DIR)/SDK/OtherLibs/OL113Tool",
                    "$(PROJECT_DIR)/SDK" };
            proj.UpdateBuildProperty(target, "LIBRARY_SEARCH_PATHS", LibrarySearchPaths, null);

            File.WriteAllText(projPath, proj.WriteToString());

            // 修改Info.plist文件
            var plistPath = Path.Combine(rootPath, "Info.plist");
            var plist = new PlistDocument();
            plist.ReadFromFile(plistPath);

            //增加权限
            plist.root.SetString("NSPhotoLibraryUsageDescription", "需要您的同意,才能访问相册");//
            plist.root.SetString("NSMicrophoneUsageDescription", "需要您的同意,才能访问麦克风");
            plist.root.SetString("NSCameraUsageDescription", "需要您的同意,才能访问相机");
            plist.root.SetString("NSTrackingUsageDescription", "您同意App使用IDFA廣告識別碼來做個人最佳化廣告嗎?");

            //增加键值对
            plist.root.SetString("bundle id", "com.test.test");
            plist.root.SetString("FacebookAppID", "819");
            var schemes = plist.root.CreateArray("LSApplicationQueriesSchemes");
            schemes.AddString("line");
            schemes.AddString("fbapi");
            schemes.AddString("fb-messenger-api");
            schemes.AddString("fbauth2");
            schemes.AddString("fbshareextension");

            // 插入URL Scheme到Info.plsit(理清结构)
            PlistElementArray urlArray = null;
            if (!plist.root.values.ContainsKey("CFBundleURLTypes"))
                urlArray = plist.root.CreateArray("CFBundleURLTypes");
            else
                urlArray = plist.root.values["CFBundleURLTypes"].AsArray();
            var dict = urlArray.AddDict().CreateArray("CFBundleURLSchemes");
            //插入dict
            dict.AddString("stios");
            dict.AddString("fb124442819");

            // 应用修改
            plist.WriteToFile(plistPath);
        }
    }
    /// 
    /// 拷贝文件夹下所有文件到新目录下面
    /// 
    /// l文件所在目录
    /// 保存的目标目录
    /// 返回:true-拷贝成功;false:拷贝失败
    public static bool CopyOldLabFilesToNewLab(string sourcePath, string savePath)
    {
        if (!Directory.Exists(savePath))
        {
            Directory.CreateDirectory(savePath);
        }

        try
        {
            string[] labDirs = Directory.GetDirectories(sourcePath);//目录
            string[] labFiles = Directory.GetFiles(sourcePath);//文件
            if (labFiles.Length > 0)
            {
                for (int i = 0; i < labFiles.Length; i++)
                {
                    if (!labFiles[i].Contains(".meta") && !labFiles[i].Contains(".DS_Store"))//排除文件
                    {
                        string fileName = Path.GetFileName(labFiles[i]);
                        File.Copy(Path.Combine(sourcePath, fileName), Path.Combine(savePath, fileName), true);
                    }
                }
            }
            if (labDirs.Length > 0)
            {
                for (int j = 0; j < labDirs.Length; j++)
                {
                    string fileName = Path.GetFileName(labDirs[j]);
                    Directory.GetDirectories(Path.Combine(sourcePath, fileName));

                    //递归调用
                    CopyOldLabFilesToNewLab(Path.Combine(sourcePath, fileName), Path.Combine(savePath, fileName));
                }
            }
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }
    //在工程文件添加资源文件夹引用,以 Create Group 形式加到工程文件
    private static void AddResourceGroupToiOSProject(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);
            //mac os文件结构原因需要处理文件后缀,不然会变成文件夹,导致库无法正常识别
            if (fileExtension.Equals(".xcassets")
                || fileExtension.EndsWith(".framework")
                || fileExtension.EndsWith(".xcframework")
                || fileExtension.EndsWith(".bundle")
                || fileExtension.EndsWith(".strings"))
            {
                string fileGuid = proj.AddFile(subDirPath, subDirPath);
                proj.AddFileToBuild(target, fileGuid);
            }
            else
            {
                AddResourceGroupToiOSProject(xcodePath, proj, target, subDirPath);
            }
        }
    }
#endif
}

你可能感兴趣的:(unity 与oc交互)