首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >UE4 开发之如何创建 iOS 平台插件

UE4 开发之如何创建 iOS 平台插件

作者头像
HelloWorld杰少
发布于 2022-08-04 05:58:30
发布于 2022-08-04 05:58:30
1.2K00
代码可运行
举报
文章被收录于专栏:HelloWorld杰少HelloWorld杰少
运行总次数:0
代码可运行

前言

在前俩篇文章中,我与大家分享了 UE4 开发如何配置 Xcode 调试环境以及如何实现 UE4 引擎的按钮事件响应,其实写这俩篇文章的目的就是为接下来的文章做一个引子,就好比是高级餐厅的前菜一样,接下来我们就要正式进入到正餐部分了.

既然 UE4 引擎具有跨平台的特性,那是否真的能像很多跨平台开发工具所说的一样:Write once, run everywhere 呢!我调研过市面上主流的几个跨平台开发工具,也自己动手搭建过环境并写了几个 Demo,我只想跟大家说:谁用谁知道(捂脸笑)。

每个平台都有自己的特性,要想做到一份代码适配所有平台的难度是非常大的,因为一个产品是有无数的功能组成的,我们不能保证每个功能都做到完美适配,所以怎么去解决当前面临的窘境呢!那就是我们要尽量减少跨平台功能的数量,只保证我们的核心功能在各个平台上能完美的适配,把一些辅助功能模块例如:登录,分享,数据采集等模块独立出来做成插件,然后集成到我们的项目中去,这些插件都是用各个平台的原生代码开发的,iOS 平台就用 OC 或者 swift 开发,Android就用 java 或者 kotlin 开发,所以完全就不用去考虑它的平台兼容性问题了。

那接下来我们就开始今天的教程吧!

UE4 开发之如何创建 iOS 平台插件

UE4 为我们广大开发者提供了众多的插件供我们使用,正是有了这些插件的存在,才让游戏开发变得更快更简单,今天我跟大家分享一下如何开发 UE4 插件。

创建 UE4 插件

•在 UE 编辑器中,打开菜单栏中的编辑下拉菜单,选择插件选项

•选择右下角的新插件

•选择截图上的 "第三方库", 并填写插件名称,例如我起的为 "JJLoginNail",以及填写作者以及描述

•创建完成后,会在你的 Xcode 工程中自动引用一个 Plugins 文件夹

包装 Framework

为了测试,我自建了一个 iOS 静态库:TestLoginSDK.framework, 里面包含一个显示用户登录界面的接口,以及回调账户名的回调,参考代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@protocol TestLoginDelegate <NSObject>

- (void)OnLoginResult:(NSString *)result;

@end


@interface JJLoginController : NSObject

+ (void)showLoginView:(UIViewController *)baseView JJCallBack:(id<TestLoginDelegate>) delegate;

@end

•在 ThirdParty 文件夹下创建 iosframeworks 文件夹,随后在该文件夹下创建 iosextend.embeddedframework 文件夹,并将第三方的 framework 放入其中

•将 iosextend.embeddedframework 添加到 .zip 压缩文件•将 iosframeworks 引入到 Xcode 工程中

前期准备做好以后,我们现在进入到正式的敲代码阶段.

编码阶段

1.在 Source 文件夹中,新建的插件为我们创建了以下源文件

1.打开 JJLoginNail.Build.cs,配置我们的 framework 路径,配置信息如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class JJLoginNail : ModuleRules
{
    public JJLoginNail(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicIncludePaths.AddRange(
            new string[] {
                // ... add public include paths required here ...
            }
            );


        PrivateIncludePaths.AddRange(
            new string[] {
                // ... add other private include paths required here ...
            }
            );


        PublicDependencyModuleNames.AddRange(
            new string[]
            {
                "Core",
                "JJLoginNailLibrary",
                "Projects",
                // ... add other public dependencies that you statically link with here ...
            }
            );


        PrivateDependencyModuleNames.AddRange(
            new string[]
            {
                // ... add private dependencies that you statically link with here ...    
            }
            );


        DynamicallyLoadedModuleNames.AddRange(
            new string[]
            {
                // ... add any modules that your module loads dynamically here ...
            }
            );

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

1.打开 JJLoginNail.h 头文件,加入我们调用 API 的逻辑,以及处理回调的逻辑:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Modules/ModuleManager.h"

#if PLATFORM_IOS
#import <TestLoginSDK/TestLoginSDK.h>

//用于处理 sdk 返回的回调
@interface FTestLoginResultModule : NSObject<TestLoginDelegate>


@end

#endif

class FJJLoginNailModule : public IModuleInterface
{
public:

    /** IModuleInterface implementation */
    virtual void StartupModule() override;
    virtual void ShutdownModule() override;


    /// 显示登录界面
    void showLogin();

private:
    /** Handle to the test dll we will load */
    void*    ExampleLibraryHandle;
};

注意点:

其中我们的 OC 类别需要用 PLATFORM_IOS 宏包起来,并 import 我们所需要的第三方framework。

1.打开 JJLoginNail.cpp 文件,实现上一步头文件中定义的接口以及在 OC 类中实现回调函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

#include "JJLoginNail.h"
#include "Core.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#include "JJLoginNailLibrary/ExampleLibrary.h"

#define LOCTEXT_NAMESPACE "FJJLoginNailModule"


#if PLATFORM_IOS
#include "IOSAppDelegate.h"
@implementation FTestLoginResultModule

- (void)OnLoginResult:(NSString *)result{
    NSLog(@"登录账号为: %@", result);
}

@end
#endif

#if PLATFORM_IOS
static FTestLoginResultModule *loginResult = nil;
#endif

void FJJLoginNailModule::showLogin(){
    #if PLATFORM_IOS
    dispatch_async(dispatch_get_main_queue(), ^{
        [JJLoginController showLoginView:(UIViewController*)[IOSAppDelegate GetDelegate].IOSController JJCallBack:[FTestLoginResultModule new]];
    });
    #endif
}


void FJJLoginNailModule::StartupModule()
{
    // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module

    // Get the base directory of this plugin
    FString BaseDir = IPluginManager::Get().FindPlugin("JJLoginNail")->GetBaseDir();

    // Add on the relative location of the third party dll and load it
    FString LibraryPath;
#if PLATFORM_WINDOWS
    LibraryPath = FPaths::Combine(*BaseDir, TEXT("Binaries/ThirdParty/JJLoginNailLibrary/Win64/ExampleLibrary.dll"));
#elif PLATFORM_MAC
    LibraryPath = FPaths::Combine(*BaseDir, TEXT("Source/ThirdParty/JJLoginNailLibrary/Mac/Release/libExampleLibrary.dylib"));
#endif // PLATFORM_WINDOWS

    ExampleLibraryHandle = !LibraryPath.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPath) : nullptr;

    if (ExampleLibraryHandle)
    {
        // Call the test function in the third party library that opens a message box
        ExampleLibraryFunction();
    }
    else
    {
        FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ThirdPartyLibraryError", "Failed to load example third party library"));
    }
}

void FJJLoginNailModule::ShutdownModule()
{
    // This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
    // we call this function before unloading the module.

    // Free the dll handle
    FPlatformProcess::FreeDllHandle(ExampleLibraryHandle);
    ExampleLibraryHandle = nullptr;
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FJJLoginNailModule, JJLoginNail)

注意点:

其中需要注意的是:

•在调用 SDK 接口的时候需要切换到主线程上,不然 App 会 Crash;•在使用 OC 代码的时候需要用 PLATFORM_IOS 进行包裹;•因为我们在实现逻辑中用到了 IOSAppDelegate 获取 RootView,所以我们需要在 JJLoginNail.Build.cs 加入一个配置 "ApplicationCore",不然会提示 IOSAppDelegate.h 头文件找不到,配置如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PublicDependencyModuleNames.AddRange(
            new string[]
            {
                "Core",
                "JJLoginNailLibrary",
                "Projects",
                "ApplicationCore"
                // ... add other public dependencies that you statically link with here ...
            }
            );

1.回到我们插件目录上层的 Source 下,打开 UE 为我们自动创建的 Hydroger.Build.cs 文件,并在里面配置我们的插件名称 "JJLoginNail", 代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class Hydroger : ModuleRules
{
    public Hydroger(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "JJLoginNail"});

        PrivateDependencyModuleNames.AddRange(new string[] {  });

        // Uncomment if you are using Slate UI
        // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");

        // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
    }
}

1.在工程中打开我们在 UE 中创建的蓝图类 MyUserWidget.cpp,并在点击事件中加入调用插件接口的逻辑:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "MyUserWidget.h"
#include "JJLoginNail.h"

void UMyUserWidget::callStartFunction()
{
//    FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, TEXT("start"), TEXT("callStartFunction"));
    #if PLATFORM_IOS
    FJJLoginNailModule *module = new FJJLoginNailModule();
    module->showLogin();
    #endif
}

注意点

1.别忘了在 Hydroger.Build.cs 中配置插件名称2.include 插件头文件,例如:#include "JJLoginNail.h"3.逻辑用 PLATFORM_IOS 包裹

最后,插上真机设备,在工程中设置好相应的签名证书,CMD+R 将工程跑在真机设备上:

•触发按钮事件,调用 SDK 里面的接口

•获取回调信息,并打印

结尾

这就是 UE4 引擎创建 iOS 插件的步骤,其实并不是很难,就是配置的环节比较多,如果中间某一个环节掉了链子,那我们创建的插件就无法被工程所引用,所以在插件的使用过程中,我们需要仔细的去检查配置。

好了,本篇教程到这里就结束了,如果遇到问题可通过留言的方式与我交流,希望本篇文章对大家有所帮助,蟹蟹。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HelloWorld杰少 微信公众号,前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
HDU - 2024 C语言合法标识符
C语言标识符是指用来标识某个实体的一个符号,在不同的应用环境下有不同的含义,标识符由字母(A-Z,a-z)、数字(0-9)、下划线“_”组成,并且首字符不能是数字,但可以是字母或者下划线。例如,正确的标识符:abc,a1,prog_to。
种花家的奋斗兔
2020/11/12
6950
哪个不是python合法的标识符_哪个不是python合法标识符
2. 剩下的字符可以是字母,数字和下划线,即不能包含除了下划线以外的符号(空格,运算符...)。
用户7886150
2021/01/20
3.3K0
HDOJ 2024 C语言合法标识符
Problem Description 输入一个字符串,判断其是否是C的合法标识符。
谙忆
2021/01/20
4490
java 键盘输入多种方法
一、java不像C中拥有scanf这样功能强大的函数,大多是通过定义输入输出流对象。常用的类有BufferedReader,Scanner。 实例程序: 1、利用 Scanner 实现从键盘读入integer或float 型数据
全栈程序员站长
2022/09/08
7370
06:合法 C 标识符
06:合法 C 标识符 总时间限制:1000ms内存限制:65536kB描述。 C语言标识符要求: 1. 非保留字; 2. 只包含字母、数字及下划线(“_”)。 3. 不以数字开头。 输入一行,包含一个字符串,字符串中不包含任何空白字符,且长度不大于20。输出一行,如果它是C语言的合法标识符,则输出yes,否则输出no。样例输入 RKPEGX9R;TWyYcp 样例输出 no 来源北京大学 计算概论 06 心理及信管 期末考试 1 #include<iostream> 2 #include<cstdio
attack
2018/04/03
1.2K0
Java之标识符与变量
文章目录 1. 关于java语言当中的标识符 2. 关于字面值: 3. 关于java语言当中的变量: 4. 关于java中的变量:变量的作用域 4. 关于变量的分类:根据变量声明的位置来分类: 1.
兮动人
2021/06/11
4710
Java之标识符与变量
挖新坑—Java
只记录Java最入门的内容,模块并不完整,更深入的知识在Java基础、Java提高、JavaWeb模块
用户6948990
2025/04/03
620
挖新坑—Java
java标识符有哪些_java标识符有哪些?java标识符有哪些不合法?
数字是指0~9,字母指大小写英文字母、下划线(_)和美元符号($),也可以是Unicode字符集中的字符,如汉字;
全栈程序员站长
2022/09/17
1.9K0
Java编写的C语言词法分析器
    这是java编写的C语言词法分析器,我也是参考很多代码,然后将核心代码整理起来,准备放在QQ空间和博客上,目的是互相学习借鉴,希望可以得到高手改进。这个词法分析器实现的功能有打开文件、保存文件、打开帮助文档、文本域内容的剪切和复制和黏贴、进行词法分析 程序的项目结构如图,Word类和Unidentifiable类是两个JavaBean类,存放的参数有两个row(整型)、word(String),row用于获取行数,word用于获取标识符,LexerFrame是词法分析器的界面类,Analyze封装了进行词法分析的核心代码 ,doc文件夹放一个帮助文档,当用户点击帮助按钮时可以弹出来以帮助用户使用。 Github项目链接:https://github.com/u014427391/lexer1.1.0,欢迎star //核心程序:
SmileNicky
2019/01/17
1.3K0
词法分析程序
程序分为4个关键方法,用户输入方法,读、写文件方法以及词法分析方法。其中词法分析方法是程序的核心。 词法分析程序主要分为两个部分,第一是取词,第二是分析。 取词阶段: 依次取字符串的每一个字符,遇到空字符时停下,将取到的字符合并成一个字符串,送去进行分析阶段。 分析阶段:程序先构建有关键字数组、分隔符数组和运算符数组,通过将取词阶段送来的字符串与各数组中元素进行比较,将字符串分类到相应的类别数组中保存。 词法分析伪代码如下: While (源码字符串没有取完){ Getchar(获取一个非空字符);
SuperHeroes
2018/05/30
1.1K0
剑指Offer(四十九)-- 把字符串装换为整数
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。数值为0或者字符串不是一个合法的数值则返回0
秦怀杂货店
2022/02/15
3080
剑指Offer(四十九)-- 把字符串装换为整数
java怎么键盘录入字符串
先写上:import java.util.Scanner //导入 java.util 包下的 Scanner 类,导入后才能使用它
全栈程序员站长
2022/09/13
9110
java怎么键盘录入字符串
Java学习笔记_零基础系列(五)详解标识符、关键字和变量
1.标识符只能由数字、字母(包括中文)、下划线(_)、美元符号($)组成,不能含有其他符号。
牛仔码农
2021/07/09
7830
习题:标识符判断
关于C语言标识符,这道2017年上海市高等学校计算机等级考试二级C三套试卷其中一套最后一道编程大题,我们来讲解下:
用户6755376
2020/03/19
5370
习题:标识符判断
Java IO流笔记
处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读x写功能。
乐心湖
2020/07/31
1K0
Java IO流笔记
SQL server合法标识符
~~ 数据库名是一个标识符,表名也是一个标识符,在SQL SERVER中标识符分为两类:
且陶陶
2023/04/12
6350
Java(2)-Java IO输入输出流
Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。
黄规速
2022/04/14
8960
Java(2)-Java IO输入输出流
几道 BAT 算法面试中经常问的「字符串」问题
题目来源于 LeetCode 第 125 号问题:验证回文串。这道题目是 初级程序员 在面试的时候经常遇到的一道算法题,而且面试官喜欢面试者手写!
五分钟学算法
2019/05/06
8400
几道 BAT 算法面试中经常问的「字符串」问题
java标识符与关键字_4、Java标识符和关键字
标识符:Java对各种变量,方法和类等要素命名时使用的字符序列称为标识符。(凡是自己可以起名的地方都叫标识符,都遵循标识符的规则)
全栈程序员站长
2022/09/08
3400
Java语言
Java分为3个体系,为JavaSE,JavaEE,JavaME,是一种面向对象的程序设计语言,记住Oracle公司收购了 Sum公司,然后Oracle公司就负责了Java语言的维护。
达达前端
2019/07/03
1.9K0
Java语言
相关推荐
HDU - 2024 C语言合法标识符
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验