blog
blog copied to clipboard
虚幻引擎5 之旅 Unreal Engine 5 Tutorials
虚幻引擎5 之旅 Unreal Engine 5 Tutorials
模块化角色
https://docs.unrealengine.com/5.3/zh-CN/working-with-modular-characters-in-unreal-engine/ 通过组合多个骨骼网格体组件来创建角色。
How to Make Modular Characters with Body Parts in Unreal Engine 5 - Leader Pose Component 用身体部位制作模块化角色
https://www.youtube.com/watch?v=CeaSv7eiWo8
[UE5]Building Modular Characters in Unreal Engine 在虚幻引擎中构造模块化角色
https://youtu.be/7IUpa3Pxqug https://www.bilibili.com/video/BV1we4y1M7SV/?spm_id_from=333.337.search-card.all.click&vd_source=f259d77343588259f8e1b4ae567b1d34 使用UE5 Lyra示例项目作为样例,本会话将讨论添加、交换和自定义角色的各种可用技术。
Stylized Character Kit: Casual 01 风格化角色套件 https://www.unrealengine.com/marketplace/zh-CN/product/stylized-male-character-kit-casual?lang=zh-CN
新建 基于Actor的角色蓝图 BP_ModularCharacter
打开 BP_ModularCharacter
选择风格化角色套件下的多个人物网格体
拖入 BP_ModularCharacter
选择 MESH_L_01 腿部组件
-细节-动画-动画模式-使用动画资产
要播放的动画-ThirdPersonIdle
此时,只有腿部有动画。其他部位静止。
重命名各个部分: FaceAccessory 脸部附属品 Hair 头发 Beard 胡须 Head 头 LowerBody 下肢 Hands 双手 UpperBody 上肢
删除重复的上肢
将 UpperBody 上肢 附加到 LowerBody 下肢 将 Hands 双手,Head 头 附加到 UpperBody 上肢 将 FaceAccessory 脸部附属品,Hair 头发,Beard 胡须 附加到 Head 头。
此时,依然只有下肢在运动
事件图表
construction script 事件图表:
设置引领姿势组件 set leader pose component Lower Body 为领导者组件
其他部位组件全部为目标组件 FaceAccessory 脸部附属品 Hair 头发 Beard 胡须 Head 头 Hands 双手 UpperBody 上肢
下肢组件的骨骼动画将复制到内存中,
其他组件如果有相同的骨骼将使用该动画。
头发没有骨骼将不会使用骨骼动画。
优点是高性能,
缺点是其他部分都需要配套骨骼。
现在整个角色的全部网格体都会播放下肢同样的动画。
为角色附加背包,武器等网格体
添加一个网格体SM_Bag到 上肢组件子级
将 网格体SM_Bag 附加到角色的插槽上
网格体SM_Bag -细节-插槽-父项套接字-spine_03 这里可以显示上肢的所有骨骼
此时背包位置仍需要调整
在此处直接调整背包位置,将不能适应角色的其他情况,例如角色使用披风而非背包。
应该在上肢骨架中添加插槽,然后调整骨架的插槽位置。
在 MESH_T_03 上肢骨骼网格体资产中添加背包等物品的插槽
在Spine_03骨骼处添加插槽 attach_backpack
attach_backpack 添加预览资产 背包网格体
调整attach_backpack位置
BP_ModularCharacter 角色红 SM_Bag 背包网格体使用插槽
网格体SM_Bag -细节-插槽-父项套接字-attach_backpack
将背包替换为带骨骼和物理资产的骨骼网格体背包 bag_skm
使背包的2个下摆可以在角色跑步时摆动
基于背包骨骼网格体创建动画蓝图 ABP_Bag
ABP_Bag 动画图表:
将角色动画应用到背包 input pose 自父项实例输入到子动画图表。
使用自身的刚体 RigidBody 此模拟根据骨骼网格体组件的物理资源进行操作
RigidBody-细节-设置-覆盖物理资产-bag_p 使用背包自己的物理资产
添加 Transform (Modify) Bone 用来测试物理资产效果【稍后删除】
"变换骨骼(Transform Bone)"节点将处理骨骼的变换--即为平移、旋转或缩放
Transform (Modify) Bone-细节-骨骼控制-要修改的骨骼-Root 即背包的根骨骼
平移-平移模式-替换现有项
现在移动背包根骨骼可预览物理资产效果,背包摆件应该可以摆动
删除测试 Transform (Modify) Bone
BP_ModularCharacter 配置 bag_skm 摆件摆动
方法1:bag_skm 直接使用 ABP_Bag 动画资产
方法2:bag_skm 骨骼网格体 使用后处理
打开 bag_skm 骨骼网格体
资产详情-骨骼网格-后期处理动画蓝图-ABP_Bag
背包通过自己根骨骼触发摆件动画
使用带有更多骨骼的上身网格体
如果上身网格体新增了源角色不具有的骨骼,默认无效,所以新增的骨骼不会产生动画。因为上身网格个体依然复制领导者网格体的骨骼动画。
基于 上身骨骼网格体 MESH_T_01 创建上身动画蓝图 ABP_Upper
ABP_Upper 动画图表: input pose
RigidBody
RigidBody-细节-设置-覆盖物理资产-PA_Upper 使用上身自己的物理资产,可以新建,使用MESH_T_01
调整力量
BP_ModularCharacter
UpperBody 组件使用 MESH_T_01 骨骼网格体
UpperBody 使用蓝图动画 ABP_Upper
预构造事件中不再为 UpperBody 设置跟随下身领导者
此时上身不会同步动画, 与背包不同,背包使用自己的根骨骼,在角色动画之后生成摆动动画。 上身需要复制自己的父节点骨骼动画
下身 ABP_Upper 从上身网格体复制姿势
动画图表: Copy Pose From Mesh "从网格体复制姿势(CopyPoseFrom Mesh) "节点可将另一个组件的姿势数据复制到该组件。只有命名匹配时才能完成操作。
Copy Pose From Mesh-细节-拷贝-使用附加的父项 如SourceMeshComponent无效、此项为true,其将查找附加的父项作为源 这将直接使用 下身的父项-上身作为复制姿势的来源。 或者手动设置来源。
复制曲线-启用
复制自定义属性-启用
这将复制父项的肌肉,变体动画。
现在,上身将随着下身执行一致的动画。
这样,无需修改基本骨架【根组件,下身的骨架】,就可以为上身添加骨骼,物理资产,用以运动。
分离脸部组件
脸部通常具由复杂的表情动画,但不应使用完整的全身骨骼来携带多余的全身曲线信息。 所以脸部通常使用单独的骨架和动画蓝图。
基于脸部骨骼网格体创建动画蓝图 ABP_Head
ABP_Head 动画图表:
Copy Pose From Mesh
Copy Pose From Mesh-细节-拷贝-使用附加的父项
复制曲线-启用
复制自定义属性-启用
BP_ModularCharacter 设置脸部动画蓝图
Head 脸部组件:
使用动画蓝图 ABP_Head
预构造事件图表:
不再为 Head 脸部组件跟随下身领导者组件
此时脸部动画与主动画一致。
测试脸部表情动画
将 BP_ModularCharacter 拖入关卡
添加 关卡序列 HeadSequence
场景中选择 BP_ModularCharacter 拖入轨道中
点击轨道右侧+号,添加 Head 脸部组件
点击 Head 脸部组件右侧+号-控制绑定-基于资产的控制绑定- 选择一个【需创建】
此时 BP_ModularCharacter 右侧+号没有 控制绑定 选项,这需要将角色 下身组件设为根组件,替换默认的场景组件
BP_ModularCharacter 将角色 LowerBody下身组件设为根组件,替换默认的场景组件 DefaultSceneRoot
直接 将 LowerBody 拖入 DefaultSceneRoot 即可
删除动画序列的轨道,重新创建BP_ModularCharacter轨道使新的根组件生效
现在 BP_ModularCharacte 也可以创建控制绑定
点击轨道右侧+号,添加 Head 脸部组件 点击 Head 脸部组件右侧+号-控制绑定-基于资产的控制绑定- 选择一个【需创建】 Head 的控制绑定将无效,脸部表情不会变化。 这是因为 脸部的根组件为上身 UpperBody。 但 UpperBody 没有曲线。 脸部从上身复制了无效的曲线。 所以需要将脸部附加到根组件 下身
BP_ModularCharacter 将脸部Head附加到根组件 下身LowerBody
现在脸部控制绑定将生效
基于 脸部骨骼网格体创建控制绑定
昼夜循环 Day-Night Cycle
通过不断更改定向光的Y (Pitch)角度实现昼夜循环
打开关卡蓝图
关卡中选择定向光 DirectionalLight
事件图表:
创建对场景的定向光的引用 create a reference to DirectionalLight
event tick
添加浮点类型变量 DaySpeed 默认值15
multiply 乘以 delta seconds 增量
结果输出至 make rotator-Y (Pitch)
DirectionalLight - add actor localRotation
Camera Scroll Zoom In/Out 鼠标滚轮控制相机视角缩放
BP_ThirdPersonCharacter_Camera 玩家角色蓝图中通过鼠标事件实现
事件图表:
事件-mouse wheel axis
获取弹簧臂组件 camera Boom
get target arm length
multiply -10
add
clamp (float)
camera Boom
set target arm length
时间操控
全局时间
打开 玩家蓝图 BP_ThirdPersonCharacter_Time 事件图表: keyboard event k set global time dilation set global time dilation-time dilation- 0.5 1 表示原速 小于1表示减慢时间流失 大于1表示加快时间流速
keyboard event s
set global time dilation-time dilation-1
Metahuman
https://www.unrealengine.com/zh-CN/metahuman
详细文档: https://dev.epicgames.com/documentation/en-us/metahuman/metahuman-documentation
MetaHuman插件
https://www.unrealengine.com/marketplace/zh-CN/product/metahuman-plugin
从安装版虚幻引擎 的 D:\program\UE_5.3\Engine\Plugins\Marketplace\MetaHuman
目录,拷贝到源码版的相同目录。
启用插件
MetaHuman插件包含两个强大的功能集。
网格体转MetaHuman:
虚幻引擎的MetaHuman插件包含网格体转MetaHuman功能。有了这项激动人心的功能,你可以将通过扫描、雕刻或传统建模创建的自定义网格体转变成具有完整绑定的MetaHuman。然后,你可以在MetaHuman Creator中进一步完善你的角色。
MetaHuman Animator:
MetaHuman Animator是我们新推出的功能集,允许你使用iPhone或立体头戴式摄像机系统(HMC)捕捉演员的表演,并将其转化成MetaHuman角色脸上高保真的面部动画。每个微妙的表情、神态和情绪都会被精确地捕捉下来,忠实地还原到你的数字人类上。它实现这些出色结果的方式简单明了——任何人都可以完成这项任务。 Metahuman Animator通过使用4D解算器,将视频及深度数据与表演者的MetaHuman代表模型结合在了一起。动画是使用GPU硬件在本地处理的,几分钟内即可得到最终动画。
要使用MetaHuman Animator,你需要UE 5.2或更高版本。
UE限定内容 - 只允许在基于虚幻引擎的产品中使用 技术细节 查看教程,详细了解其工作原理。网格体转MetaHuman快速入门 标签
将任意网格体转换为Metahuman / Convert any Mesh to Metahuman
安装metahuman插件 https://www.unrealengine.com/marketplace/zh-CN/product/metahuman-plugin
RO2 仙境传说2:世界之门 的 虚幻引擎2.5 模型资源导入虚幻5
使用 虚幻引擎查看器 UE Viewer 解包程序资源
虚幻引擎查看器 最后更新: 06.01.2022
虚幻引擎资源查看器(以前称为虚幻模型查看器)是一个程序,用于查看和提取使用虚幻引擎制作的各种游戏中的资源。有时该程序被称为“umodel”,即“unreal”和“model viewer”的缩写。 https://www.gildor.org/en/projects/umodel#files
从RO2游戏文件中提取出: 模型文件:例如 Actbox_01.gltf,Actbox_01.bin
相关的贴图文件 png
网格体文件:例如 Actbox_01.psk
动画文件:例如 actbox_01ani.psa,actbox_01ani.config
ActorX Importer for 3ds Max
https://www.gildor.org/projects/unactorx ActorX Importer 补充了 Epic Games ActorX Exporter 的功能。Epic 的插件可以从 3ds Max、Maya 和 XSI 导出 psk 和 psa 文件。此页面中的插件具有相反的功能:您可以将 psk 和 psa 文件加载回 3ds Max(没有适用于 Maya 和 XSI 的版本)。
特征 将 psk 和 pskx 网格加载到 3ds Max 中 加载 PSA 动画 自动创建和分配由UE Viewer生成的素材 将网格/动画批量转换为 max、fbx 或 ase 格式
将插件文件夹放入3ds Max 安装目录的 Autodesk\3ds Max 2024\stdplugs\ActorX Importer
启动 3ds Max 后会自动加载该插件
设置ActorX 导入器的材质路径
例如 H:\ro2\Animations-psk\Rag2Npcs_Ma
包含子文件夹。
可以设置为所有材质的根目录。
清空3dmax场景,防止多个物体重叠
点击 ActorX 导入器-工具-清空场景
每次导入新的网格体和动画前都需要清空场景
导入 PSK 网格体文件
点击 导入 PSK 文件,,只选择一个
导入 PSA 动画文件
点击 导入 PSA 动画文件,只选择一个
点击 全部加载 ,将加载所有动画
可以使用 fbx 导出【可选】
使用 3ds max 内置的导出
使用 ActorX 批量导出 网格体【建议】
psk文件路径 选择psk网格体所在目录。
提示材质0时,选择材质目录的第一个材质,将自动使用全部相关材质
点击 导出网格 ,可以批量导出网格体以及附带的物理资产,材质,贴图到网格体目录下的 fbx文件夹
使用 ActorX 批量导出 动画【建议】
点击 导出动画,动画将导出到同目录的fbx目录下
改动画包含了网格体组件
导入虚幻引擎
将网格体批量导入虚幻引擎
批量选择fbx,导入
不要勾选导入动画
将动画批量导入虚幻引擎
导入时,勾选 导入动画,并且选择之前导入的骨骼
导入后回生成重复的网格体,物理资产,材质,贴图,全部删除。
只保留动画序列
将没有关联动画资产的 gltf 模型文件 导入 blender ,再导出 fbx格式
将 fbx 模型导入虚幻引擎
Gravity & Physics 虚幻引擎的重力与物理
为静态网格体添加 重力与物理
添加 静态网格体 SM_cube
添加-形状-立方体
选中立方体-右键-浏览至资产
拷贝 cube至自定义文件夹中 重命名为 SM_cube
场景添加 SM_cube,移除原cube. SM_cube 默认启用了碰撞。
玩家也具有碰撞。
现在运行游戏,玩家角色无法推动 SM_cube
SM_cube 无法直接模拟物理
新建 Actor 蓝图 BP_Cube
BP_Cube 中添加 静态网格体组件 SM_cube
场景添加 BP_Cube
BP_Cube 的 SM_cube 组件 默认启用了碰撞。
玩家也具有碰撞。
现在运行游戏,玩家角色无法推动 BP_Cube
BP_Cube 启用模拟物理
BP_Cube-SM_cube 组件-物理-模拟物理-启用
现在,玩家将可以推动 BP_Cube
BP_Cube 启用模拟物理的质量
BP_Cube-SM_cube 组件-物理-质量(公斤)-启用 100
BP_Cube 质量越重,玩家推动BP_Cube 的距离越小,
质量为1时,可以将 BP_Cube 推飞。
质量很大时,只能推动BP_Cube前进很小距离。
重力
取消重力后,BP_Cube 将悬浮,但由于模拟物理和启用质量,仍会与玩家发生作用力。
创建具有多个对象的预制件 Create Prefabs with Multiple Objects
将3个静态网格体 合并为一个蓝图 BPP_Prefabs
添加3个静态网格体
多选这3个静态网格体,右键-关卡-创建已打包关卡actor
保存为关卡 NewMap
再保存为预制件 BPP_Prefabs
BPP_Prefabs 包含关卡实例组件
https://docs.unrealengine.com/5.3/zh-CN/level-instancing-in-unreal-engine/
现在将 BPP_Prefabs 拖入场景将包括3个静态网格体
制作可推开关闭的真实的门
##方式1:物理控件门 Physics Door 使用物理控制组件制作可手动推开,然后自动缓慢关闭的门
需要初学者包
内容浏览器-添加-添加功能或内容包-
内容-starter content
新建 Actor 蓝图门 BP_PhysicsDoor
添加静态网格体组件 StaticMesh 重命名为 Door
Door 使用初学者包中的门静态网格体 SM_Door
加静态网格体组件 StaticMesh 重命名为 Frame 作为门框,与门同级
Frame 组件使用初学者包中的静态网格体 SM_DoorFrame
调整 Door 的位置
0,45,0
为 Door 组件启用模拟物理使其可以移动
由于 Door组件的SM_Door没有碰撞体,所以默认无法启用模拟物理
将 SM_Door 和 SM_DoorFrame 复制一份供BP_PhysicsDoor测试用
不再修改和使用原网格体。 BP_PhysicsDoor使用复制的网格体
为 SM_Door 静态网格体添加盒体简单碰撞
Door 组件 启用模拟物理
物理-物理模拟-启用
由于启用了模拟物理 ,默认情况下,受到外部碰撞,门将倒下
Frame 门框组件设置为无碰撞
碰撞-碰撞预设-无碰撞
防止门框干扰碰撞
添加 PhysicsConstraint 物理约束组件
约束门的位置
PhysicsConstraint 物理约束组件默认位于门的底部中心,球形,默认可以任意方向旋转
设置约束 只可以水平旋转
Angular limits-摆动1运动-自由
Angular limits-摆动2运动-锁定
这回摆脱垂直球体
Angular limits-扭曲运动-锁定
这将禁止移动
现在只显示水平的红色圆形,表示只可以水平旋转
使PhysicsConstraint 物理约束组件对门组件产生约束
PhysicsConstraint -细节-约束-组件命名1-组件名称-Door 【门组件的名称】 表示约束 Door 组件,即门。 要约束的首个组件属性的命名。如Actor1为空,将在拥有者中查看。如此项为空,将使用Actor1的RootComponent
现在 Door 组件 周围将显示红色边框
将 BP_PhysicsDoor 提高,与地面保持距离,防止门与地面碰撞
此时玩家碰撞门,门将绕门的中轴旋转。
因为物理约束组件位于门的底部中心,且约束门绕约束组件的水平轴旋转
调整 PhysicsConstraint 物理约束组件
Angular limits-摆动1运动-受限
此时可以调整 摆动1限度
Angular limits-摆动1限度-90
表示门可以向内或向外旋转90度
默认的红色半圆表示门在x方向的左右90度旋转,这与门的旋转不一致
绕Z轴旋转约束使其与门的旋转方向一致
调整后
移动旋转约束位置到门的左下角
推门
现在碰撞门,可以使门向内开90度
也可以使门向外开90度
PhysicsConstraint 物理约束组件 添加力使门可以自动缓慢归位关闭
PhysicsConstraint 物理约束组件 -细节-角发动机-角驱动模式-扭曲和摇摆 路径被分解为扭曲(滚动约束)和摇摆(椎体约束)。如不跟随最短弧可能导致万向节锁定。可与锁定角约束共用。
角发动机-目标方向-驱动-摇摆-启用 控制当前朝向/速度和目标朝向/速度之间的椎体约束驱动。只要至少一个摇摆限制设为不受限或受限,此项便可用。
现在默认力将起作用
现在 碰撞将门推开后,门将内外晃动,直到很久以后彻底停止晃动,缓慢归位到门框。
Door组件使门快速回到原位置
Door组件-细节-物理-角阻尼-15
添加后用于减弱角运动的“拖拽”力
现在,门被碰撞推开后,将快速返回的原位置。
方式2:Physics Asset 物理资产门
启用 Skeletal Mesh Editor tools 插件
https://docs.unrealengine.com/5.3/zh-CN/skeletal-mesh-editor-in-unreal-engine/
unreal steam
需要以 standalone game 独立进程游戏 模式运行游戏。
需要打开 steam
https://github.com/mordentral/AdvancedSessionsPlugin https://github.com/Risensy/Steam Discord Server - https://discord.gg/AyPUwKdbTK
Online Subsystem Steam Online Subsystem Steam的概述,包括如何设置项目以在Valve的Steam平台上分发。 https://docs.unrealengine.com/5.3/zh-CN/online-subsystem-steam-interface-in-unreal-engine/
多人游戏中的关卡切换 https://docs.unrealengine.com/5.3/zh-CN/travelling-in-multiplayer-in-unreal-engine/
为花草添加被风吹动的效果
创建材质函数 MF_Wind
材质函数需要参数1:WindDirection 风的方向 类型为向量4 默认值 0,1,0,0
材质函数需要参数1:WindIntensity 风的强度 类型为标量 默认值 1
输出值用于材质的 全局位置偏移
M_Wind 材质中使用材质函数 MF_Wind
WindDirection :0,1,0,0 切记,A通道不能为1 WindIntensity :1
M_Wind 材质中将风提升为参数,开关风,风向,风速
分组-Wind
MI_Wind 材质实例中开启风
花瓣飘落 Niagara 效果
花瓣材质
导入单个花瓣图片纹理 ,带透明通道
例如导入花瓣透明png
导入图片为 纹理 T_Flower
基于纹理 T_Flower新建花瓣材质 M_Flower
材质-混合模式-半透明 着色模型-双面植物 双面-启用 【否则背向摄像机的花瓣面将不显示,导致花瓣忽隐忽现】
使用 Particle Color 节点制作材质,可在粒子系统中更换颜色。
Fraction 为饱和度。
基于 材质 M_Flower 创建材质实例 材质 MI_Flower
新建 Niagara 系统 NS_FallingFlower
右键-Niagara系统-创建空白系统
右键添加发射器-Blowing Particles 风吹效果粒子
此时将 NS_FallingFlower 拖出场景,可以看到基本的飘散粒子效果
Blowing Particles - 渲染-Sprite渲染器 使用材质实例 MI_Flower
Blowing Particles - 渲染-Sprite渲染器:
精灵渲染-材质-MI_Flower
花瓣颜色
Blowing Particles-粒子生成:
initialize particles-color
需要 Particle Color 材质节点配合生效。
花瓣粒子生成的数量
Blowing Particles-粒子生成:
Sprote Attributes-Sprite Size Mode-Uniform Sprite Size Min 最小数量 -5
Sprote Attributes-Sprite Size Mode-Uniform Sprite Size Max 最大数量 -15
控制花瓣飘落速度
Blowing Particles-粒子更新: Aerodynamic Drag 空气阻力-
控制风力
Blowing Particles-粒子更新:
Wind Force-Wind Speed 控制风吹的方向和风速-xyz 200,0,0 表示吹向镜头
自定义粒子
默认花瓣平面较薄,。
如果花瓣具由弯曲,且有一定厚度,粒子效果更加。
取消Sprite 渲染器,使用网格体渲染器
Blowing Particles-渲染-Sprite 渲染器-取消
Blowing Particles-渲染-加号-网格体渲染器
点击 修复问题,自动修复粒子
网格体-使用网格体版本的花瓣。
可以添加多各不同的花瓣网格体。
这样花瓣飘落后将会堆积在地面。
粒子生成 随机
Blowing Particles- 粒子生成-Mesh Attributes-Mesh Render Arrar visibility mode-random
Blowing Particles- 粒子生成-Mesh Attributes-Mesh Render Arrar visibility mode-Mesh Render info-网格体渲染器-网格体渲染器
粒子大小
Blowing Particles- 粒子生成-Mesh Attributes-Mesh Scale mode-Random Uniform
调整花瓣落地后与地面的接触模拟
Blowing Particles- 粒子更新-Align Particles with collision plane:
allow alignment on X -取消 【不与地面x方向对齐,防止在x方向约束粒子】
allow alignment on Z - 启用
调整粒子生成区域
Blowing Particles- 粒子生成-shape location:
shape-
在半径300的球体内生成粒子
每秒生成数量
Blowing Particles-spawn rate:
改变材质基础颜色
虚幻引擎本地化系统 Unreal Engine Localization System
本地化和国际化
它们通常属于本地化,但它们并不相同。
本地化是适应的过程 例如:在游戏中翻译文本为特定地区或语言。
国际化是设计软件的过程,以便于应用程序翻译到其他语言以适应其他地区,且不需要修改工程。
可以本地化的类型
如何本地化
资产的本地化
本地化控制板
虚幻通过 本地化控制板 进行本地化
工具-本地化控制板
本地化控制板
游戏目标
游戏目标是将要本地化的游戏内容的部分
可以新建游戏目标,例如为游戏DLC新建游戏目标
加载政策:
game 目标使用固定或游戏
游戏启动后将自动加载翻译。
DLC 目标使用永不
引擎目标
引擎的本地化
一般不需要
收集文本
从包收集
更加便捷
例如:收集UI资产,从中找到要翻译的文本
包括路径通配符-添加路径 Content/Ro2ea/Blueprints/UI/*
表示收集UI目录下的资产,包含控件等资产
语系
默认只有英语。 添加新语言,例如中文(简体)
注意:::::添加的语言必须是具体条目,否则翻译不生效【预览也失效】。
例如:中文 语言,无效
例如:中文(简体) 语言,有效
本地语言
默认的语言,基于此开始翻译。
建议使用英语作为本地语言,因为代码中更多为字母,方便翻译。 更改本地语言将会丢失之前的翻译。且不能撤销操作。
标记需要翻译的文本
例如 :控件文本
点击空间文本旁边的旗帜标志,显示翻译选项
本地化-启用 表示可翻译,可以被本地化控制板收集
对固定展示的数字,关闭其本地化,防止被本地化控制板收集。
例如角色等级的具体值:99
不被收集的文本将显示警告标志
例如用户名,密码,用户输入的内容 修改后需重新收集文本。
收集文本
点击 收集文本,开始收集本地语言的已标记为需要翻译的文本数据
找到248个可翻译的文本
显示翻译进度
当前英语为本地语言,所以需要将英语翻译为中文简体等其他语言。
点击 中文简体 右侧的 编辑此语言的翻译
未翻译为 70 处
为方便开发,继续将英语切换为本地语言
点击 中文简体 右侧编辑此语言的翻译
右侧输入对应英文【已设置为本地系统语言】的中文翻译
翻译完成过后,继续点击 收集文本
已翻译的中文简体语言显示翻译进度
编译翻译
需要编译收集的文本使引擎感知新的文本被翻译。
语系-计算字数
语系-编译文本
语系-选择翻译好的语言 中文简体-右侧 编译此语言的翻译 或 编译文本
切换游戏语言
编辑器偏好设置-通用-区域和语言-预览游戏语言
切换为中文简体【英语为本地系统时】
如果在编辑器中预览翻译,需要将 加载政策临时改为 游戏/固定/编辑器
控件中也可以直接预览翻译
en
zh-Hans
如果预览翻译不生效,请检查: 语系必须为具体项。中文(简体) 可以。 中文 不可以。 可能需要重启编辑器。 加载政策临时改为 游戏/固定/编辑器。
虚幻引擎 蓝图变量/C++ 本地化
Unreal Engine Source Code Localization
翻译源代码文件(C++或蓝图)中的文本。我们需要在蓝图中使用文本变量Text,在C++中使用FText。
蓝图
蓝图控件需要使用 文本类控件和变量
蓝图变量 需要文本类型
C++
引擎将收集C++中的 NSLOCTEXT 或 LOCTEXT
NSLOCTEXT
是一个宏,用于在 Unreal Engine 项目中定义命名空间化的本地化文本。这个宏允许你创建在不同语言环境下可以被适当翻译的字符串。使用 NSLOCTEXT
时,你需要指定三个参数:一个命名空间,一个键,和默认的文本字符串。这样就为每个特定的字符串指定了一个唯一的上下文和标识符,有助于在后续的本地化过程中进行准确翻译。
以下是详解 NSLOCTEXT
宏的各个部分:
-
命名空间(Namespace): 命名空间用于对相关的本地化文本进行分组。这有助于组织和区分项目中的不同部分或不同模块的文本。例如,你可能会有一个用于UI元素的命名空间和一个用于游戏逻辑的命名空间。
-
键(Key): 键必须项目中唯一。否则本地化控制板会显示检测到冲突。
键是在给定命名空间内唯一标识一段文本的字符串。在本地化过程中,翻译人员通常会看到这个键和默认文本,以便提供正确的翻译。键的选择应当反映文本内容的用途或内容,以方便理解和翻译。
-
默认文本(Default Text): 默认文本是在源语言(通常是英语)下提供的文本字符串。这是在游戏运行时如果没有找到适当的翻译或者在开发过程中默认显示的文本。
以下是如何使用 NSLOCTEXT
宏定义本地化文本的示例:
FText MyText = NSLOCTEXT("Dialogues", "Greeting", "Hello, player!");
在这个例子中:
-
"Dialogues"
是命名空间,用于分组可能出现在游戏对话框中的文本。 -
"Greeting"
是这段文本的唯一键,表明这段文本用于问候。 -
"Hello, player!"
是如果游戏以开发语言(比如英语)运行时显示的默认文本。
使用 NSLOCTEXT
定义的本地化文本,可以在之后的本地化流程中被翻译到不同语言,并且可以通过Unreal Engine的本地化系统根据玩家的语言偏好自动选择和显示正确的文本版本。这使得游戏或应用能够支持多语言,并为玩家提供更佳的体验。
FText WarnMessage = NSLOCTEXT("UserMessage", "WarnMessage", "name is wrong!!");
#define LOCTEXT_NAMESPACE "UserMessage"
FText WarnMessage2 = LOCTEXT("WarnMessage", "name is to short!!");
#undef LOCTEXT_NAMESPACE
收集 C++代码中的本地换文本 LOCTEXT,NSLOCTEXT
本地化控制板-收集文本-从文本文件收集
搜索目录-C++目录 Source
文件扩展名 -常用扩展名 h cpp ini 等
收集蓝图中的文本变量
从包收集-包括路径通配符 选择包含蓝图资产的目录例如 Content/Ro2ea/*
开始收集
语系-收集文本
中文(简体) 编辑此语言的翻译 计算字数 编译文本
虚幻引擎本地化字符串表 重用字符串
类似变量用法。 Unreal Engine Localization String Tables 本地化字符串表可以避免翻译重复的单词或短语(这在游戏UI或蓝图中很常见)
新建目录 例如 Localization,收集翻译文本时必须包含该目录的本地化字符串表。 可以放置到相关文本使用的目录下。
新建 字符串表格资产 ST_UICommon
右键-其他-字符串表格
添加 文本
添加键值对:start_game - start game
使用 字符串表格资产 ST_UICommon 中的文本键替换游戏中的文本
找到文本翻译按钮-引用文本-字符串表格-ST_UICommon-start_game
收集文本
start game 有变动,需要再次翻译。 收集文本,翻译,编译文本。
虚幻引擎本地化格式文本
Unreal Engine Localization Format Text 正确使用文本格式来组合以后可以本地化的文本。我们可以根据性别、复数、数字、日期、货币等定制翻译
蓝图中使用 Append 等操作FSting的函数节点,无法本地化。 需要使用 工具-文本-Format Text 格式化文本函数节点来操作文本,才可以被本地化收集。
例如显示一个当前日期文本:Date:{Date}
Date:
为可本地化的文本,大括号内Date
为捕获的日期变量
本地化控制板中收集并翻译 Date:{Date}
翻译前面 Date:
部分
{Date}
需要保留,但可以更换位置
计算字数,编译文本。
本地化货币
虚幻引擎外部本地化工具 poedit
Unreal Engine External Localization Tools | poedit
外部本地化工具,例如 POEDIT 或任何支持 PO 文件的本地化工具。这将使我们能够在不打开引擎的情况下进行翻译、获取建议、使用低端机器等。
导出文本
本地化控制板-语系-导出文本 或 本地化控制板-中文简体-导出此语言的翻译
Game.po
为需要外部打开翻译的文件
poedit
https://poedit.net/ https://github.com/vslavik/poedit
打开 Content\Localization\Game\zh-Hans\Game.po
中文翻译。
编辑右侧文本即可。
导入翻译目录
翻译完成后,保存po文件
本地化控制板-语系-导入文本
选择目录 E:\Unreal Projects 532\Ro2ea\Content\Localization\Game
导入全部语系的po翻译文件
编译文本。
虚幻引擎资源本地化
Unreal Engine Asset Localization
不仅需要翻译文本,还需要翻译其他类型的资产,例如纹理、材质等。
对于打包的游戏,需要完全重启可执行文件才能使本地化资产正常工作。在“设置当前区域性”节点中,如果展开高级选项,则会出现“保存到配置”复选框,该复选框将保留语言选择与保存游戏对象一起:https://dev.epicgames.com/community/snippets/W5E/unreal-engine-persist-culture-to-config-files-in-set-current-culture
纹理本地化
纹理-右键-资产本地化-新建本地化资产-中文(简体)
这将新建中文简体版本的同名纹理
Ro2ea/Content/L10N/zh-Hans/Ro2ea/Image/gravityfes_logo.uasset
在虚幻引擎外部修改本地化资产
中文简体版本的同名纹理-右键-资产操作-导出
导出需要的格式例如 PNG,TGA
在外部软件中修改导出的文件。
导入外部修改后的文件
打开 需要本地化的 中文简体版本的同名纹理 Ro2ea/Content/L10N/zh-Hans/Ro2ea/Image/gravityfes_logo.uasset
文件路径-源文件 选择修改后的文件以更新到当前文件。
注意
如果游戏运行中使用命令行切换语言,本地化资产例如纹理将不生效。 这是由于纹理是加载到内存中的。
需要重新加载纹理,只需要切换关卡即可。
虚幻引擎对话本地化
Unreal Engine Dialogue Localization
待补充
虚幻引擎本地化语言切换
Unreal Engine Localization Language Switching
编辑器中切换预览游戏语言
编辑器偏好设置-通用-区域和语言-国际化-预览游戏语言
控件切换语言
独立进程游戏 模式预览语言
这是为了在使用命令行切换语言时,只对游戏生效。
不会切换引擎和编辑器的语言。
独立进程游戏 运行时按波浪键 ~ 打开控制台。
输入切换语言命令 culture=en
切换为英语
输入切换语言命令 culture=zh-hans
切换为中文(简体)
注意,纹理等资产需要通过切换关卡重新加载使本地化生效。
蓝图中运行时切换语言 【待完善】
工具集-国际化-get current culture 获取当前操作系统的语言
set current culture 设置语言
这同时会修改编辑器语言,除非使用独立进程游戏 模式运行。
项目配置中切换语言
打包设置中启用翻译的语言
项目设置-项目-打包-高级-要打包的本地化-显示本地化文本
启用-英语
启用-中文(简体)
平台-windows-打包项目
运行游戏生成游戏配置文件 Engine.ini Game.ini
配置文件中设置默认语言
[Internationalization] culture=en
两个配置都可以设置默认语言 Game.ini 的设置将会覆盖 Engine.ini
游戏启动文件快捷方式添加语言参数
为打包后的游戏执行文件 exe 创建快捷方式,
在 路径末尾添加 -culture=en
例如D:\ro2\System\RAGII.EXE -culture=en
这回覆盖配置文件。
C++ 中切换语言
``
UFUNCTION(BlueprintCallable, Category = "RoLibrary|zh")
static void ChangeGameLanguage(const FString& NewLanguageCode);
void URoLibrary::ChangeGameLanguage(const FString& NewLanguageCode)
{
// 实例化一个文化对象,例如"fr"代表法语
FCulturePtr NewCulture = FInternationalization::Get().GetCulture(NewLanguageCode);
if (NewCulture.IsValid())
{
// 设置新的语言和地区
FInternationalization::Get().SetCurrentCulture(NewLanguageCode);
// 你还可以分别设置显示语言和音频语言
FInternationalization::Get().SetCurrentLanguageAndLocale(NewLanguageCode);
// 输出当前语言以确认更改
//UE_LOG(LogTemp, Log, TEXT("Language changed to: %s"), *FInternationalization::Get().GetCurrentLanguage()->GetName());
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Invalid or unsupported language code: %s"), *NewLanguageCode);
}
//ChangeGameLanguage(TEXT("zh-Hans"));
}
使用
ChangeGameLanguage(TEXT("zh-Hans"));
虚幻引擎本地化打包设置
Unreal Engine Localization Packaging Settings
打包设置中启用翻译的语言
项目设置-项目-打包-高级-要打包的本地化-显示本地化文本
启用-英语
启用-中文(简体)
国际化支持
项目设置-项目-打包-高级-国际化支持
靠前的选项打包后文件更小[可以忽略,仅1-5MB差距],但支持的显示更差
中文需要选择 EFIJSCJK 15MB,在获取本地语言时可以显示对应语言的文字而非英语表示的中文(简体)
不同平台的配置文件也可以修改
Paper 2D Sprites
https://docs.unrealengine.com/5.3/zh-CN/how-to-import-and-use-paper-2d-sprites-in-unreal-engine/
Flipbook组件
Sprites WIdget
使用多张 Sprites 纹理创建一个 纹理2D数组
选择多张Sprites 纹理-右键-创建纹理阵列 T_loading_run_Array
Sprites 纹理 loading_run_01-loading_run_012
纹理2D数组 T_loading_run_Array
基于 纹理2D数组 T_loading_run_Array 创建材质 M_loading_run_Array
材质 M_loading_run_Array
材质域-用户界面
混合模式-已遮罩
TextureCoordinate
向量项-AppendVector
Time Constant 1 默认65 转换为参数 FPS Multiply
Constant 1 默认65 转换为参数 NumberOfTextures 值为纹理数量 Fmod
使用改材质即可
使用UMG创建可拖放UI控件 DRAG AND DROP WIDGET
https://docs.unrealengine.com/5.3/zh-CN/creating-drag-and-drop-ui-in-unreal-engine/
DRAG AND DROP WIDGET
创建控件 WBP_Draggable
创建控件 WBP_HealthBar 作为要拖拽的控件
创建主屏幕控件 WBP_Main
基于 拖放操作 DragDropOperation 类创建新的 蓝图类,命名为 BP_WidgetDrag
创建 用户控件 变量,命名为 WidgetReference
类型:用户控件 对象引用
选中 实例可编辑(Instance Editable) 和 生成时公开(Expose on Spawn)。 这将用于存放我们想要在屏幕上四处拖动的UMG控件。
创建 矢量2D 变量,命名为 DragOffset
类型:vector2D /向量2D
选中 实例可编辑(Instance Editable) 和 生成时公开(Expose on Spawn)。
这会使位置从我们开始拖放控件的位置偏移。
WBP_Draggable
创建 用户控件 变量,命名为 WidgetReference
类型:用户控件 对象引用
选中 实例可编辑(Instance Editable) 和 生成时公开(Expose on Spawn)
WBP_HealthBar
注意,只有最外部的控件【当前为尺寸框控件】设置为:行为-已启用,可视性-可视。 内部控件都不可以设置为可视,否则拖动失效。
设计控件外观
编写OnMouseButtonDown功能的脚本
这一步使我们能够确定玩家是否在拖动鼠标左键。
在 事件图表 中,添加 OnMouseButtonDown 和 OnDragDetected 覆盖。这样会为事件图表中的每个覆盖创建选项卡。 调用自定义脚本需要置换几个函数。鼠标键按下时将进行一些检查,还将检查出现控件拖动时发生的状况。
OnMouseButtonDown 按下鼠标按钮时
选择 OnMouseButtonDown 选项卡。从 OnMouseButtonDown 节点上 我的几何结构(My Geometry) 引脚拖出引线并添加 绝对到局部(Absolute to Local) 节点。
从 鼠标事件(Mouse Event) 引脚拖出引线,添加 获取屏幕空间位置(Get Screen Space Position) 节点,并将返回值连接到 绝对坐标(Absolute Coordinate) 引脚。
此操作会将生命值条控件的绝对坐标转换为局部空间,原理是 获取鼠标按钮注册按下鼠标键的屏幕位置。这样会将位置存储为变量,以便我们确定玩家实际点击控件的位置以及放下控件的位置。
右键单击 绝对到局部(Absolute to Local) 节点的 返回值(Return Value),并选择 提升为变量(Promote to Variable)。将变量命名为 拖拽偏移(Drag Offset)。
在图中单击右键,并添加 按下后检测拖拽(Detect Drag if Pressed) 节点。将 拖拽键(Drag Key) 设置为 鼠标左键(Left Mouse Button)。
完成其余引脚的连接。
将 鼠标事件(Mouse Event) 连接到 指针事件(Pointer Event)。
将 按下后检测拖拽(Detect Drag if Pressed) 的 返回值(Return Value) 引脚连接到 返回节点
将四个节点的 执行(Exec) 引脚连接起来。
编写OnDragDetect功能的脚本 :发现拖动时
在这步中,我们将决定玩家实际在屏幕上拖动HealthBar时发生的状况。
选择 OnDragDetected 选项卡。在 OnDragDetected 节点上单击右键并添加 创建控件(Create Widget) 节点。将 类(Class) 设置为 拖拽控件(WBP_Draggable)。
从 控件引用(Widget Reference) 引脚连接 Self 节点。将返回值 提升 为变量,命名为 已拖拽控件(Dragged Widget) 并连接引脚。
现在,当我们创建拖拽控件时,它将引用现有的HealthBar控件。我们还会将虚拟拖拽控件提升为变量,以便稍后访问它,并在选择放下控件时从显示画面中将它移除。
单击右键并创建 Drag & Drop Operation 节点。将 类(Class) 设置为 控件拖拽(BP_WidgetDrag),并将 枢轴(Pivot) 设为 鼠标按下(Mouse Down)。
如果相对于指针拖拽,枢轴将确定在执行拖拽操作时拖拽控件显示(Drag Widget Visual)应出现的位置。
将以下节点连接到 DragAndDropOperation 节点引脚。
从 被拖拽控件设置(Dragged Widget Set) 到 返回节点 的 执行 线
Self 到 控件引用(Widget Reference)
被拖拽控件(Dragged Widget) 到 默认拖拽显示(Default Drag Visual)
拖拽偏移(Drag Offset) 到 拖拽偏移(Drag Offset)
前文中我们说明了哪个控件蓝图是引用,拖动可视应该是什么,并提供了一个开始拖动的偏移。默认情况下,节点上有一个偏移引脚;但我们使用自己的计算来确定按下鼠标按钮时要开始偏移的位置。
编译 并 保存 HealthBar 蓝图。
接下来需要确定玩家按下鼠标左键时应该发生的操作并执行OnDrop函数。
WBP_Main
设置OnDrop函数
这里,我们设置主 HUD 控件蓝图,并覆盖我们执行 OnDrop 函数时要发生的操作。
打开 WBP_Main 控件蓝图。在 画布面板 的 细节(Details) 面板中,将 可视性(Visibility) 设为 可见(Visible)。
我们在HealthBar控件内部编写了拖拽检测脚本;但松开鼠标左键时,我们希望将生命值条放到HUD控件蓝图中。为了让HUD接收到命中检测,需要让面板可见。
在 调色板(Palette) 窗口中,将 HealthBar 控件添加到画布。
在 事件图表 中,从 我的蓝图(My Blueprint) 面板添加 OnDrop 放置时 函数覆盖。
在 OnDrop 节点上 运算(Operation) 拖出引线,并添加 转换为控件拖拽(Cast to BP_WidgetDrag) 节点。然后,添加 获取控件引用(Get Widget Reference) 并将 作为控件拖拽(As Widget Drag) 引脚连接到 控件引用(Widget Reference) 和 拖拽偏移(Drag Offset) 节点。
此操作将检查哪类操作正作为 OnDrop 函数的部分在执行。如果是 控件拖拽(Widget Drag),我们会获得 WidgetReference(作为被拖拽的控件传递)以及 DragOffset(或开始拖拽的位置)。
从 我的几何结构(My Geometry) 引脚,添加 绝对到局部(Absolute to Local) 节点。从 指针事件(Pointer Event) 引脚,添加 GetScreenSpacePosition 节点。 这将告诉我们在2D空间中松开鼠标左键放置控件的位置。我们将用这个值减去 DragOffset,确定应该在什么位置放下控件。
添加 Vector2D - Vector 2D 节点,从 绝对到局部(Absolute to Local) 的 返回值 减去 DragOffset。
单击右键并添加 从父项移除(Remove from Parent)、添加到视口(Add to Viewport) 和 设置视口中的位置(Set Position in Viewport) 节点。按照以上所列的顺序将所有3个节点的 执行(Exec) 引脚连接起来,并将 设置视口中的位置(Set Position in Viewport) 节点连接到 返回节点。
进行以下连接和调整:
控件引用(Widget Reference) 引脚连接到所有三个节点上的 目标(Target) 引脚。
Vector2D - Vector 2D 节点的 返回值 引脚连接到 位置(Position) 引脚。
取消选中 移除DPIScale(Remove DPIScale)
选中 返回值(Return Value)
取消勾选 移除DPIScale(Remove DPIScale) 并选中 返回值,因为无需移除DPI缩放。我们已经处理了这个函数,因此返回为true。我们首先通过此脚本移除现有的体力条控件,然后将其重新添加到相对于Drag Offset的新位置中的画面。
编译 并 保存 HUD 控件蓝图。
我们已设置HUD处理拖拽控件的放置,它还将显示体力条。接下来将设置被拖拽控件模拟体力条的外形,并对角色蓝图发出指令将 HUD 添加到视口。
WBP_Draggable
在这一步中,配置 DragWidget,这是我们将拖到视口中的可视控件。
打开 DragWidget 控件蓝图,并将 画布面板 替换为拥有子 边框 的 缩放框。
将 缩放框 重命名为 WidgetSize,并将 isVariable 设为 true。选中 宽度覆盖(Width Override) 和 高度覆盖(Height Override)。
我们将对缩放框的宽度和高度进行设置,使其成为体力条控件的尺寸。
选择 边框,并将 笔刷颜色(Brush Color) 设为 黑色(Black),Alpha 值为 0.5,以呈现一定的透明度。
在本示例中,我们的生命值条轮廓为拖拽显示,同时在同一个位置保留实际的生命值条。
在 事件图表 中,从 事件构造 拖出引线,添加 转换为生命值条(Cast to WBP_HealthBar) 节点。从 控件引用(Widget Reference) 连出引线,并将它连接到 对象(Object) 引脚。
从 作为生命值条(As Health Bar) 引脚,添加 获取所需大小(Get Desired Size) 节点。将返回值连接到 中断矢量2D(Break Vector 2D) 节点。
这样就获得了生命值条的大小,并可以将缩放框设置为相同大小。我们可以手动输入覆盖;但如果要更改生命值条的大小,也必须在此处更改。
单击右键并添加 设置高度覆盖(Set Height Override) 和 设置控件覆盖(Set Widget Override) 节点,并将它们分别连接到 转换为生命值条(Cast to HealthBar) 节点。然后拖入 控件大小(Widget Size) 节点。
连接以下引脚:
控件大小(Widget Size) 到两个 目标(Target) 引脚
中断矢量2D X 到 输入高度覆盖(In Height Override)
中断矢量2D Y 到 输入宽度覆盖(In Width Override)
编译 并 保存 DragWidget 蓝图。
向视口添加HUD控件 WBP_Main
最后,需要将 HUD 控件蓝图 WBP_Main 添加到 角色 蓝图中的视口并启用鼠标光标,以便能够看到拖拽位置。
在 内容浏览器 中的 Content/ThirdPersonBP/Blueprints 下,打开 ThirdPersonCharacter 蓝图。
从 事件开始播放(Event Begin Play) 节点拖出引线,添加 创建控件(Create Widget) 节点并将 类(Class) 设置为 WBP_Main。创建 添加到视口(Add to Viewport) 节点并将它连接到 设置显示鼠标光标(SET Show Mouse Cursor)。添加 获取玩家控制器(Get Player Controller) 节点,并将 返回值 连接到 设置目标(SET Target)。
编译、保存 并单击 运行(Play) 按钮,以运行拖拽控件。
最终结果 在编辑器中运行时,可以单击左键,并将生命值条拖到屏幕上,然后将它放到新位置。
这只是开始拖放流程的一个元素范例。可能需要进行额外检查,确保玩家不会将控件拖至安全区外,或放在其他控件之上。
制作抓娃娃机
blender 中制作抓钩骨架,模型,动画
为抓钩添加4个插槽用来约束被抓物体
抓钩添加4个静态网格体组件,附加到4个插槽上
4个静态网格体组件添加简单碰撞
静态网格体组件 生成重叠事件,启用碰撞
不启用模拟物理
被抓物体属性设置
模拟物理-启用
质量-启用 10公斤
启用重力-启用
碰撞-生成重叠事件
启用碰撞 查询和物理
阻挡适当的物体
球体骨骼网格体的静态网格体添加简单碰撞
运动控制