面向UE4新手----基于UE4的室内软装系统设计和实现思路


由于一直有朋友在与我讨论关于UE4室内软装的系统设计问题,问题也都大同小异,正好类似项目有一些经验,因此在此分享给大家,希望能帮助更多UE4的新手和小团队。

由于我本人是独立游戏开发者而非室内设计方向的,并且当初这个项目是基于VR的,本身需求更多一些,因此在此分享一个简化版的,通过传统键鼠操作的设计思路,抛砖引玉。

后续可能还会继续更新更多相关的内容。

需求分析

由我个人所接触的项目来看,基于UE4的室内框架主要分成两个方向,一种是VR的操作方式,另一种是传统的鼠标操作模式,虽然部分核心逻辑变化不大,但这两种模式在架构上有比较大的出入。

原因1是UE4在4.15后加入了原生的VR支持,在早先的版本中对于3D widget并不能直接做射线操作,因此需要额外的插件或深入底层写针对widget component的VR交互扩展。并且扩展后的插件和代码也不容易移植到新版本的引擎上。

原因2是不论VIVE还是Oculus,手柄的VR交互和鼠标的交互不同,手柄是基于位于Player Character中的LR Controller组件进行操作的,而鼠标相关的逻辑则主要靠Player Controller进行控制。导致相关需求和逻辑需要进行重新评估。同时HMD并不能显示HUD,所以传统使用HUD进行显示的逻辑也必须重新设计。

在这里主要写核心业务逻辑的设计思路,因此使用了传统鼠标的交互方式,Input部分只用传统的按键映射来进行,而对于基于UE4进行VR室内项目的开发者,可以将Input部分根据需求使用LR Controller组件的OnComponentBegin/EndOverlap事件来替代按键映射进行交互判定。并且将本文中出现的Get Hit Result Under Cursor By Channel函数替换成Line Trace By Channel函数。并根据需求进行修改。

在这个例子中,我们需要完成以下多个需求。

1,自适应UI,动态生成家具按钮,并且自动排列对齐。

2,鼠标点击按钮进行交互,放置家具到场景中。

3,根据鼠标指向,即时调整家具位置。

4,自动吸附其他家具,智能判断可以被放置的家具类型和位置。

5,根据不同家具类型进行交互。

设计要点

1,尽量多用实例化,通常新手对于UE4会直接调用某个BP的父类,这个习惯并不好,因为直接调用父类增加了扩展的成本,编译的时候也增加了时间成本。

2,尽量使用抽象简单的数据存储方式,比如DataTable,Enum和Structure Array等,因为这样在上项目的时候不需要再深入到不同bp去做调整,只需要很少的几次点击即可。

3,易于扩展,对于未来可能的扩展预留好入口。

按键映射

E-Interaction

Left Mouse Button-ActionConfirmation

实现过程

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第1张图片

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第2张图片
首先是需要创建的核心类和文件结构,除了基本的

1,Gamemode(GM_Interior)

2,PlayerController(C_Interior)

3,PlayerCharacter(PC_Interior)

以外,还需要创建

1,GameInstance(GI_Interior)**(对于室内的框架,经常可能更换地图,并且极端情况下可能更换PlayerCharacter,因此把数据存入GameInstance作为全局的储存是一个好习惯,更多信息可以参考官方文档中的Game Framework章节)**

2,Enum(E_FurnitureType)枚举(包含了所有的家具类型)

3,Structure(S_FurnitureClass)结构体(包含了一个家具所需要的所有信息)

4,UMG(UMG_Main)(用于约束生成的按钮位置)

5,UMG(WC_Button)(这也是一个UMG,区别在于,UMG_Main中的所有组件都是Canvas Panel的组件,而UMG_Button则是单独的一个Button,不属于Canvas Panel,创建的时候需要把Canvas Panel删去。因此命名時使用了WC前缀代表WidgetComponent)

6,Actor BP(BP_Furniture_Master)(所有Furniture的父类,用于处理所有对Furniture的操作。)

正式开始构建框架

这里写图片描述

1,首先是枚举E_FurnitureType中需要的家具类型

    1,Chair

    2,Floor

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第3张图片

2,定义Structure的元素,分别是

    1,String:Name(家具的名称)

    2,E_FurnitureType:Type(这就是之前创建的枚举)

    3,Actor-Class:Actor(注意是Actor Class而非Actor Reference,因为Actor的引用只能在Runtime時进行动态赋值。)

    4,Texture2D:Image(家具的图片,用于作为按钮样式的图片)

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第4张图片

3,进入BP_Furniture_Master,创建一个Box Collision和一个Static Mesh,同时创建四个变量:

    1,E_FurnitureType:FurnitureType(本家具的类型,用于后续扩展或直接在场景中修改类型。注意没有任何家具应该被分配成Root类型)

    2,String:Name(本家具的名字,用于后续扩展或直接在场景中修改显示名称。)

    3,Array[E_FurnitureType]:CanPlacedOnActorType(可被放置到的家具类型数组,当一个家具不能被放置到任何家具上时,留空数组。)

    4,Boolean:CanBeInteracted(能否被操作,如果为否,则不接受用户操作输入。)

接着从BP_FurnitureMaster中实例化出

    1,BP_FloorMaster

    2,BP_ChairMaster

    3,再分别从BP_FloorMaster和BP_ChairMaster中实例化出BP_Floor_Init和BP_Chair_Init。(后续所有的家具都根据其类型的MasterBP实例化出来。)

    4,进入BP_Floor_Master,定义其类型为Floor,并且由于其不能被放置在任何家具类型上,将CanPlacedOnActorType数组的值留空。

    5,进入BP_Chair_Master,定义其类型为Chair,并且由于其能被放置在Floor家具类型上,将CanPlacedOnActorType数组中添加一个元素,赋值为Floor。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第5张图片

4,进入GI_Interior,创建:

    1,Array[S_FurnitureClass]:FurnitureMaster数组。并赋值以便于测试用。注意赋值的Actor需要选择为已经实例化后的Actor。

    2,Actor-Reference:OverlappingActor:这个Actor对象用于储存当玩家进入家具的可操作体积時,将自身储存到Game Instance以便于让其他类访问到,用于后续扩展,当然也可以使用接口或者直接在Player Character类中创建。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第6张图片

5,在WC_Button中,删除Canvas Panel,创建Button和Text组件,并调整样式。将Button和Text都设置为变量(右上角Is Variable设置为true)。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第7张图片

6,在WC_Button中,创建OnPressed事件和OnReleased事件。并创建:

    1,Actor-Class:SelfReference

    2,E_FurnitureType:FurnitureType

基本逻辑是,当用户按下按钮時,生成相应的对象,并且设置为隐藏。当用户松开按钮时,显示对象,同时每帧tick对象的世界位置。如果图片太小的话可以下载文后完整的项目。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第8张图片

7, 在UMG_Main中,放置一个Horizontal Box组件于Canvas Panel下,并将其Is Variable属性设置为True。同时将Anchors锚点设置为屏幕正中心,完成自适应。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第9张图片

8,在UMG_Main的Graph中,核心逻辑为,从GameInstance中提取出用户定义的S_FurnitureClass数组,并且loop该数组,对每个元素生成WC_Button,并对按钮的样式和文字进行赋值,完成后,使用Slot As函数将其对应的对其功能设置好(set size和set horizontal alignment)

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第10张图片

9,在PC_Interior中,将Show Mouse Cursor设置为TRUE,同时Enable Click Event,Enable Mouse Overlap Event也设置为true,便于日后扩展。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第11张图片

10,在C_Interior中,主要写以下五条功能。

    1,在载入用户后,生成菜单,并渲染至用户屏幕。

    2,如果用户按下鼠标生成对象后松开鼠标进入放置阶段,判断是否条件允许放置对象,如果可以,每帧tick对象位置,并update到Final Location向量变量。

    3,用户在世界中再次按下鼠标,确认对象放置。

    4,当用户按下交互按键时,判定是否存在可交互对象,以及是否满足交互前置条件。如果允许,调用交互事件。

    5,交互事件,根据被交互对象中的E_FurnitureType键值,使用switch关键字来分离针对不同类型的不同交互方式。

面向UE4新手----基于UE4的室内软装系统设计和实现思路_第12张图片

11,在BP_Furniture_Master中,创建OnActorBeginOverlap事件和OnActorEndOverlap事件,并写如下逻辑。

    1,判断进入交互体积的对象是否是用户,如果是,将自身actor存入Game Instance。

    2,判断离开交互体积的对象是否是用户,如果是,将Game Instance中的OverlappingActor设置为空。

小结

这个例子是一个非常简单的小框架,从空项目开始只用了大约两个小时进行搭建,真正的合同项目也采用类似的思路,但是由于需求更多更复杂,扩展的需求也更多,还是不免遇到对项目修改的大动作,因此在设计时就需要抽象的进行逻辑的编写,考虑到未来可能的扩展需求,保证所有的逻辑都不被约束死。举个例子,在一开始的版本中,CanPlacedActorType是一个single变量而不是Array,但实现的时候稍加考虑就会发现,一个家具应该被允许被放在多种家具类型上,比如蜡烛既可以放在桌子上,也可以放在柜子上。如果变量不是Array的话,后续的扩展就需要进入C_Character中进行多重判定,导致相似的业务逻辑不能被重用,增加了扩展的工作量和难度。

写在最后

由于我本人并不是做室内设计的,因此如果有更好的解决方案和意见,欢迎讨论。后续的更新也会写在这里。

附件

链接:http://pan.baidu.com/s/1i5HqtEX 密码:17lw

你可能感兴趣的:(经验分享)