首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 25-03-05 19:22
  • 3698
  • 9295
blog.csdn.net

本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索
HelloWorld杰少 即可关注。

前言

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

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

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

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

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

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

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

image

  • 选择右下角的新插件

image

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

image

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

image

处理第三方的 Framework

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

@protocol TestLoginDelegate 

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

@end


@interface JJLoginController : NSObject

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

@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 在 ThirdParty 文件夹下创建 iosframeworks 文件夹,随后再该文件夹下创建 iosextend.embeddedframework 文件夹,并将第三方的 framework 放入其中

image

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

image

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

编码阶段
  1. 在 Source 文件夹中插件为我们创建了以下源文件

image

  1. 打开 JJLoginNail.Build.cs,配置我们的第三方 framework 路径,配置信息如下:
// 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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  1. 打开 JJLoginNail.h 头文件,加入我们调用 API 的逻辑,以及处理回调的逻辑:
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Modules/ModuleManager.h"

#if PLATFORM_IOS
#import 

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


@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;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
注意点:

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

  1. 打开 JJLoginNail.cpp 文件,实现上一步头文件中定义的接口以及在 OC 类中实现回调函数
// 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)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
注意点:

其中需要注意的是:

  • 在调用 SDK 接口的时候需要切换到主线程上,不然 App 会 Crash;
  • 在使用 OC 代码的时候需要用 PLATFORM_IOS 进行包裹;
  • 因为我们在实现逻辑中用到了 IOSAppDelegate 获取 RootView,所以我们需要在 JJLoginNail.Build.cs 加入一个配置 “ApplicationCore”,不然会提示 IOSAppDelegate.h 头文件找不到,配置如下:
PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				"JJLoginNailLibrary",
				"Projects",
                "ApplicationCore"
				// ... add other public dependencies that you statically link with here ...
			}
			);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 回到我们插件文件夹上层文件夹的 Source 下,打开 UE 为我们自动创建的 Hydroger.Build.cs 文件,并在里面配置我们的插件名称 “JJLoginNail”, 代码如下:
// 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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  1. 在工程中打开我们在 UE 中创建的蓝图类 MyUserWidget.cpp,并在点击事件中加入调用插件接口的逻辑:
#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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
注意点
  1. 别忘了在 Hydroger.Build.cs 中配置插件名称
  2. include 插件头文件,例如:#include “JJLoginNail.h”
  3. 逻辑用 PLATFORM_IOS 包裹

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

image

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

image

  • 获取回调信息,并打印

image

结尾

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

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

相关阅读:

UE4 如何实现与 iOS 原生之间的数据交互
UE4 开发之如何创建 iOS 平台插件
UE4 开发之实现按钮事件响应
UE4 开发之配置 Xcode 调试环境

关注我的技术公众号,获取优质技术文章。
微信扫一扫下方二维码即可关注:
image

注:本文转载自blog.csdn.net的HelloWord杰少的文章"https://blog.csdn.net/shenjie12345678/article/details/111812429"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top