虚幻物理资产导出XML
# 虚幻物理资产导出XML
导出虚幻引擎的角色PhysicsAsset 资产为xml格式 , 方便在其他引擎或者软件中创建 角色布娃娃系统的PhysicsAsset 资产参数,导出的参数如下。
- 胶囊体参数,类型,如球体,胶囊体,BOX,骨骼信息 .
- 关节约束信息。
# 安装 UE-TAPython
使用python 库导出,这里因为虚幻官方的 python库中没有读取胶囊体数据的API,所以使用一个第三库,PythonPhysicsAssetLib - TAColor (opens new window)
Releases · cgerchenhp/UE_TAPython_Plugin_Release · GitHub (opens new window)
下载过来之后解压 得到 TAPython 文件夹,放进项目的Plugins 文件夹即可
关于该库的细节 可直接查看其首页 欢迎来到UE Python 脚本工具TAPython的主页 - TAColor (opens new window)
# 使用脚本
SkeletonToPhysicsAssetToXMl_v3.py
导出保存路径为资产同级目录底下
# XML格式
# 3.1 胶囊体
导出 碰撞体的 类型,如球体,胶囊体,盒子 。
- 大小,半径,长度。
- 碰撞体的轴心位置,相对骨骼的轴心的偏移数据。
- 质量设置无法导出,
radius | 胶囊体 半径 | ![]() |
height | 胶囊体 长度 | |
pos | 胶囊体中心位置, | |
quaternion | 胶囊体旋转 |
# 3.2 关节约束
- 约束的具体参数信息可导出,每个轴向的限制信息等等
- 约束的位置无法导出, 只能是默认在骨骼轴心上。
PhysX3.4文档(9) -- Joints - 知乎 (opens new window)
unreal.ConstraintInstanceBlueprintLibrary — Unreal Python 5.4 (Experimental) documentation
# 3.3 Constraint Behavior
![]() | ![]() | disable_collsion |
![]() | parent_dominates | |
![]() | mass_conditioning | |
![]() | enable_projection | |
![]() | linear_alpha | |
![]() | angular_alpha |
# 3.4 LinearLimits, LinearMotaor
轴向移动限制,Locked不能移动
[TABLE]
3.5 AngularMotor
轴向旋转 限制,free 随意旋转,limited 限制角度旋转,locked 禁止旋转
[TABLE]
# Python细节
# 4.1 对象序列化
是将Python 对象类转换成可保存到文件的文本格式。这里只需重写类 的__dict__方法,如下
class capsules(bodiebase):
def __init__(self) -> None:
self.center = vector3d()
self.rotation = Rotator3d()
self.radius = 0.0
self.length = 0.0
@property
def __dict__(self):
dict_ = {}
dict_["radius"] = cm_m_units_string(self.radius)
dict_["height"] = cm_m_units_string(self.length)
dict_["pos"] = vector3d_to_string(self.pos,6)
dict_["quaternion"] = quaternion_to_string(self.gl_tm.rotation)
dict_["rotation"] = Rotator_to_string(self.euler_rot)
return dict_
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
可以自定义类如何转为 dict ,以及哪些属性可以被转移。
直接使用 xml.etree这个自动库 对象类转换 xml 的元素节点
import xml.etree.ElementTree as ET
def capsules_to_xml(obj):
return ET.Element("capsule" ,obj.__dict__)
2
3
4
# 4.2 物理资产操作
PythonPhysicsAssetLib - TAColor (opens new window)
拿到物理资源的 骨骼树,各个骨骼的名字和序号ID
bone_names,bone_ids = unreal.PythonPhysicsAssetLib.get_bodies_hierarchy(self.current_PhysicsAsset)
2
拿到某个骨骼的碰撞体的 ID数组,如果胶囊体,一个骨骼可以设置多个碰撞体。
bodys_id = unreal.PythonPhysicsAssetLib.get_bodies_from_bone(self.current_PhysicsAsset,bone_body.boneid)
2
拿到某个碰撞体的属性信息,如半径,长度,旋转值(局部坐标系)等。
length = unreal.PythonPhysicsAssetLib.get_body_length(current_asset,bodys_id)
radius = unreal.PythonPhysicsAssetLib.get_body_radius(current_asset,bodys_id)
rotation = unreal.PythonPhysicsAssetLib.get_body_rotation(current_asset,bodys_id)
bone_body_center = unreal.PythonPhysicsAssetLib.get_body_center(current_asset,bodys_id)
size = unreal.PythonPhysicsAssetLib.get_body_size(current_asset,bodys_id)
2
3
4
5
6
# 5. 3dsMax导入
将从虚幻中导出的 物理资产 xml 导入进 3dsMax .
3ds Max 与 UE 的坐标系区别在于 Y 轴方向相反,而 XZ 轴完全一致,
所以 3ds Max 中的位移 (x, y, z),转换到 UE 中就变为 (x, -y, z)。
UE 的quaternion 四元数旋转数值 到3dsMax 里的最终数据是 (x, -y , z, w)
同样使用Python 解析 xml 文件,因为使用 pymxs 所以只支持高版本3dsMax
#max_import_phsics_asset_xml_v2.py
#3dsMax 2022
import xml.etree.ElementTree as ET
from xml.dom import minidom
from pymxs import runtime as rt
rt.execute("fn quat_matrix3 b = (return b as matrix3)")
def to_point3(li):
#ue to 3dsMax
return rt.point3(float(li[0]),float(li[1]) * -1.0,float(li[2]))
def to_quaternion(li):
#ue to 3dsMax
return rt.quat(float(li[0]),float(li[1])* -1.0,float(li[2]),float(li[3]))
def to_matrix3(p1,p2,p3,p4):
return rt.matrix3(p1,p2,p3,p4)
def to_eulerAngles(li):
#ue to 3dsMax
return rt.eulerAngles(float(li[1]),float(li[0])*-1.0,float(li[2])*-1.0)
def import_physics_asset_XMl(xmlfile):
tree = ET.parse(xmlfile)
root = tree.getroot()
rigbody = root.findall("Skp/RigidBody")
for i in rigbody:
p = rt.Capsule()
p.name = i.attrib['name']
rt.select(p)
for o in i.iter("capsule") :
p.radius = float(o.attrib['radius'])
p.height = float(o.attrib['height'])
p.pivot = p.center
pos_str = o.attrib['pos']
pos_ = pos_str.split(" ")
rot_str = o.attrib['quaternion']
rot_ = rot_str.split(" ")
ruler_rot = o.attrib['rotation']
ruler_ = ruler_rot.split(" ")
e_rot = to_eulerAngles(ruler_)
q_rot = to_quaternion(rot_)
#rot_tm = rt.quat_matrix3(e_rot)
rot_tm = rt.quat_matrix3(q_rot)
p.transform = rot_tm
p.pos = to_point3(pos_)
if __name__ == "__main__":
#xmlfile = r"D:\Documents\Unreal Projects\PhysicsAsset_Python\Content\Test\TestAsix.xml"
xmlfile = r"D:\Documents\Unreal Projects\PhysicsAsset_Python\Content\Darkelf_Boss\Darkelf_Boss.xml"
import_physics_asset_XMl(xmlfile)
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