c++排序函数对二维数组排序_第2期 UE4 C++实现任意类型数组蓝图排序节点

1. Overview

本教程旨在讲解在虚幻引擎(UE4) c++中实现蓝图(Blueprint)可调用的任意类型数组排序的蓝图节点。纯蓝图实现任意类型数组排序方法,请查看第1期 在蓝图实现任意类型数组排序特别声明,本篇文章主要代码来源于网络,本人仅做综述性整理与回顾(review), 如有侵权,请联系删除。编者水平有限,如有错漏敬请谅解。

2. Introduction

排序算法是开发过程中常用的一类算法,使用ue4进行开发不可避免的要用到排序算法。若仅使用ue4 c++进行内容开发,可以直接调用c++ stl中的排序算法,就可以实现数组排序。由于ue4 c++本身并没给蓝图系统(Blueprint System)提供任意类型数组排序的节点,因此当同时使用ue4 c++和Blueprint(BP)完成逻辑功能,如何在ue4 c++ 中实现一个任意类型数组排序蓝图节点,就成为一个值得深究的问题。

本文主要讲解ue4 c++实现任意类型数组排序的蓝图节点方法和原理,以及该节点在Blueprint中的使用方法。

3. Required Knowledge

1.熟悉ue4 c++的语法规则

2.了解ue4 反射机制和使用方式;

4. Why

Blueprint中常使用的类型,除基本类型(int/float/sting/vecto/transform…)外,其他最为常用的大类是UStruct类 和UObject派生类。这二大类伴随整个开发过程,并且随时会增加新的UStruct类型和UObject派生类。

如前所述,当开发人员同时使用ue4 c++和Blueprint进行开发时,开发人员无法预知将要用到的所有类型对象(UClass/UStruct),难以给每一种需要进行排序的类型定义排序方法来,并暴露给Blueprint;主要原因是blueprint不支持C++的模板,无法直接将一个C++模板函数暴露给蓝图。但是Blueprint支持Wildcard(通配符)类型参数,举例来说Blueprint System中Utilities|Array目录下的蓝图节点都是通配符类型的蓝图节点,对于任意类型数组都可以使用同一个蓝图节点实现该数组的Add/Clear/Find的方法。因此 在ue4 c++实现接收任意数组类型的蓝图节点 (Blueprint Node)是理论可行的。

5. Sort Approach

下面介绍在ue4 c++中实现排序的蓝图节点实现方法。排序的关键在于如何比较二个数组成员的大小,对于任意类型数组,由于在未连接该蓝图节点之前,并不知道该数组成员比较大小的方法,因此实现任意类型数组排序的蓝图节点,不仅要知道数组还需要知道大小比较的方法。通常要知道二个数组成员的大小比较结果有二种方式:

其一:基于FindFunction方法,ue4 UObject支持根据名称(FunctionName)查找的函数,并且可以在不知道该函数具体实现的时候直接调用。因此在排序节点上传入一个函数名FunctionName,在c++中需要比较二个成员大小时,直接调用该比较函数进行大小比较,并将结果作为二个数组成员的大小比较结果。

其二,基于FindField方法,由于ue4 UStrcut/UObject均支持属性(UProperty)的查找和遍历,因此可以通过传入一个PropertyName查找该数组成员的UPropery以及对应的Value值,使用该Value值来进行大小比较,并将比较结果作为二个数组成员的比较结果。

5.1 基于stl库非通用蓝图排序节点

创建以Blueprint Function Library为基类c++类,在该类的头文件(.h文件)中定义待排序的结构体类型 (本例为FSortStruct),并在头文件中声明排序函数,示例如下

UFUNCTION

在源文件(.cpp)实现该排序方法

void 

编译完成后,可以在蓝图中找到该节点

47e680597a3e02b4cb4b4dd4b695d130.png
非通用结构体数组排序节点

点评

优点:实现方法简单,本质上是调用stl库中的排序算法,因此算法效率高,这也是实现蓝图排序节点最为常用的一种方法。

缺点:不支持通配符类型数组,无法重用。

5.2 基于FindFunction方法实现通用蓝图排序节点的方法

该方法来源于 邱子鉴,西山居技术中心,地址:http://tech.seasungame.com/blog/index.php/2017/08/14/ue4-zailantuzhongshixianshuzupaixugongneng/

源代码:

UFUNCTION

使用方法示例:

e999c3f02ca2b8708929a20e4134873c.png
通用排序节点使用示例

3ebb4277f04582689b1bf4c727ca089d.png
排序蓝图节点的自定义排序函数示例

9690a44c36716fe5899695dd0f9e6fc0.png
排序结果

点评:

优点:支持任意类型数组排序,如(UObject、UStruct以及基本类型(int, float…)),自定义排序数组成员比较方法,大大扩展了该排序节点的使用场景,如当第一个变量相等时,比较第二个变量的情况。

缺点:该方法基于冒泡排序方法,冒泡排序时间复杂度最坏的情况是O(n^2),效率较低。

5.3 基于FindField方法实现通用蓝图排序节点的方法

该方法来源于 https://github.com/EverNewJoy/VictoryPlugin,VictoryBPFunctionLibrary::Array_Sort()

// .h file

/**

// .cpp file

//Reference: https://github.com/EverNewJoy/VictoryPlugin

特别提醒:上述代码在原始代码的基础上添加一个函数Algorithm::FindField(),用于支持蓝图结构体(在蓝图中定义的结构体)数组排序时,无法查找到UProperty问题。

修改的位置:

UProperty

使用方法示例:

bec429842d9225c104b7fd24b20e50d8.png
通用排序节点使用示例

结果输出:

39ea0d3f0e677256ceb64ec437b67c46.png
排序结果输出

点评

优点:支持任意类型UStruct和UObject子类数组的排序。

缺点: 仅支持一个变量参数的比较,不支持基本类型数组排序。该方法仍然是基于冒泡排序算法,效率低于stl排序算法。

6. Conclusion

本文主要介绍了二种 ue4 c++实现任意类型数组排序蓝图节点的方法,用于满足日常开发的蓝图排序需求。由于二者均为冒泡排序原理,算法效率一般低于的stl排序算法。

进阶版:基于stl排序算法的任意类型数组排序节点的实现,待完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值