zoukankan      html  css  js  c++  java
  • UE4 IOS互相调用

    上篇文章讲了UE4安卓互相调用,这篇来看看IOS原生代码和UE4的关系。

    plist

    上篇文章提到了一个概念:UPL,在IOS代码编写里同样有使用UPL的地方,但对于IOS目前我所见到只是用于更改plist(UE 4.25.1 默认打包会产生下面这样一个 plist 文件info.plist,在一些特殊的需求中,需要往这个 plist 中添加元素或者修改以及删除。)

    ios 的 ipa 包中都会有 plist 文件,可以用来配置 app 的一些属性,apple 的开发者文档里对每个支持的 key 有详细的描述:iOS Keys

    在 UE 的项目设置中,可以给 plist 添加元素,在 Project Settings-Platform-iOS-Additional Plist data 中可以填入一个字符串,它会被插入到 plist 文件中:

    <key>AdditionalElementAAA</key>
    <string>this key is a test element.</string>
    

    中间的 是格式化代码,用于另起一行。

    如果想要修改或者删除 plist 的元素,需要通过 UPL 来写逻辑(当然也可以使用 UPL 来添加元素,建议使用这种做法)。

    <?xml version="1.0" encoding="utf-8"?>
    <root>
        <init>
            <log text="UPL Exalpme adding element to plist..."/>
        </init>
        <trace enable="true"/>
        <iosPListUpdates>
            <addElements tag="dict" once="true">
                <key>AdditionalElementAAA</key>
                <string>this key is a test element.</string>
            </addElements>
        </iosPListUpdates>
    </root>
    

    上面是用来添加元素的,上面的内容和直接写到 Additional Plist data 是一样的。

    遍历 plist 中的 key:

    <?xml version="1.0" encoding="utf-8"?>
    <root>
        <init>
            <log text="UPL Exalpme..."/>
        </init>
        <trace enable="true"/>
        <iosPListUpdates>
            <loopElements tag="dict">
                <loopElements tag="$">
                    <setStringFromTag result="TagName" tag="$"/>
                    <setBoolIsEqual result="bIsKey" arg1="$S(TagName)" arg2="key"/>
                    <if condition="bIsKey">
                        <true>
                            <log text="$S(TagName):$S(TagValue)"/>
                        </true>
                    </if>
                </loopElements>
            </loopElements>
            
        </iosPListUpdates>
    </root>
    

    注意:当前元素以 tag = "$" 方式引用。

    两种调用方式

    Framework

    通过给项目添加ios的framework库来添加ios功能

    这块我没有实践过,引用他人的案例来讲解

    https://blog.csdn.net/shenjie12345678/article/details/111812429

    image

    Build.cs文件

           if (Target.Platform == UnrealTargetPlatform.IOS){
                PublicAdditionalFrameworks.Add(
                    new Framework(
                        "TestLoginSDK",
                        "../ThirdParty/iosframeworks/iosextend.embeddedframework.zip"
                    )
                );
            }
    

    IOS 上的 Framework 有点类似于静态链接库的意思,相当于把.a+.h+ 资源打包到一块的集合体。更具体的区别描述请看:iOS 库 .a 与.framework 区别

    在 UE 中以集成 IOS 上操作 Keycahin 的 SSKeychain 为例,在 Module 的 build.cs 中使用 PublicAdditionalFrameworks 来添加:

    PublicAdditionalFrameworks.Add(
        new Framework(
            "SSKeychain",
            "ThirdParty/IOS/SSKeychain.embeddedframework.zip",
            "SSKeychain.framework/SSKeychain.bundle"
            )
    );
    

    构造 Framework 的第一个参数是名字,第二个是 framework 的路径(相对于 Module),第三个则是解压之后的 Framework 的 bundle 路径(如果 framework 没有 bundle 则可以忽略这个参数,而且就算有 bundle,但是不写这第三个参数貌似也没什么问题)。

    这种方法就是一开始将所有的IOS平台有关的代码封成库,然后在UE中的CPP函数中用一句OC的调用

    注意点:

    其中需要注意的是:

    • 在调用 SDK 接口的时候需要切换到主线程上,不然 App 会 Crash;

      • dispatch_async(dispatch_get_main_queue(), ^{
        //your code
        });
        
    • 在使用 OC 代码的时候需要用#if PLATFORM_IOS #endif 进行包裹;

    优缺点

    优点:部分代码可以不开源,成熟的模块可以拿来就用!便于进行分模块管理等等。如果有写ios的同学,直接让他给你整一个你只需要调用一下就好。

    缺点:和UE的交互有限,复杂的交互需求写起来比较麻烦。

    OC混编

    先不提OC的语法各种对CPP程序员反人类,OC混编的优点还是很棒的,其实你可能发现了,上面一种方法里的调用framework库的那一句代码就是oc代码,其实这就是混编了。不过这里的混编更为复杂,指将原先的ios的代码的类Interface、implementation直接写在cpp里。

    oc、c、 c++同根同源,他们的基础数据类型天然就能互相调用。

    使用OC混编其实可以直接引用ios的库文件,比如

    #import <UIKit/UIKit.h>
    

    很多sdk就是这么干的,这样代码可以大部分都放在一起,开发起来很方便,调试一下,想改oc就改oc,想改cpp就改cpp

    而且因为身在UE的工程环境下,oc的函数体里可以直接使用UE提供的一些类,当然还是要注意线程问题使用AsyncTask

    不过混编的时候执行顺序有时候让人比较困惑,比如我这边先写了NSLog,后写了UE_LOG,在日志中UE_LOG有可能先于NSLog执行,这块还是分开一点比较好,不要太过自由。

    优缺点

    很多的优点,上面提到了的都是优点,我在oc的函数体里直接excute UE作用域绑定的委托,传递数据,改ue代码和oc代码,xcode build->install->running都很快。

    缺点其实也比较明显,写小规模的代码还好,在很大量平台代码的情况下,要在没有代码提示的环境下写逻辑难度还是很大的,况且很多ios平台有一些成熟的代码的解决方案,直接以一个framework库提供更好

    扩展

    杰少这篇文章讲了UE4的委托和IOS的委托的交互

    https://blog.csdn.net/shenjie12345678/article/details/112168356#comments_15713973

    平台代码技巧

    小技巧:跨平台的代码可以封在不同的同名cpp文件中(分平台名字,编辑器会识别到对应的平台),这样在不同的平台编译的时候只会取对应文件夹下的cpp文件,不会产生重定义

    采坑

    提示xml is missing

    字符串IosPlugin 能找到xml文件,IOSPlugin找不到xml,奇怪的拼写检查。

    AdditionalPropertiesForReceipt.Add(new ReceiptProperty("IosPlugin",System.IO.Path.Combine(PluginPath,"IOS/PlatformCommon_APL_IOS.xml")));
    

    IOS截图

    截图的传递到ue4的思路很简单,把图片数据转化成字节数组,然后参数传到UE4后,通过这个buffer再解析出图片

    使用UIImagePNGRepresentation传到UE4后转换成Texture2D发现显示失败,是一个透明图

    定位后发现ios的截图默认为png,64位深,UE4对应处理图片的ImportBufferAsTexture2D接口在处理png64的时候不报错但是无法正确处理。

    使用UIImageJPEGRepresentation在IOS层把图片转成jpg解决问题。

  • 相关阅读:
    模块之间的消息传递优势与问题
    cp命令
    gimp的python控制台生成UI代码
    three.js(六) 地形法向量生成
    mysql 主从复制配置
    Three.js(九)perlin 2d噪音的生成
    three.js(五) 地形纹理混合
    mongodb 复制
    pycparse python的c语法分析器
    ajax出现 所需的数据还不可用
  • 原文地址:https://www.cnblogs.com/FlyingZiming/p/14648517.html
Copyright © 2011-2022 走看看