美文网首页
unity 与oc交互

unity 与oc交互

作者: AngerCow | 来源:发表于2021-06-22 17:50 被阅读0次

    "$(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);
            }
        }
        /// <summary>
        /// 拷贝文件夹下所有文件到新目录下面
        /// </summary>
        /// <param name="sourcePath">l文件所在目录</param>
        /// <param name="savePath">保存的目标目录</param>
        /// <returns>返回:true-拷贝成功;false:拷贝失败</returns>
        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交互

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