前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Unity与iOS交互,Unity脚本修改Xcode工程

Unity与iOS交互,Unity脚本修改Xcode工程

作者头像
用户2215591
发布于 2021-03-02 06:33:14
发布于 2021-03-02 06:33:14
1.7K00
代码可运行
举报
文章被收录于专栏:iOSer成长记录iOSer成长记录
运行总次数:0
代码可运行

Unity与iOS交互

  • Unity调用iOS的方法,首先在Xcode中新建一个iOS的桥接类,并且将.m的后缀修改为.mm
  • 在.h中加入以下代码,里面的函数包括 无返回,返回字符串,返回布尔,带参数的函数等 这里需要注意一个问题,传入的参数和返回的字符串最好都使用json格式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#if defined(__cplusplus)
extern "C"{
#endif
    // 获取系统语言
    extern char *GetLanguage();
    // 开始震动
    extern void StartVibration(char *param);
    // 是否是全面屏
    extern bool IsFullSecreen();
    // Unity iOS 字符串内存管理
    extern char* CharMemoryManagement(NSString *param);
#if defined(__cplusplus)
}
#endif
  • 在.mm中的实现,这里需要注意的是,返回字符串的时候,只能通过CharMemoryManagement方法将字符串转换成char,我试过其他很多种转换方式,都会造成程序崩溃的问题,Tools类里面就是方法的具体实现,代码与本文无关就不贴出来了
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#if defined(__cplusplus)
extern "C"{
#endif
    char *GetLanguage()
    {
        NSString *str = [Tools GetLanguage];
        return CharMemoryManagement(str);
    }
    void StartVibration(char *param)
    {
        [Tools StartVibration:[NSString stringWithUTF8String:param]];
    }
    bool IsFullSecreen()
    {
        return [Tools IsFullSecreen];
    }
    // 如果方法返回的是字符串,需要使用该方法将字符串转为char
    char* CharMemoryManagement(NSString *text)
    {
        char* ret = nullptr;
        ret = (char*) malloc([text length] + 1);
        memcpy(ret,[text UTF8String],([text length] + 1));
        return ret;
    }
#if defined(__cplusplus)
}
#endif
  • 上面的步骤完成之后,将.h和.mm文件(包括Tools等依赖的文件)拷贝到Unity工程中Assets目录下
  • 在Unity中,新建一个cs脚本,添加以下代码,这个脚本最好实现成单例,然后就可以通过Instance.IOSGetLanguage()来调用 注意需要引用 using System.Runtime.InteropServices 命名空间
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#if UNITY_IOS && !UNITY_EDITOR
    [DllImport("__Internal")] private static extern string GetLanguage();
    [DllImport("__Internal")] private static extern bool IsFullSecreen();
    [DllImport("__Internal")] private static extern void StartVibration(string param);
#endif

#region Unity to iOS
    public string IOSGetLanguage()
    {
#if UNITY_IOS && !UNITY_EDITOR
        return GetLanguage();
#else
        return "";
#endif
    }
    public void IOSStartVibration(long time)
    {
#if UNITY_IOS && !UNITY_EDITOR
        StartVibration(time.ToString());
#endif
    }
    public bool IOSIsFullSecreen()
    {
#if UNITY_IOS && !UNITY_EDITOR
        return IsFullSecreen();
#else
        return false;
#endif
    }
  • iOS通知Unity,iOS直接调用Unity方法的实现是非常麻烦的,通常情况下,我们都使用通知的方法,常见的场景是Unity调用iOS方法需要异步返回时
  • 在iOS类中加入下面代码,然后我们就可以给Unity发送通知了,如UnitySendMessage("节点名称", "方法名称", "参数,没有就传空字符串"",不能传nil")
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// --------- 某个.mm文件中 ---------
#if defined(__cplusplus)
extern "C"{
#endif
    extern void UnitySendMessage(const char *, const char *, const char *);
#if defined(__cplusplus)
}
#endif

// --------- 需要通知Unity的iOS类中 ---------
- (void)didReceiveReward {
    // 在iOS的某个方法中,向Unity发送消息
    UnitySendMessage("iOSLibraryUnity", "OnDidReceiveReward", "收到奖励");
}

//  --------- Unity中挂在节点上的脚本,用来接收通知 ---------
private void Start()
{
    // 脚本挂载的节点名必须和UnitySendMessage发送时填的一样
    this.name = "iOSLibraryUnity";
}
private void OnDidReceiveReward(string msg)
{
    // 接收到iOS通知
    Debug.log(msg);
}

Unity脚本修改Xcode工程

Unity要在iOS平台发布,需要先生成Xcode工程,通常生成Xcode工程后我们还需要修改很多的配置,添加原生代码等, 而这些是可以通过cs脚本修改的,比如修改Xcode工程的plist、添加Framework库、拷贝文件到iOS工程、插入代码等

  • 自动pod 实现自动pod需要谷歌的一个插件https://github.com/googlesamples/unity-jar-resolver,该插件在谷歌相关的一些SDK中就有,如OnsSignal、Firebase等SDK,如你应用集成有这些SDK,则不需要再下载该插件了,查看是否集成了该插件可以看你Assets目录下有没有ExternalDependencyManager文件,或看Assets->External Dependency Manager有没有这个选项
  • 集成完插件后,在Editor目录下新建一个Dependencies.xml的文件,里面的内容如下,这样在生成Xcode工程时就会自动将下面的库pod进工程
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependencies>
  <iosPods>
    <iosPod name="AFNetworking" version="4.0.1"/>
    <iosPod name="SDWebImage" version="5.8.4"/>
    <iosPod name="Masonry" version="1.1.0"/>
    <iosPod name="YYModel" version="1.0.4"/>
  </iosPods>
</dependencies>
  • 修改Xcode工程,在Editor中新建一个cs脚本,如下
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using UnityEditor.XCodeEditor;

public static class BuildiOS
{
    [PostProcessBuild(100)]
    public static void OnPostprocessBuild(BuildTarget buildTarget, string buildPath)
    {
        if (buildTarget != BuildTarget.iOS)
            return;
        var mProjectPath = PBXProject.GetPBXProjectPath(buildPath);
        var mProject = new PBXProject();
        mProject.ReadFromString(File.ReadAllText(mProjectPath));

        var mTargetGUID = GetPBXProjectTargetGUID(mProject);
        var mFrameworkGUID = GetPBXProjectUnityFrameworkGUID(mProject);

        var mPlistPath = Path.Combine(buildPath, "Info.plist");

        // 修改Plist
        PlistModify(mPlistPath);

        // 添加系统库
        SystemFrameworkAdd(mProject, mFrameworkGUID);

        // 添加文件
        FilesAdd(mProject, mTargetGUID, buildPath, mProjectPath);

        // 插入代码
        UnityAppControllerCodesAdd(buildPath);
    }

#if UNITY_2019_3_OR_NEWER
    private static string GetPBXProjectTargetGUID(PBXProject project)
    {
        return project.GetUnityMainTargetGuid();
    }
    private static string GetPBXProjectUnityFrameworkGUID(PBXProject project)
    {
        return project.GetUnityFrameworkTargetGuid();
    }
#else
    private static string GetPBXProjectTargetGUID(PBXProject project)
    {
        return project.TargetGuidByName(PBXProject.GetUnityTargetName());
    }
    private static string GetPBXProjectUnityFrameworkGUID(PBXProject project)
    {
        return GetPBXProjectTargetGUID(project);
    }
#endif
}
  • 修改plist
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static void PlistModify(string plistPath)
{
    var plist = new PlistDocument();
    plist.ReadFromFile(plistPath);

    // plist中添加一个字符串类型的key 如隐私设置
    plist.root.SetString("NSLocationAlwaysAndWhenInUseUsageDescription",
                         "$(PRODUCT_NAME) needs to get the location. I hope you agree.";

    // plist中添加一个布尔的key
    plist.root.SetBoolean("CADisableMinimumFrameDuration", false);

    // plist中添加一个字典的key 如ATS设置
    PlistElementDict dict = plist.root.CreateDict("NSAppTransportSecurity");
    dict.SetBoolean("NSAllowsArbitraryLoads", true);
        
    // 最后保存plist
    plist.WriteToFile(plistPath);
}
  • 添加系统库
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static void SystemFrameworkAdd(PBXProject project, string mFrameworkGUID) 
{
    string[] FRAMEWORKS_TO_ADD = {
        "libz.dylib",
        "libc++.dylib",
        "Security.framework",
        "SystemConfiguration.framework",
    };
    foreach (var framework in FRAMEWORKS_TO_ADD)
    {
        project.AddFrameworkToProject(mFrameworkGUID, framework, false);
    }
}
private static void SystemLibAdd(PBXProject project, string targetGuid, string lib)
{
    string fileGuid = project.AddFile("usr/lib/" + lib, "Frameworks/" + lib, PBXSourceTree.Sdk);
    project.AddFileToBuild(targetGuid, fileGuid);
}
  • 拷贝文件夹,代码文件如.h/.m等文件会自动拷贝的Xcode工程中,但图片,三方的Framework、lib等文件并不会自动拷贝到Xcode工程中,所以需要cs脚本来完成
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static void FilesAdd(PBXProject project, string mTargetGUID, string buildPath, string projectPath)
{
    string ResourcePath = "Assets/文件夹路径";
    XcodeDirectoryProcessor copy = new XcodeDirectoryProcessor();
    copy.CopyAndAddBuildToXcode(project, mTargetGUID, ResourcePath, buildPath, "Xcode中的文件夹名称");
    File.WriteAllText(projectPath, project.WriteToString());
}
  • 插入代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static void UnityAppControllerCodesAdd(string buildPath)
{
    // 获取Prefix.pch文件
    string mPchPath = buildPath + "/Classes/Prefix.pch";
    UnityEditor.XCodeEditor.XClass Pch = new UnityEditor.XCodeEditor.XClass(mPchPath);
    // 需要插入的代码,例如我们在pch中插入一段引入类的代码
    string call = "#import \"output.h\"";
    // 代码标记,找到pch文件里面已经存在的代码,我们就可以将需要插入的代码,插入到这行代码下面
    string mark = "#include \"UnityInterface.h\"";
    // 开始插入代码
    Pch.WriteBelow(mark, call);
}
  • 其他Editor中使用到的cs文件
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using UnityEngine;
using System.IO;

#if UNITY_IOS
using UnityEditor.iOS.Xcode;

public static class ExtensionName
{
    public const string META = ".meta";
    public const string ARCHIVE = ".a";
    public const string FRAMEWORK = ".framework";
    public const string BUNDLE = ".bundle";
}

public class XcodeDirectoryProcessor {

    /// <summary>
    /// 添加编译本地文件到Xcode工程
    /// </summary>
    /// <param name="pbxProject"></param>
    /// <param name="targetGuid"></param>
    /// <param name="copyDirectoryPath">源路径</param>
    /// <param name="buildPath">拷贝路径</param>
    /// <param name="currentDirectoryPath">拷贝路径/currentDirectoryPath</param>
    /// <param name="needToAddBuild"></param>
    public void CopyAndAddBuildToXcode(PBXProject pbxProject, string targetGuid, string copyDirectoryPath, string buildPath, string currentDirectoryPath, bool needToAddBuild = true){

        string unityDirectoryPath = copyDirectoryPath;
        string xcodeDirectoryPath = buildPath;

        if(!string.IsNullOrEmpty(currentDirectoryPath)){
            unityDirectoryPath = Path.Combine(unityDirectoryPath, currentDirectoryPath);
            xcodeDirectoryPath = Path.Combine(xcodeDirectoryPath, currentDirectoryPath);
            Delete (xcodeDirectoryPath);
            Directory.CreateDirectory(xcodeDirectoryPath);
        }
        foreach (string filePath in Directory.GetFiles(unityDirectoryPath)){
            string extension = Path.GetExtension (filePath);
            if(extension == ExtensionName.META){
                continue;
            }
            else if(extension == ExtensionName.ARCHIVE){
                pbxProject.AddBuildProperty(
                    targetGuid, 
                    "LIBRARY_SEARCH_PATHS", 
                    "$(PROJECT_DIR)/" + currentDirectoryPath
                );
            }
            string fileName = Path.GetFileName (filePath);
            string copyPath = Path.Combine (xcodeDirectoryPath, fileName);
            if(fileName[0] == '.'){
                continue;
            }
            File.Delete(copyPath);
            File.Copy(filePath, copyPath);
            if(needToAddBuild){
                string relativePath = Path.Combine(currentDirectoryPath, fileName);
                pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
            }
        }
        //遍历文件夹
        foreach (string directoryPath in Directory.GetDirectories(unityDirectoryPath)){
            string directoryName = Path.GetFileName (directoryPath);
            bool nextNeedToAddBuild = needToAddBuild;
            if(directoryName.Contains(ExtensionName.FRAMEWORK) || directoryName.Contains(ExtensionName.BUNDLE) || 
               directoryName == "Unity-iPhone"){
                nextNeedToAddBuild = false;
            }
            CopyAndAddBuildToXcode (
                pbxProject, targetGuid, 
                copyDirectoryPath, buildPath, Path.Combine(currentDirectoryPath, directoryName), 
                nextNeedToAddBuild
            );
            if(directoryName.Contains(ExtensionName.FRAMEWORK) || directoryName.Contains(ExtensionName.BUNDLE)){
                string relativePath = Path.Combine(currentDirectoryPath, directoryName);
                pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
                pbxProject.AddBuildProperty(
                    targetGuid, 
                    "FRAMEWORK_SEARCH_PATHS", 
                    "$(PROJECT_DIR)/" + currentDirectoryPath
                );
            }
        }
    }

    /// <summary>
    /// 拷贝目录(拷贝时候会删除copyPath)
    /// </summary>
    /// <param name="sourcePath"></param>
    /// <param name="copyPath"></param>
    public void CopyAndReplace(string sourcePath, string copyPath)
    {
        Delete (copyPath);
        Directory.CreateDirectory(copyPath);
        foreach (var file in Directory.GetFiles(sourcePath)){
            File.Copy(file, Path.Combine(copyPath, Path.GetFileName(file)));
        }
        foreach (var dir in Directory.GetDirectories(sourcePath)){
            CopyAndReplace(dir, Path.Combine(copyPath, Path.GetFileName(dir)));
        }
    }

    /// <summary>
    /// 删除目录
    /// </summary>
    /// <param name="targetDirectoryPath"></param>
    public void Delete(string targetDirectoryPath){
        if (!Directory.Exists (targetDirectoryPath)) {
            return;
        }
        string[] filePaths = Directory.GetFiles(targetDirectoryPath);
        foreach (string filePath in filePaths){
            File.SetAttributes(filePath, FileAttributes.Normal);
            File.Delete(filePath);
        }
        string[] directoryPaths = Directory.GetDirectories(targetDirectoryPath);
        foreach (string directoryPath in directoryPaths){
            Delete(directoryPath);
        }
        Directory.Delete(targetDirectoryPath, false);
    }
}

#endif
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Pandas-25.可视化
Pandas-25.可视化 用matplotlib库的plot()方法实现简单的可视化 df = pd.DataFrame(np.random.randn(10,4),index=pd.date_ra
悠扬前奏
2019/05/29
6580
你知道怎么用Pandas绘制带交互的可视化图表吗?
之前咱们介绍过Pandas可视化图表的绘制《『数据可视化』一文掌握Pandas可视化图表》,不过它是依托于matplotlib,因此无法进行交互。但其实,在Pandas的0.25.0版本之后,提供了一些其他绘图后端,其中就有我们今天要演示的主角基于Bokeh!
可以叫我才哥
2021/09/24
3.9K0
Pandas可视化详解 | 轻松玩转Pandas(12)
数据分析的结果不仅仅只是你来看的,更多的时候是给需求方或者老板来看的,为了更直观地看出结果,数据可视化是必不可少的一个环节。这里带大家来看下一些常用的图形的画法。
abs_zero
2018/09/25
2.7K0
Pandas可视化详解 | 轻松玩转Pandas(12)
Python数据科学(九)- 使用Pandas绘制统计图表1.信息可视化
因为人对图像信息的解析效率比文字更高,所以可视化可以使数据更为直观,便于理解,使决策变得高效,所以信息可视化就显得尤为重要。
Python攻城狮
2018/08/23
9630
Python数据科学(九)- 使用Pandas绘制统计图表1.信息可视化
干货案例 | Pandas数据可视化怎么做?
数据可视化可以让我们很直观的发现数据中隐藏的规律,察觉到变量之间的互动关系,可以帮助我们更好的给他人解释现象,做到一图胜千文的说明效果。
朱小五
2020/04/27
2.7K0
干货案例 | Pandas数据可视化怎么做?
pandas 图形可视化大全
plot()的参数设置subplots=True即可自动对dataframe数据生成子图的可视化图形。
Python数据科学
2023/08/29
2700
pandas 图形可视化大全
Pandas绘图功能
可视化是用来探索性数据分析最强大的工具之一。Pandas库包含基本的绘图功能,可以让你创建各种绘图。Pandas中的绘图是在matplotlib之上构建的,如果你很熟悉matplotlib你会惊奇地发现他们的绘图风格是一样的。
用户3577892
2020/11/12
1.8K0
Seaborn + Pandas带你玩转股市数据可视化分析
在日常生活中,可视化技术常常是优先选择的方法。尽管在大多数技术学科(包括数据挖掘)中通常强调算法或数学方法,但是可视化技术也能在数据分析方面起到关键性作用。
数据STUDIO
2021/06/24
6.9K0
Matplotlib可视化没那么难:7种常用图表最全绘制攻略来了!
导读:绘图是数据分析工作中的重要一环,是探索过程的一部分。Matplotlib是当前用于数据可视化的最流行的Python包之一,本文主要介绍数据可视化分析工具:Matplotlib。
IT阅读排行榜
2021/06/01
6.9K0
Matplotlib可视化没那么难:7种常用图表最全绘制攻略来了!
『数据可视化』一文掌握Pandas可视化图表
今天简单介绍一下Pandas可视化图表的一些操作,Pandas其实提供了一个绘图方法plot(),可以很方便的将Series和Dataframe类型数据直接进行数据可视化。
可以叫我才哥
2021/08/05
8.4K0
Python数据可视化的10种技能
如果你想要用 Python 进行数据分析,就需要在项目初期开始进行探索性的数据分析,这样方便你对数据有一定的了解。其中最直观的就是采用数据可视化技术,这样,数据不仅一目了然,而且更容易被解读。同样在数据分析得到结果之后,我们还需要用到可视化技术,把最终的结果呈现出来。
MachineLP
2019/05/26
2.8K0
数据分析之Pandas快速图表可视化各类操作详解
一般我们做数据挖掘或者是数据分析,再或者是大数据开发提取数据库里面的数据时候,难免只能拿着表格数据左看右看,内心总是希望能够根据自己所想立马生成一张数据可视化的图表来更直观的呈现数据。而当我们想要进行数据可视化的时候,往往需要调用很多的库与函数,还需要数据转换以及大量的代码处理编写。这都是十分繁琐的工作,确实只为了数据可视化我们不需要实现数据可视化的工程编程,这都是数据分析师以及拥有专业的报表工具来做的事情,日常分析的话我们根据自己的需求直接进行快速出图即可,而Pandas正好就带有这个功能,当然还是依赖matplotlib库的,只不过将代码压缩更容易实现。下面就让我们来了解一下如何快速出图。
fanstuck
2024/01/25
4962
数据分析之Pandas快速图表可视化各类操作详解
Pandas可视化综合指南:手把手从零教你绘制数据图表
数据可视化本来是一个非常复杂的过程,但随着Pandas数据帧plot()函数的出现,使得创建可视化图形变得很容易。
昱良
2019/09/24
2K0
Pandas可视化综合指南:手把手从零教你绘制数据图表
数据导入与预处理-拓展-pandas可视化
关于pandas的可视化的用法还有很多,这里不再拓展,但还是建议使用matplotlib,seaborn等库完成绘图。
用户2225445
2022/11/12
3.2K0
数据导入与预处理-拓展-pandas可视化
数据可视化干货:使用pandas和seaborn制作炫酷图表(附代码)
导读:我们介绍过用matplotlib制作图表的一些tips,感兴趣的同学可以戳→纯干货:手把手教你用Python做数据可视化(附代码)。matplotlib是一个相当底层的工具。你可以从其基本组件中组装一个图表:数据显示(即绘图的类型:线、条、框、散点图、轮廓等)、图例、标题、刻度标记和其他注释。
前端皮皮
2021/05/18
5.6K0
数据可视化干货:使用pandas和seaborn制作炫酷图表(附代码)
Python 数据可视化,常用看这一篇就够了
如果你想要用 Python 进行数据分析,就需要在项目初期开始进行探索性的数据分析,这样方便你对数据有一定的了解。其中最直观的就是采用数据可视化技术,这样,数据不仅一目了然,而且更容易被解读。
全栈程序员站长
2022/09/07
2.1K0
Pandas 高级教程——数据可视化
Pandas 提供了强大的数据可视化工具,可以帮助你更好地理解数据、发现模式和进行探索性数据分析。本篇博客将深入介绍 Pandas 中的数据可视化功能,并通过实例演示如何创建各种图表和图形。
Echo_Wish
2023/12/26
3600
五分钟入门数据可视化
在数据科学中,有多种工具可以进行可视化。在本文中,我(毛利)展示了使用Python来实现的各种可视化图表。
润森
2019/11/15
2.8K0
Python-Seaborn 17个超好看图表绘制
Seaborn是一个基于matplotlib且数据结构与pandas统一的统计图制作库。Seaborn框架旨在以数据可视化为中心来挖掘与理解数据。
DataCharm
2021/02/22
3.5K0
Python-Seaborn 17个超好看图表绘制
Python数据分析实战(3)Python实现数据可视化
数据可视化是指将数据放在可视环境中、进一步理解数据的技术,可以通过它更加详细地了解隐藏在数据表面之下的模式、趋势和相关性。
cutercorley
2020/08/31
4.6K0
推荐阅读
相关推荐
Pandas-25.可视化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档