UE5 C++ 插件开发 1.开源

Posted CloudHu1989

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE5 C++ 插件开发 1.开源相关的知识,希望对你有一定的参考价值。

目录


0. 前言

关于是否将插件开源,自己挣扎了很久,最后选择开源的主要原因在于自己从开源社区受益太多,自觉有必要回馈开源社区.
自己很高兴回馈社区的超我战胜了需要满足自己经济需求的那个小我,这件事证明自己的格局比以前大了,这对自己和开源社区来说都是一件好事情.
至于这个付费专栏,自己无法取消付费,这个是平台写死的,可能是为那些已经付费的用户考虑,幸好现在没有人付费,这让自己感到如释重负.
开源地址在:https://github.com/cloudhu/SimpleShop
如果大家喜欢这个插件,可以点个关注,虽然短期内自己抽不出时间来更新,但是以后一旦抽出时间就会快速更新.


1. 反思

一直在和两个朋友开发游戏,为了拉投资自己就写了一份商业计划书草案,写这个草案的过程中进行了大量反思:

  • 游戏的核心竞争力是什么?
  • 游戏的核心价值观是什么?
  • 游戏可以给玩家带来什么?
  • 游戏可以给社会贡献什么?
  • 游戏可以回报投资人什么?

这些问题自己至今还没有想透彻,但是确让自己的方向变得无比清晰:自己要做的是前所未有的,对玩家有益,对社会有贡献,并且可以为投资人带来收益的游戏.
这一切都指向了一份新的商业计划书,这一份是接下来自己需要长时间需要更新和迭代的,直到这份商业计划书可以打动自己.
一份可以打动投资人的商业计划书首先是打动自己的,然后才能打动投资人,最终变成一款受到玩家和社会认可的产品,这个就是自己的反思所得,这些反思进一步让自

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

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

前言

在前俩篇文章中,我与大家分享了 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, 里面包含一个显示用户登录界面的接口,以及回调账户名的回调,参考代码如下:

@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 路径,配置信息如下:
// 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 的逻辑,以及处理回调的逻辑:
// 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 类中实现回调函数
// 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 头文件找不到,配置如下:
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”, 代码如下:
// 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,并在点击事件中加入调用插件接口的逻辑:
#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 插件步骤就结束了,其实并不是很难,就是配置的环节比较多,如果中间某一个环节掉了链子,那我们创建的插件就无法被工程所引用,所以在插件的使用过程中,需要仔细的去检查我们的配置。

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

相关阅读:

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

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

以上是关于UE5 C++ 插件开发 1.开源的主要内容,如果未能解决你的问题,请参考以下文章

UE5 使用Spine插件

UE5 使用Spine插件

UE5 使用Spine插件

[玩转UE4/UE5动画系统>C++篇>C++基础] 之 C++版模板中那些琐碎而又应知应会的语法知识小结(本文献给刚学完谭浩强就来啃UEC++的同学)

如何用UE5封装Protobuf插件

虚幻引擎UEUE4/UE5 功能性插件推荐及使用介绍