U2A Blender/FBX Pipeline
Reproduzierbarer Export aus den Blender-Quellen der Godot-Referenz nach FBX, geprüft auf beiden Seiten; sechs repräsentative Assets vollständig in Unity verifiziert (normale Einheit g01, Einheit mit Skelett Funkenlanze, Turm Grenzwacht, Ancient, Schlundkrone, Vegetation/Kartenrequisiten), dazu Bastion, Kernwacht und Bossgrotte für die Szene. - tools/blender: Manifest mit Exportregeln je Asset, Exportskript mit Prüfungen (Einheiten, Maßstab, Achsen, Vorderseite, Mesh-Namen, Dreiecke, Materialslots, Normalen, Tangenten, Vertexfarben, Maße, Root Bone, Bone-Namen, Clips, Blend Shapes) gegen die Manifeste der Godot-GLBs, FBX-Rundreise, byteidentische Ausgabe (feste Uhrzeit, PYTHONHASHSEED). - Regeln wie beim GLB-Export: HIGH-RES-Modifikatoren weglassen, logische Namen, Skin-Teile zusammenfügen; 180°-Drehung, damit die Vorderseite nach Unitys Achsen-Bake auf +Z liegt (Unity = (-x, y, z) der Godot-Koordinaten). - Unity: Importregeln (Postprocessor), Verifier gegen das Blender-Protokoll, Vorschaubilder; URP-Asset, Linear-Farbraum, URP-Settings nach Assets/Luneraria/Settings/Rendering. - Ergebnis: 176/176 Blender-Prüfungen, 128/128 Unity-Prüfungen, Dreiecke gleich den Godot-GLBs, Maße auf 0,05 mm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8
Assets/Luneraria/Art.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50ac3333ebb2c4d7a9f94a41495626b4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Art/Buildings.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1f40c6a05032444fdbf7dd895f45db6f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1191
Assets/Luneraria/Art/Buildings/ancient.export.json
Normal file
7
Assets/Luneraria/Art/Buildings/ancient.export.json.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4a082f612d76242bd8aebf43e93aeca2
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Buildings/ancient.fbx
Normal file
111
Assets/Luneraria/Art/Buildings/ancient.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a0437d8104fe34013aacb4fb7c2a5a6c
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
602
Assets/Luneraria/Art/Buildings/bastion.export.json
Normal file
|
|
@ -0,0 +1,602 @@
|
|||
{
|
||||
"id": "bastion",
|
||||
"group": "Buildings",
|
||||
"source": "assets-source/luneraria/g2/bastion.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['Crystal', 'Debris', 'Lower', 'Pennant', 'Ring', 'Ruin', 'Shard_0', 'Shard_1', 'Shard_2', 'Upper', 'Upper_Damaged']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "triangles_match_godot",
|
||||
"ok": true,
|
||||
"detail": "9364 fbx / 9364 godot"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "materials_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.00000 m"
|
||||
},
|
||||
{
|
||||
"check": "no_armature",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "9364 / 9364"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"source_sha256": "5ac677fe95f3c65364fa4003b9cae694ad58734b157238f196f4d926de655d60",
|
||||
"removed_modifiers": 0,
|
||||
"kind": "static",
|
||||
"fps": 30.0,
|
||||
"objects": 11,
|
||||
"meshes": {
|
||||
"Lower": {
|
||||
"mesh": "Lower",
|
||||
"triangles": 658,
|
||||
"vertices": 368,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Metal_Iron"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.7395,
|
||||
0.0,
|
||||
-2.25
|
||||
],
|
||||
"max": [
|
||||
1.7395,
|
||||
2.6655,
|
||||
1.6437
|
||||
]
|
||||
}
|
||||
},
|
||||
"Upper": {
|
||||
"mesh": "Upper",
|
||||
"triangles": 3272,
|
||||
"vertices": 1722,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Rune_Team",
|
||||
"LN_Stone_Dark",
|
||||
"LN_Metal_Iron",
|
||||
"LN_Wood"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.5347,
|
||||
2.4409,
|
||||
-1.5347
|
||||
],
|
||||
"max": [
|
||||
1.5347,
|
||||
7.1605,
|
||||
1.5347
|
||||
]
|
||||
}
|
||||
},
|
||||
"Upper_Damaged": {
|
||||
"mesh": "Upper_Damaged",
|
||||
"triangles": 2948,
|
||||
"vertices": 1554,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Rune_Team",
|
||||
"LN_Stone_Dark",
|
||||
"LN_Metal_Iron",
|
||||
"LN_Wood"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.5368,
|
||||
2.3209,
|
||||
-1.5372
|
||||
],
|
||||
"max": [
|
||||
1.4687,
|
||||
7.1605,
|
||||
1.5405
|
||||
]
|
||||
}
|
||||
},
|
||||
"Debris": {
|
||||
"mesh": "Debris",
|
||||
"triangles": 316,
|
||||
"vertices": 178,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.1156,
|
||||
-0.3891,
|
||||
-1.7064
|
||||
],
|
||||
"max": [
|
||||
1.8813,
|
||||
0.54,
|
||||
1.9496
|
||||
]
|
||||
}
|
||||
},
|
||||
"Crystal": {
|
||||
"mesh": "Crystal",
|
||||
"triangles": 24,
|
||||
"vertices": 14,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.4934,
|
||||
5.54,
|
||||
-0.4411
|
||||
],
|
||||
"max": [
|
||||
0.4885,
|
||||
7.06,
|
||||
0.409
|
||||
]
|
||||
}
|
||||
},
|
||||
"Ring": {
|
||||
"mesh": "Ring",
|
||||
"triangles": 640,
|
||||
"vertices": 320,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Metal_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.865,
|
||||
6.15,
|
||||
-0.865
|
||||
],
|
||||
"max": [
|
||||
0.865,
|
||||
6.25,
|
||||
0.865
|
||||
]
|
||||
}
|
||||
},
|
||||
"Shard_0": {
|
||||
"mesh": "Shard_0",
|
||||
"triangles": 20,
|
||||
"vertices": 12,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.1308,
|
||||
6.17,
|
||||
-0.106
|
||||
],
|
||||
"max": [
|
||||
-0.9277,
|
||||
6.61,
|
||||
0.1012
|
||||
]
|
||||
}
|
||||
},
|
||||
"Shard_1": {
|
||||
"mesh": "Shard_1",
|
||||
"triangles": 20,
|
||||
"vertices": 12,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
0.397,
|
||||
6.17,
|
||||
0.7782
|
||||
],
|
||||
"max": [
|
||||
0.601,
|
||||
6.61,
|
||||
0.9923
|
||||
]
|
||||
}
|
||||
},
|
||||
"Shard_2": {
|
||||
"mesh": "Shard_2",
|
||||
"triangles": 20,
|
||||
"vertices": 12,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
0.3992,
|
||||
6.17,
|
||||
-0.9903
|
||||
],
|
||||
"max": [
|
||||
0.6009,
|
||||
6.61,
|
||||
-0.779
|
||||
]
|
||||
}
|
||||
},
|
||||
"Pennant": {
|
||||
"mesh": "Pennant",
|
||||
"triangles": 64,
|
||||
"vertices": 45,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Cloth_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
0.06,
|
||||
5.65,
|
||||
-1.46
|
||||
],
|
||||
"max": [
|
||||
0.76,
|
||||
6.8,
|
||||
-1.46
|
||||
]
|
||||
}
|
||||
},
|
||||
"Ruin": {
|
||||
"mesh": "Ruin",
|
||||
"triangles": 1382,
|
||||
"vertices": 770,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.0369,
|
||||
-0.3691,
|
||||
-2.5389
|
||||
],
|
||||
"max": [
|
||||
2.9008,
|
||||
2.6896,
|
||||
1.9476
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.1156,
|
||||
-0.3891,
|
||||
-2.5389
|
||||
],
|
||||
"max": [
|
||||
2.9008,
|
||||
7.1605,
|
||||
1.9496
|
||||
]
|
||||
},
|
||||
"clips": [],
|
||||
"expected_from_godot": {
|
||||
"triangles": 9364,
|
||||
"bounds_godot": {
|
||||
"min": [
|
||||
-1.7395,
|
||||
0.0,
|
||||
-2.25
|
||||
],
|
||||
"max": [
|
||||
1.7395,
|
||||
7.1605,
|
||||
1.6437
|
||||
]
|
||||
},
|
||||
"resource_path": "res://assets/luneraria/g2/bastion.glb"
|
||||
},
|
||||
"meshes_without_uv": [
|
||||
"Crystal",
|
||||
"Debris",
|
||||
"Lower",
|
||||
"Shard_0",
|
||||
"Shard_1",
|
||||
"Shard_2"
|
||||
],
|
||||
"triangles": 9364,
|
||||
"fbx": "Assets/Luneraria/Art/Buildings/bastion.fbx",
|
||||
"fbx_bytes": 618812,
|
||||
"ok": true
|
||||
}
|
||||
7
Assets/Luneraria/Art/Buildings/bastion.export.json.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b6d3f51223b7f4f00b4ae9778a64127e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Buildings/bastion.fbx
Normal file
111
Assets/Luneraria/Art/Buildings/bastion.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6633f0fd87c194e13a26c46c8a57a3a8
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
632
Assets/Luneraria/Art/Buildings/bossgrotte.export.json
Normal file
|
|
@ -0,0 +1,632 @@
|
|||
{
|
||||
"id": "bossgrotte",
|
||||
"group": "Buildings",
|
||||
"source": "assets-source/luneraria/g2/bossgrotte.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['Altar', 'Cave', 'CaveGlow', 'Channel', 'Floor', 'Gate', 'PillarCrystals', 'Pillars', 'Platform', 'Rocks', 'Runes', 'Source']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "triangles_match_godot",
|
||||
"ok": true,
|
||||
"detail": "15182 fbx / 15182 godot"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "materials_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.00000 m"
|
||||
},
|
||||
{
|
||||
"check": "no_armature",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "15182 / 15182"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"source_sha256": "c3a87a8e7b0b8e0778ba7f9f274584e98e5c70a8229bc1cbee7ed9fd6aba7d9e",
|
||||
"removed_modifiers": 0,
|
||||
"kind": "static",
|
||||
"fps": 30.0,
|
||||
"objects": 12,
|
||||
"meshes": {
|
||||
"Floor": {
|
||||
"mesh": "Floor",
|
||||
"triangles": 2108,
|
||||
"vertices": 1097,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Grotto"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-7.7775,
|
||||
-0.4,
|
||||
-7.7874
|
||||
],
|
||||
"max": [
|
||||
7.7755,
|
||||
0.26,
|
||||
7.7976
|
||||
]
|
||||
}
|
||||
},
|
||||
"Runes": {
|
||||
"mesh": "Runes",
|
||||
"triangles": 1164,
|
||||
"vertices": 712,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Rune_Grotto"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-4.72,
|
||||
0.104,
|
||||
-7.9255
|
||||
],
|
||||
"max": [
|
||||
7.9255,
|
||||
5.899,
|
||||
4.72
|
||||
]
|
||||
}
|
||||
},
|
||||
"Platform": {
|
||||
"mesh": "Platform",
|
||||
"triangles": 808,
|
||||
"vertices": 433,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Grotto"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.8,
|
||||
-0.02,
|
||||
-3.8
|
||||
],
|
||||
"max": [
|
||||
3.8,
|
||||
0.125,
|
||||
0.8
|
||||
]
|
||||
}
|
||||
},
|
||||
"Altar": {
|
||||
"mesh": "Altar",
|
||||
"triangles": 552,
|
||||
"vertices": 280,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Grotto"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
1.7789,
|
||||
-0.05,
|
||||
-4.4738
|
||||
],
|
||||
"max": [
|
||||
4.4738,
|
||||
3.45,
|
||||
-1.7789
|
||||
]
|
||||
}
|
||||
},
|
||||
"Source": {
|
||||
"mesh": "Source",
|
||||
"triangles": 192,
|
||||
"vertices": 112,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Grotto"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
2.64,
|
||||
0.5,
|
||||
-3.4746
|
||||
],
|
||||
"max": [
|
||||
3.6064,
|
||||
2.7,
|
||||
-2.7716
|
||||
]
|
||||
}
|
||||
},
|
||||
"Gate": {
|
||||
"mesh": "Gate",
|
||||
"triangles": 3944,
|
||||
"vertices": 2016,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Grotto",
|
||||
"LN_Metal_Bronze"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
3.2222,
|
||||
-0.5,
|
||||
-9.435
|
||||
],
|
||||
"max": [
|
||||
9.435,
|
||||
7.499,
|
||||
-3.2222
|
||||
]
|
||||
}
|
||||
},
|
||||
"Cave": {
|
||||
"mesh": "Cave",
|
||||
"triangles": 424,
|
||||
"vertices": 232,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Cave",
|
||||
"LN_Stone_Dark"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
4.575,
|
||||
-1.93,
|
||||
-10.0692
|
||||
],
|
||||
"max": [
|
||||
10.0692,
|
||||
3.7,
|
||||
-4.575
|
||||
]
|
||||
}
|
||||
},
|
||||
"CaveGlow": {
|
||||
"mesh": "CaveGlow",
|
||||
"triangles": 182,
|
||||
"vertices": 117,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Water_Glow",
|
||||
"LN_Crystal_Grotto"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
5.1204,
|
||||
-0.97,
|
||||
-9.4328
|
||||
],
|
||||
"max": [
|
||||
9.5452,
|
||||
2.7,
|
||||
-5.4993
|
||||
]
|
||||
}
|
||||
},
|
||||
"Channel": {
|
||||
"mesh": "Channel",
|
||||
"triangles": 600,
|
||||
"vertices": 304,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Water_Glow"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.3712,
|
||||
0.26,
|
||||
-7.0092
|
||||
],
|
||||
"max": [
|
||||
7.0092,
|
||||
0.28,
|
||||
0.3712
|
||||
]
|
||||
}
|
||||
},
|
||||
"Pillars": {
|
||||
"mesh": "Pillars",
|
||||
"triangles": 4328,
|
||||
"vertices": 2280,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Grotto"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-7.7579,
|
||||
-0.05,
|
||||
-7.5321
|
||||
],
|
||||
"max": [
|
||||
7.5454,
|
||||
5.961,
|
||||
7.7587
|
||||
]
|
||||
}
|
||||
},
|
||||
"PillarCrystals": {
|
||||
"mesh": "PillarCrystals",
|
||||
"triangles": 80,
|
||||
"vertices": 48,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Grotto"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-6.4468,
|
||||
5.23,
|
||||
-7.0317
|
||||
],
|
||||
"max": [
|
||||
7.014,
|
||||
6.03,
|
||||
6.441
|
||||
]
|
||||
}
|
||||
},
|
||||
"Rocks": {
|
||||
"mesh": "Rocks",
|
||||
"triangles": 800,
|
||||
"vertices": 420,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Rock"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.9737,
|
||||
-0.6391,
|
||||
-10.4646
|
||||
],
|
||||
"max": [
|
||||
10.5442,
|
||||
7.6927,
|
||||
2.8772
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-7.7775,
|
||||
-1.93,
|
||||
-10.4646
|
||||
],
|
||||
"max": [
|
||||
10.5442,
|
||||
7.6927,
|
||||
7.7976
|
||||
]
|
||||
},
|
||||
"clips": [],
|
||||
"expected_from_godot": {
|
||||
"triangles": 15182,
|
||||
"bounds_godot": {
|
||||
"min": [
|
||||
-10.5442,
|
||||
-1.93,
|
||||
-10.4646
|
||||
],
|
||||
"max": [
|
||||
7.7775,
|
||||
7.6927,
|
||||
7.7976
|
||||
]
|
||||
},
|
||||
"resource_path": "res://assets/luneraria/g2/bossgrotte.glb"
|
||||
},
|
||||
"meshes_without_uv": [
|
||||
"Cave",
|
||||
"PillarCrystals",
|
||||
"Rocks",
|
||||
"Source"
|
||||
],
|
||||
"triangles": 15182,
|
||||
"fbx": "Assets/Luneraria/Art/Buildings/bossgrotte.fbx",
|
||||
"fbx_bytes": 989708,
|
||||
"ok": true
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b3c1a5924044546adb0dba298c3ddc35
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Buildings/bossgrotte.fbx
Normal file
111
Assets/Luneraria/Art/Buildings/bossgrotte.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 39a4b40e68ab84129824e427365b5868
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
456
Assets/Luneraria/Art/Buildings/grenzwacht.export.json
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
{
|
||||
"id": "grenzwacht",
|
||||
"group": "Buildings",
|
||||
"source": "assets-source/luneraria/g2/grenzwacht.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['Crystal', 'Debris', 'Lower', 'Pennant', 'Ruin', 'Upper', 'Upper_Damaged']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "triangles_match_godot",
|
||||
"ok": true,
|
||||
"detail": "6516 fbx / 6516 godot"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "materials_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.00000 m"
|
||||
},
|
||||
{
|
||||
"check": "no_armature",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "6516 / 6516"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"source_sha256": "7067f4f3349918e412a3ee684651753bbb3ee958a46dd3775af6b93661d7e96f",
|
||||
"removed_modifiers": 0,
|
||||
"kind": "static",
|
||||
"fps": 30.0,
|
||||
"objects": 7,
|
||||
"meshes": {
|
||||
"Lower": {
|
||||
"mesh": "Lower",
|
||||
"triangles": 550,
|
||||
"vertices": 296,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Wood"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.3752,
|
||||
0.0,
|
||||
-1.3735
|
||||
],
|
||||
"max": [
|
||||
1.3717,
|
||||
2.3142,
|
||||
1.3678
|
||||
]
|
||||
}
|
||||
},
|
||||
"Upper": {
|
||||
"mesh": "Upper",
|
||||
"triangles": 2536,
|
||||
"vertices": 1336,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Rune_Team",
|
||||
"LN_Stone_Dark",
|
||||
"LN_Metal_Iron",
|
||||
"LN_Wood"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.1568,
|
||||
2.18,
|
||||
-1.1568
|
||||
],
|
||||
"max": [
|
||||
1.1568,
|
||||
6.0601,
|
||||
1.1568
|
||||
]
|
||||
}
|
||||
},
|
||||
"Upper_Damaged": {
|
||||
"mesh": "Upper_Damaged",
|
||||
"triangles": 2164,
|
||||
"vertices": 1136,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Rune_Team",
|
||||
"LN_Stone_Dark",
|
||||
"LN_Wood",
|
||||
"LN_Metal_Iron"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.1568,
|
||||
2.18,
|
||||
-1.1569
|
||||
],
|
||||
"max": [
|
||||
1.1606,
|
||||
6.0601,
|
||||
1.1364
|
||||
]
|
||||
}
|
||||
},
|
||||
"Debris": {
|
||||
"mesh": "Debris",
|
||||
"triangles": 140,
|
||||
"vertices": 84,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.0393,
|
||||
-0.0358,
|
||||
-1.4479
|
||||
],
|
||||
"max": [
|
||||
1.8685,
|
||||
0.2255,
|
||||
0.2742
|
||||
]
|
||||
}
|
||||
},
|
||||
"Crystal": {
|
||||
"mesh": "Crystal",
|
||||
"triangles": 24,
|
||||
"vertices": 14,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.3468,
|
||||
4.7,
|
||||
-0.3102
|
||||
],
|
||||
"max": [
|
||||
0.345,
|
||||
5.84,
|
||||
0.3126
|
||||
]
|
||||
}
|
||||
},
|
||||
"Pennant": {
|
||||
"mesh": "Pennant",
|
||||
"triangles": 64,
|
||||
"vertices": 45,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Cloth_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
0.06,
|
||||
4.72,
|
||||
-1.02
|
||||
],
|
||||
"max": [
|
||||
0.68,
|
||||
5.72,
|
||||
-1.02
|
||||
]
|
||||
}
|
||||
},
|
||||
"Ruin": {
|
||||
"mesh": "Ruin",
|
||||
"triangles": 1038,
|
||||
"vertices": 580,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Team",
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.2575,
|
||||
-0.0653,
|
||||
-2.5526
|
||||
],
|
||||
"max": [
|
||||
1.9658,
|
||||
1.7462,
|
||||
1.3683
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.2575,
|
||||
-0.0653,
|
||||
-2.5526
|
||||
],
|
||||
"max": [
|
||||
1.9658,
|
||||
6.0601,
|
||||
1.3683
|
||||
]
|
||||
},
|
||||
"clips": [],
|
||||
"expected_from_godot": {
|
||||
"triangles": 6516,
|
||||
"bounds_godot": {
|
||||
"min": [
|
||||
-1.3717,
|
||||
0.0,
|
||||
-1.3735
|
||||
],
|
||||
"max": [
|
||||
1.3752,
|
||||
6.0601,
|
||||
1.3678
|
||||
]
|
||||
},
|
||||
"resource_path": "res://assets/luneraria/g2/grenzwacht.glb"
|
||||
},
|
||||
"meshes_without_uv": [
|
||||
"Crystal",
|
||||
"Debris"
|
||||
],
|
||||
"triangles": 6516,
|
||||
"fbx": "Assets/Luneraria/Art/Buildings/grenzwacht.fbx",
|
||||
"fbx_bytes": 457404,
|
||||
"ok": true
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81cb37d5386d048999e1ca915d0cb88d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Buildings/grenzwacht.fbx
Normal file
111
Assets/Luneraria/Art/Buildings/grenzwacht.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5b76880584cb448b5b6c8a5f93db8b54
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
526
Assets/Luneraria/Art/Buildings/kernwacht.export.json
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
{
|
||||
"id": "kernwacht",
|
||||
"group": "Buildings",
|
||||
"source": "assets-source/luneraria/g2/kernwacht.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['Banner_L', 'Banner_R', 'Crystal', 'Debris', 'Lower', 'Ring', 'Ruin', 'Upper', 'Upper_Damaged']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "triangles_match_godot",
|
||||
"ok": true,
|
||||
"detail": "9224 fbx / 9224 godot"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "materials_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.00000 m"
|
||||
},
|
||||
{
|
||||
"check": "no_armature",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "9224 / 9224"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"source_sha256": "2797f6f7b705a99333dbfdfce029a2f4894a74d2fb7939eb108ab2eaf7edd09e",
|
||||
"removed_modifiers": 0,
|
||||
"kind": "static",
|
||||
"fps": 30.0,
|
||||
"objects": 9,
|
||||
"meshes": {
|
||||
"Lower": {
|
||||
"mesh": "Lower",
|
||||
"triangles": 548,
|
||||
"vertices": 304,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Rune_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.8139,
|
||||
0.0,
|
||||
-1.8017
|
||||
],
|
||||
"max": [
|
||||
1.8045,
|
||||
2.76,
|
||||
1.806
|
||||
]
|
||||
}
|
||||
},
|
||||
"Upper": {
|
||||
"mesh": "Upper",
|
||||
"triangles": 3280,
|
||||
"vertices": 1660,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Metal_Team",
|
||||
"LN_Crystal_Team",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Iron"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.6442,
|
||||
2.5345,
|
||||
-1.0915
|
||||
],
|
||||
"max": [
|
||||
1.6442,
|
||||
8.33,
|
||||
1.734
|
||||
]
|
||||
}
|
||||
},
|
||||
"Upper_Damaged": {
|
||||
"mesh": "Upper_Damaged",
|
||||
"triangles": 3280,
|
||||
"vertices": 1660,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Metal_Team",
|
||||
"LN_Crystal_Team",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Metal_Iron"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.6442,
|
||||
2.5345,
|
||||
-1.0915
|
||||
],
|
||||
"max": [
|
||||
1.6442,
|
||||
8.33,
|
||||
1.734
|
||||
]
|
||||
}
|
||||
},
|
||||
"Debris": {
|
||||
"mesh": "Debris",
|
||||
"triangles": 160,
|
||||
"vertices": 96,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Pale"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.1991,
|
||||
-0.0421,
|
||||
-1.8567
|
||||
],
|
||||
"max": [
|
||||
1.8296,
|
||||
0.2606,
|
||||
0.2916
|
||||
]
|
||||
}
|
||||
},
|
||||
"Crystal": {
|
||||
"mesh": "Crystal",
|
||||
"triangles": 24,
|
||||
"vertices": 14,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.5554,
|
||||
4.51,
|
||||
-0.4884
|
||||
],
|
||||
"max": [
|
||||
0.5682,
|
||||
6.25,
|
||||
0.5124
|
||||
]
|
||||
}
|
||||
},
|
||||
"Ring": {
|
||||
"mesh": "Ring",
|
||||
"triangles": 640,
|
||||
"vertices": 320,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Metal_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.03,
|
||||
5.195,
|
||||
-1.03
|
||||
],
|
||||
"max": [
|
||||
1.03,
|
||||
5.305,
|
||||
1.03
|
||||
]
|
||||
}
|
||||
},
|
||||
"Banner_L": {
|
||||
"mesh": "Banner_L",
|
||||
"triangles": 80,
|
||||
"vertices": 55,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Cloth_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
1.5597,
|
||||
3.9,
|
||||
-1.2585
|
||||
],
|
||||
"max": [
|
||||
1.8697,
|
||||
5.5,
|
||||
-0.7215
|
||||
]
|
||||
}
|
||||
},
|
||||
"Banner_R": {
|
||||
"mesh": "Banner_R",
|
||||
"triangles": 80,
|
||||
"vertices": 55,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Cloth_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.8697,
|
||||
3.9,
|
||||
-1.2585
|
||||
],
|
||||
"max": [
|
||||
-1.5597,
|
||||
5.5,
|
||||
-0.7215
|
||||
]
|
||||
}
|
||||
},
|
||||
"Ruin": {
|
||||
"mesh": "Ruin",
|
||||
"triangles": 1132,
|
||||
"vertices": 632,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Stone_Dark",
|
||||
"LN_Stone_Pale",
|
||||
"LN_Rune_Team",
|
||||
"LN_Crystal_Team"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-6.0762,
|
||||
-2.3959,
|
||||
-2.1939
|
||||
],
|
||||
"max": [
|
||||
2.3962,
|
||||
2.0939,
|
||||
1.8126
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-6.0762,
|
||||
-2.3959,
|
||||
-2.1939
|
||||
],
|
||||
"max": [
|
||||
2.3962,
|
||||
8.33,
|
||||
1.8126
|
||||
]
|
||||
},
|
||||
"clips": [],
|
||||
"expected_from_godot": {
|
||||
"triangles": 9224,
|
||||
"bounds_godot": {
|
||||
"min": [
|
||||
-1.8045,
|
||||
0.0,
|
||||
-1.8017
|
||||
],
|
||||
"max": [
|
||||
1.8139,
|
||||
8.33,
|
||||
1.806
|
||||
]
|
||||
},
|
||||
"resource_path": "res://assets/luneraria/g2/kernwacht.glb"
|
||||
},
|
||||
"meshes_without_uv": [
|
||||
"Crystal",
|
||||
"Debris"
|
||||
],
|
||||
"triangles": 9224,
|
||||
"fbx": "Assets/Luneraria/Art/Buildings/kernwacht.fbx",
|
||||
"fbx_bytes": 732684,
|
||||
"ok": true
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5dc29c90a350446e480591bab7513b23
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Buildings/kernwacht.fbx
Normal file
111
Assets/Luneraria/Art/Buildings/kernwacht.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2d354ddf8728c467da524d4c540efccd
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Art/Characters.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f870578f70b3a45ccbfa68cceccd2579
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
405
Assets/Luneraria/Art/Characters/funkenlanze.export.json
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
{
|
||||
"id": "funkenlanze",
|
||||
"group": "Characters",
|
||||
"source": "assets-source/phase18/funkenlanze.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['FunkenBody']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "triangles_match_godot",
|
||||
"ok": true,
|
||||
"detail": "24036 fbx / 24036 godot"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.00005 m"
|
||||
},
|
||||
{
|
||||
"check": "one_armature",
|
||||
"ok": true,
|
||||
"detail": "['FunkenRig']"
|
||||
},
|
||||
{
|
||||
"check": "single_root_bone",
|
||||
"ok": true,
|
||||
"detail": "['Root']"
|
||||
},
|
||||
{
|
||||
"check": "root_bone_name",
|
||||
"ok": true,
|
||||
"detail": "['Root']"
|
||||
},
|
||||
{
|
||||
"check": "bone_count_match_godot",
|
||||
"ok": true,
|
||||
"detail": "26 / 26"
|
||||
},
|
||||
{
|
||||
"check": "bone_names_portable",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "skinned_meshes_present",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "clips_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "required_clips_present",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "24036 / 24036"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_bones",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_clips",
|
||||
"ok": true,
|
||||
"detail": "['ability', 'attack_a', 'attack_b', 'death', 'hit', 'idle', 'start', 'stop', 'walk']"
|
||||
}
|
||||
],
|
||||
"source_sha256": "e21714e04a93f6266aae2edbf7db69c25d33b00429ebf62c01c6f832e18a771f",
|
||||
"removed_modifiers": 0,
|
||||
"joined_parts": 104,
|
||||
"kind": "skinned",
|
||||
"fps": 30.0,
|
||||
"objects": 2,
|
||||
"meshes": {
|
||||
"FunkenBody": {
|
||||
"mesh": "FunkenBody",
|
||||
"triangles": 24036,
|
||||
"vertices": 12226,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"FL_Basalt",
|
||||
"FL_BurnishedBronze",
|
||||
"FL_Obsidian",
|
||||
"FL_Ember",
|
||||
"FL_Joint",
|
||||
"FL_BronzeEdge",
|
||||
"FL_Iron",
|
||||
"FL_Crystal"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap"
|
||||
],
|
||||
"color_attributes": [
|
||||
"SurfaceColor"
|
||||
],
|
||||
"active_color": "SurfaceColor",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": true,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.5652,
|
||||
-0.0104,
|
||||
-0.2945
|
||||
],
|
||||
"max": [
|
||||
0.43,
|
||||
2.0212,
|
||||
1.435
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {
|
||||
"FunkenRig": {
|
||||
"bones": [
|
||||
"Root",
|
||||
"Pelvis",
|
||||
"Spine",
|
||||
"Chest",
|
||||
"Neck",
|
||||
"Head",
|
||||
"Clavicle.L",
|
||||
"UpperArm.L",
|
||||
"Forearm.L",
|
||||
"Hand.L",
|
||||
"Index.L",
|
||||
"Clavicle.R",
|
||||
"UpperArm.R",
|
||||
"Forearm.R",
|
||||
"Hand.R",
|
||||
"Index.R",
|
||||
"Weapon",
|
||||
"Bolt",
|
||||
"Crystal",
|
||||
"Chamber",
|
||||
"Thigh.L",
|
||||
"Shin.L",
|
||||
"Foot.L",
|
||||
"Thigh.R",
|
||||
"Shin.R",
|
||||
"Foot.R"
|
||||
],
|
||||
"roots": [
|
||||
"Root"
|
||||
]
|
||||
}
|
||||
},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.5652,
|
||||
-0.0104,
|
||||
-0.2945
|
||||
],
|
||||
"max": [
|
||||
0.43,
|
||||
2.0212,
|
||||
1.435
|
||||
]
|
||||
},
|
||||
"clips": [
|
||||
{
|
||||
"name": "ability",
|
||||
"frames": [
|
||||
0.0,
|
||||
39.0
|
||||
],
|
||||
"seconds": 1.3,
|
||||
"loop": false,
|
||||
"contact_seconds": 0.9
|
||||
},
|
||||
{
|
||||
"name": "attack_a",
|
||||
"frames": [
|
||||
0.0,
|
||||
39.0
|
||||
],
|
||||
"seconds": 1.3,
|
||||
"loop": false,
|
||||
"contact_seconds": 0.9
|
||||
},
|
||||
{
|
||||
"name": "attack_b",
|
||||
"frames": [
|
||||
0.0,
|
||||
39.0
|
||||
],
|
||||
"seconds": 1.3,
|
||||
"loop": false,
|
||||
"contact_seconds": 0.9
|
||||
},
|
||||
{
|
||||
"name": "death",
|
||||
"frames": [
|
||||
0.0,
|
||||
60.0
|
||||
],
|
||||
"seconds": 2.0,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "hit",
|
||||
"frames": [
|
||||
0.0,
|
||||
15.0
|
||||
],
|
||||
"seconds": 0.5,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "idle",
|
||||
"frames": [
|
||||
0.0,
|
||||
90.0
|
||||
],
|
||||
"seconds": 3.0,
|
||||
"loop": true,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"frames": [
|
||||
0.0,
|
||||
12.0
|
||||
],
|
||||
"seconds": 0.4,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "stop",
|
||||
"frames": [
|
||||
0.0,
|
||||
12.0
|
||||
],
|
||||
"seconds": 0.4,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "walk",
|
||||
"frames": [
|
||||
0.0,
|
||||
36.0
|
||||
],
|
||||
"seconds": 1.2,
|
||||
"loop": true,
|
||||
"contact_seconds": -1.0
|
||||
}
|
||||
],
|
||||
"expected_from_godot": {
|
||||
"triangles": 24036,
|
||||
"bounds_godot": {
|
||||
"min": [
|
||||
-0.4300000071525574,
|
||||
-0.010409347712993622,
|
||||
-0.2945486903190613
|
||||
],
|
||||
"max": [
|
||||
0.5651692152023315,
|
||||
2.021195411682129,
|
||||
1.4350000619888306
|
||||
]
|
||||
},
|
||||
"bones": 26,
|
||||
"clips": [
|
||||
"idle",
|
||||
"start",
|
||||
"walk",
|
||||
"stop",
|
||||
"attack_a",
|
||||
"attack_b",
|
||||
"hit",
|
||||
"ability",
|
||||
"death"
|
||||
],
|
||||
"resource_path": "res://assets/characters/funkenlanze.glb"
|
||||
},
|
||||
"meshes_without_uv": [],
|
||||
"triangles": 24036,
|
||||
"fbx": "Assets/Luneraria/Art/Characters/funkenlanze.fbx",
|
||||
"fbx_bytes": 3675308,
|
||||
"ok": true
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 373bb56c33f234adeac31c870ede9072
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Characters/funkenlanze.fbx
Normal file
393
Assets/Luneraria/Art/Characters/funkenlanze.fbx.meta
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 652ee682a82c34ff99c2eb11cd218f5e
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations:
|
||||
- serializedVersion: 16
|
||||
name: ability
|
||||
takeName: FunkenRig|ability
|
||||
internalID: -1787258805998246360
|
||||
firstFrame: 0
|
||||
lastFrame: 39
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.6923077
|
||||
functionName: OnLuneContact
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: attack_a
|
||||
takeName: FunkenRig|attack_a
|
||||
internalID: -6628820121952251911
|
||||
firstFrame: 0
|
||||
lastFrame: 39
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.6923077
|
||||
functionName: OnLuneContact
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: attack_b
|
||||
takeName: FunkenRig|attack_b
|
||||
internalID: -2963360793056117044
|
||||
firstFrame: 0
|
||||
lastFrame: 39
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.6923077
|
||||
functionName: OnLuneContact
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: death
|
||||
takeName: FunkenRig|death
|
||||
internalID: 9159963757730041032
|
||||
firstFrame: 0
|
||||
lastFrame: 60
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: hit
|
||||
takeName: FunkenRig|hit
|
||||
internalID: -4707179913997139171
|
||||
firstFrame: 0
|
||||
lastFrame: 15
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: idle
|
||||
takeName: FunkenRig|idle
|
||||
internalID: -1348917559068937310
|
||||
firstFrame: 0
|
||||
lastFrame: 90
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 1
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: start
|
||||
takeName: FunkenRig|start
|
||||
internalID: 6150794267048699607
|
||||
firstFrame: 0
|
||||
lastFrame: 12
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: stop
|
||||
takeName: FunkenRig|stop
|
||||
internalID: 637536857275861776
|
||||
firstFrame: 0
|
||||
lastFrame: 12
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: walk
|
||||
takeName: FunkenRig|walk
|
||||
internalID: 7607972658950073716
|
||||
firstFrame: 0
|
||||
lastFrame: 36
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 1
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 1
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 2
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 1
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
431
Assets/Luneraria/Art/Characters/schlundkrone.export.json
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
{
|
||||
"id": "schlundkrone",
|
||||
"group": "Characters",
|
||||
"source": "assets-source/luneraria/g2/schlundkrone.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['SchlundkroneBody']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "triangles_match_godot",
|
||||
"ok": true,
|
||||
"detail": "5712 fbx / 5712 godot"
|
||||
},
|
||||
{
|
||||
"check": "materials_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.00000 m"
|
||||
},
|
||||
{
|
||||
"check": "one_armature",
|
||||
"ok": true,
|
||||
"detail": "['SchlundkroneRig']"
|
||||
},
|
||||
{
|
||||
"check": "single_root_bone",
|
||||
"ok": true,
|
||||
"detail": "['Root']"
|
||||
},
|
||||
{
|
||||
"check": "root_bone_name",
|
||||
"ok": true,
|
||||
"detail": "['Root']"
|
||||
},
|
||||
{
|
||||
"check": "bone_names_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bone_count_match_godot",
|
||||
"ok": true,
|
||||
"detail": "24 / 24"
|
||||
},
|
||||
{
|
||||
"check": "bone_names_portable",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "skinned_meshes_present",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "clips_match_godot",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "required_clips_present",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "clip_lengths_match_godot",
|
||||
"ok": true,
|
||||
"detail": "largest difference 0.0000 s"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "5712 / 5712"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_bones",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_clips",
|
||||
"ok": true,
|
||||
"detail": "['ability', 'attack_a', 'attack_b', 'death', 'hit', 'idle', 'roar', 'start', 'stop', 'victory', 'walk']"
|
||||
}
|
||||
],
|
||||
"source_sha256": "21f116f3ccf293b7f4c86bd23c07f86a41bd5d29c032f28bdb5c44043e9c6d7b",
|
||||
"removed_modifiers": 0,
|
||||
"kind": "skinned",
|
||||
"fps": 30.0,
|
||||
"objects": 2,
|
||||
"meshes": {
|
||||
"SchlundkroneBody": {
|
||||
"mesh": "SchlundkroneBody",
|
||||
"triangles": 5712,
|
||||
"vertices": 3048,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"LN_Boss_Hide",
|
||||
"LN_Boss_Bone",
|
||||
"LN_Crystal_Boss",
|
||||
"LN_Boss_Bronze"
|
||||
],
|
||||
"uv_layers": [
|
||||
"UVMap",
|
||||
"UVRest"
|
||||
],
|
||||
"color_attributes": [
|
||||
"Col"
|
||||
],
|
||||
"active_color": "Col",
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": true,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.3273,
|
||||
0.0053,
|
||||
-0.5532
|
||||
],
|
||||
"max": [
|
||||
1.2307,
|
||||
3.3182,
|
||||
0.9253
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {
|
||||
"SchlundkroneRig": {
|
||||
"bones": [
|
||||
"Root",
|
||||
"Hips",
|
||||
"Spine",
|
||||
"Chest",
|
||||
"Neck",
|
||||
"Head",
|
||||
"Jaw",
|
||||
"Crown",
|
||||
"Maw.L",
|
||||
"Shoulder.L",
|
||||
"UpperArm.L",
|
||||
"Forearm.L",
|
||||
"Hand.L",
|
||||
"Maw.R",
|
||||
"Shoulder.R",
|
||||
"UpperArm.R",
|
||||
"Forearm.R",
|
||||
"Hand.R",
|
||||
"Thigh.L",
|
||||
"Shin.L",
|
||||
"Foot.L",
|
||||
"Thigh.R",
|
||||
"Shin.R",
|
||||
"Foot.R"
|
||||
],
|
||||
"roots": [
|
||||
"Root"
|
||||
]
|
||||
}
|
||||
},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.3273,
|
||||
0.0053,
|
||||
-0.5532
|
||||
],
|
||||
"max": [
|
||||
1.2307,
|
||||
3.3182,
|
||||
0.9253
|
||||
]
|
||||
},
|
||||
"clips": [
|
||||
{
|
||||
"name": "ability",
|
||||
"frames": [
|
||||
0.0,
|
||||
39.0
|
||||
],
|
||||
"seconds": 1.3,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "attack_a",
|
||||
"frames": [
|
||||
0.0,
|
||||
39.0
|
||||
],
|
||||
"seconds": 1.3,
|
||||
"loop": false,
|
||||
"contact_seconds": 0.9
|
||||
},
|
||||
{
|
||||
"name": "attack_b",
|
||||
"frames": [
|
||||
0.0,
|
||||
39.0
|
||||
],
|
||||
"seconds": 1.3,
|
||||
"loop": false,
|
||||
"contact_seconds": 0.9
|
||||
},
|
||||
{
|
||||
"name": "death",
|
||||
"frames": [
|
||||
0.0,
|
||||
66.0
|
||||
],
|
||||
"seconds": 2.2,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "hit",
|
||||
"frames": [
|
||||
0.0,
|
||||
15.0
|
||||
],
|
||||
"seconds": 0.5,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "idle",
|
||||
"frames": [
|
||||
0.0,
|
||||
90.0
|
||||
],
|
||||
"seconds": 3.0,
|
||||
"loop": true,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "roar",
|
||||
"frames": [
|
||||
0.0,
|
||||
60.0
|
||||
],
|
||||
"seconds": 2.0,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"frames": [
|
||||
0.0,
|
||||
12.0
|
||||
],
|
||||
"seconds": 0.4,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "stop",
|
||||
"frames": [
|
||||
0.0,
|
||||
12.0
|
||||
],
|
||||
"seconds": 0.4,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "victory",
|
||||
"frames": [
|
||||
0.0,
|
||||
60.0
|
||||
],
|
||||
"seconds": 2.0,
|
||||
"loop": false,
|
||||
"contact_seconds": -1.0
|
||||
},
|
||||
{
|
||||
"name": "walk",
|
||||
"frames": [
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
"seconds": 1.6,
|
||||
"loop": true,
|
||||
"contact_seconds": -1.0
|
||||
}
|
||||
],
|
||||
"expected_from_godot": {
|
||||
"triangles": 5712,
|
||||
"bounds_godot": {
|
||||
"min": [
|
||||
-1.2307,
|
||||
0.0053,
|
||||
-0.5532
|
||||
],
|
||||
"max": [
|
||||
1.3273,
|
||||
3.3182,
|
||||
0.9253
|
||||
]
|
||||
},
|
||||
"bones": 24,
|
||||
"clips": [
|
||||
"ability",
|
||||
"attack_a",
|
||||
"attack_b",
|
||||
"death",
|
||||
"hit",
|
||||
"idle",
|
||||
"roar",
|
||||
"start",
|
||||
"stop",
|
||||
"victory",
|
||||
"walk"
|
||||
],
|
||||
"resource_path": "res://assets/luneraria/g2/schlundkrone.glb"
|
||||
},
|
||||
"meshes_without_uv": [],
|
||||
"triangles": 5712,
|
||||
"fbx": "Assets/Luneraria/Art/Characters/schlundkrone.fbx",
|
||||
"fbx_bytes": 2838956,
|
||||
"ok": true
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 96a195571f91340e5b420cd273a91231
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Characters/schlundkrone.fbx
Normal file
444
Assets/Luneraria/Art/Characters/schlundkrone.fbx.meta
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b2dd57798499c4b7b8698ee56e676c45
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations:
|
||||
- serializedVersion: 16
|
||||
name: ability
|
||||
takeName: SchlundkroneRig|ability
|
||||
internalID: 8816013596772264376
|
||||
firstFrame: 0
|
||||
lastFrame: 39
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: attack_a
|
||||
takeName: SchlundkroneRig|attack_a
|
||||
internalID: -3581854836903996656
|
||||
firstFrame: 0
|
||||
lastFrame: 39
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.6923077
|
||||
functionName: OnLuneContact
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: attack_b
|
||||
takeName: SchlundkroneRig|attack_b
|
||||
internalID: 7137080732755112609
|
||||
firstFrame: 0
|
||||
lastFrame: 39
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events:
|
||||
- time: 0.6923077
|
||||
functionName: OnLuneContact
|
||||
data:
|
||||
objectReferenceParameter: {instanceID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: death
|
||||
takeName: SchlundkroneRig|death
|
||||
internalID: 3223440528613674463
|
||||
firstFrame: 0
|
||||
lastFrame: 66
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: hit
|
||||
takeName: SchlundkroneRig|hit
|
||||
internalID: -1153443838369333364
|
||||
firstFrame: 0
|
||||
lastFrame: 15
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: idle
|
||||
takeName: SchlundkroneRig|idle
|
||||
internalID: 2159908019584541609
|
||||
firstFrame: 0
|
||||
lastFrame: 90
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 1
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: roar
|
||||
takeName: SchlundkroneRig|roar
|
||||
internalID: 1662885906025357955
|
||||
firstFrame: 0
|
||||
lastFrame: 60
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: start
|
||||
takeName: SchlundkroneRig|start
|
||||
internalID: -8546801627699338383
|
||||
firstFrame: 0
|
||||
lastFrame: 12
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: stop
|
||||
takeName: SchlundkroneRig|stop
|
||||
internalID: 8440139490132052637
|
||||
firstFrame: 0
|
||||
lastFrame: 12
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: victory
|
||||
takeName: SchlundkroneRig|victory
|
||||
internalID: 7279649719363434968
|
||||
firstFrame: 0
|
||||
lastFrame: 60
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 0
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: walk
|
||||
takeName: SchlundkroneRig|walk
|
||||
internalID: -395723189595340628
|
||||
firstFrame: 0
|
||||
lastFrame: 48
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 1
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 0
|
||||
loopBlendPositionY: 0
|
||||
loopBlendPositionXZ: 0
|
||||
keepOriginalOrientation: 0
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 0
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask: []
|
||||
maskType: 3
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 1
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 2
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 1
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Art/Environment.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2cf6ff2112f7d4fd5bcff4710800659a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
684
Assets/Luneraria/Art/Environment/map_props.export.json
Normal file
|
|
@ -0,0 +1,684 @@
|
|||
{
|
||||
"id": "map_props",
|
||||
"group": "Environment",
|
||||
"source": "assets-source/luneraria/map_props.blend",
|
||||
"exporter_version": 5,
|
||||
"blender": "5.2.2 LTS",
|
||||
"fbx_settings": {
|
||||
"use_selection": true,
|
||||
"use_visible": false,
|
||||
"use_active_collection": false,
|
||||
"global_scale": 1.0,
|
||||
"apply_unit_scale": true,
|
||||
"apply_scale_options": "FBX_SCALE_UNITS",
|
||||
"axis_forward": "Y",
|
||||
"axis_up": "Z",
|
||||
"bake_space_transform": false,
|
||||
"object_types": [
|
||||
"ARMATURE",
|
||||
"EMPTY",
|
||||
"MESH"
|
||||
],
|
||||
"use_mesh_modifiers": true,
|
||||
"use_mesh_modifiers_render": true,
|
||||
"mesh_smooth_type": "OFF",
|
||||
"use_subsurf": false,
|
||||
"use_mesh_edges": false,
|
||||
"use_tspace": true,
|
||||
"use_triangles": false,
|
||||
"colors_type": "LINEAR",
|
||||
"prioritize_active_color": true,
|
||||
"use_custom_props": false,
|
||||
"add_leaf_bones": false,
|
||||
"primary_bone_axis": "Y",
|
||||
"secondary_bone_axis": "X",
|
||||
"use_armature_deform_only": true,
|
||||
"armature_nodetype": "NULL",
|
||||
"bake_anim": true,
|
||||
"bake_anim_use_all_bones": true,
|
||||
"bake_anim_use_nla_strips": false,
|
||||
"bake_anim_use_all_actions": true,
|
||||
"bake_anim_force_startend_keying": true,
|
||||
"bake_anim_step": 1.0,
|
||||
"bake_anim_simplify_factor": 0.0,
|
||||
"path_mode": "STRIP",
|
||||
"embed_textures": false,
|
||||
"batch_mode": "OFF"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"check": "turn_applied",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "units_metric",
|
||||
"ok": true,
|
||||
"detail": "METRIC"
|
||||
},
|
||||
{
|
||||
"check": "unit_scale_1",
|
||||
"ok": true,
|
||||
"detail": "1.0"
|
||||
},
|
||||
{
|
||||
"check": "no_negative_scale",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "object_scale_1",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names_unique",
|
||||
"ok": true,
|
||||
"detail": "['Banner', 'Bridge', 'Curb', 'EdgeCliff', 'Oak_0', 'Oak_1', 'Oak_2', 'Pine_0', 'Pine_1', 'Pine_2', 'Rock_0', 'Rock_1', 'Rock_2', 'Shrub_0', 'Shrub_1']"
|
||||
},
|
||||
{
|
||||
"check": "material_slots_filled",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangent_prerequisites",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_blend_shapes",
|
||||
"ok": true,
|
||||
"detail": "{}"
|
||||
},
|
||||
{
|
||||
"check": "no_armature",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_triangles",
|
||||
"ok": true,
|
||||
"detail": "7338 / 7338"
|
||||
},
|
||||
{
|
||||
"check": "roundtrip_materials",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"source_sha256": "e2e723fc53da0d4bb686800ddba36ebebe7708e0944c32a81fd6d9c159e30e68",
|
||||
"removed_modifiers": 0,
|
||||
"kind": "static",
|
||||
"fps": 24.0,
|
||||
"objects": 15,
|
||||
"meshes": {
|
||||
"Bridge": {
|
||||
"mesh": "Deck_0",
|
||||
"triangles": 1088,
|
||||
"vertices": 656,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_paving",
|
||||
"ENV_limestone",
|
||||
"ENV_brass"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-5.515,
|
||||
-1.3,
|
||||
-3.9
|
||||
],
|
||||
"max": [
|
||||
5.515,
|
||||
1.46,
|
||||
3.9
|
||||
]
|
||||
}
|
||||
},
|
||||
"Curb": {
|
||||
"mesh": "Curb",
|
||||
"triangles": 12,
|
||||
"vertices": 8,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_limestone"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.65,
|
||||
-0.01,
|
||||
-0.21
|
||||
],
|
||||
"max": [
|
||||
0.65,
|
||||
0.25,
|
||||
0.21
|
||||
]
|
||||
}
|
||||
},
|
||||
"Pine_0": {
|
||||
"mesh": "Trunk",
|
||||
"triangles": 358,
|
||||
"vertices": 191,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_bark",
|
||||
"ENV_leaf_dark",
|
||||
"ENV_leaf_mid"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.411,
|
||||
0.0,
|
||||
-1.3761
|
||||
],
|
||||
"max": [
|
||||
1.2882,
|
||||
4.332,
|
||||
1.3462
|
||||
]
|
||||
}
|
||||
},
|
||||
"Pine_1": {
|
||||
"mesh": "Trunk.001",
|
||||
"triangles": 358,
|
||||
"vertices": 191,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_bark",
|
||||
"ENV_leaf_dark",
|
||||
"ENV_leaf_mid"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.4442,
|
||||
0.0,
|
||||
-1.4865
|
||||
],
|
||||
"max": [
|
||||
1.434,
|
||||
5.244,
|
||||
1.3943
|
||||
]
|
||||
}
|
||||
},
|
||||
"Pine_2": {
|
||||
"mesh": "Trunk.002",
|
||||
"triangles": 358,
|
||||
"vertices": 191,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_bark",
|
||||
"ENV_leaf_dark",
|
||||
"ENV_leaf_mid"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.5452,
|
||||
0.0,
|
||||
-1.5182
|
||||
],
|
||||
"max": [
|
||||
1.4493,
|
||||
3.648,
|
||||
1.5733
|
||||
]
|
||||
}
|
||||
},
|
||||
"Oak_0": {
|
||||
"mesh": "Trunk.003",
|
||||
"triangles": 1270,
|
||||
"vertices": 669,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_bark",
|
||||
"ENV_leaf_mid",
|
||||
"ENV_leaf_light",
|
||||
"ENV_leaf_dark"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.7039,
|
||||
-0.0306,
|
||||
-1.8912
|
||||
],
|
||||
"max": [
|
||||
1.373,
|
||||
4.02,
|
||||
1.5742
|
||||
]
|
||||
}
|
||||
},
|
||||
"Oak_1": {
|
||||
"mesh": "Trunk.004",
|
||||
"triangles": 1270,
|
||||
"vertices": 669,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_bark",
|
||||
"ENV_leaf_mid",
|
||||
"ENV_leaf_light",
|
||||
"ENV_leaf_dark"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.7964,
|
||||
-0.0255,
|
||||
-1.5792
|
||||
],
|
||||
"max": [
|
||||
1.5389,
|
||||
4.6442,
|
||||
1.6028
|
||||
]
|
||||
}
|
||||
},
|
||||
"Oak_2": {
|
||||
"mesh": "Trunk.005",
|
||||
"triangles": 1270,
|
||||
"vertices": 669,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_bark",
|
||||
"ENV_leaf_mid",
|
||||
"ENV_leaf_light",
|
||||
"ENV_leaf_dark"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.7448,
|
||||
-0.0387,
|
||||
-1.4185
|
||||
],
|
||||
"max": [
|
||||
1.6053,
|
||||
3.4947,
|
||||
1.7902
|
||||
]
|
||||
}
|
||||
},
|
||||
"Rock_0": {
|
||||
"mesh": "Rock",
|
||||
"triangles": 140,
|
||||
"vertices": 78,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_cliff",
|
||||
"ENV_leaf_dark",
|
||||
"ENV_limestone"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.7155,
|
||||
-0.04,
|
||||
-1.0953
|
||||
],
|
||||
"max": [
|
||||
1.0683,
|
||||
1.0416,
|
||||
1.0294
|
||||
]
|
||||
}
|
||||
},
|
||||
"Rock_1": {
|
||||
"mesh": "Rock.001",
|
||||
"triangles": 140,
|
||||
"vertices": 78,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_cliff",
|
||||
"ENV_leaf_dark",
|
||||
"ENV_limestone"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-2.4291,
|
||||
-0.055,
|
||||
-1.4554
|
||||
],
|
||||
"max": [
|
||||
1.8589,
|
||||
1.5017,
|
||||
1.32
|
||||
]
|
||||
}
|
||||
},
|
||||
"Rock_2": {
|
||||
"mesh": "Rock.002",
|
||||
"triangles": 140,
|
||||
"vertices": 78,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_cliff",
|
||||
"ENV_leaf_dark",
|
||||
"ENV_limestone"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.2032,
|
||||
-0.025,
|
||||
-0.7362
|
||||
],
|
||||
"max": [
|
||||
0.776,
|
||||
0.6172,
|
||||
0.7375
|
||||
]
|
||||
}
|
||||
},
|
||||
"Shrub_0": {
|
||||
"mesh": "Shrub",
|
||||
"triangles": 80,
|
||||
"vertices": 42,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_leaf_mid"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-0.813,
|
||||
0.135,
|
||||
-0.8861
|
||||
],
|
||||
"max": [
|
||||
0.7211,
|
||||
0.8205,
|
||||
0.7093
|
||||
]
|
||||
}
|
||||
},
|
||||
"Shrub_1": {
|
||||
"mesh": "Shrub.001",
|
||||
"triangles": 80,
|
||||
"vertices": 42,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_leaf_dark"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.0772,
|
||||
0.135,
|
||||
-0.8513
|
||||
],
|
||||
"max": [
|
||||
0.9518,
|
||||
0.9641,
|
||||
0.8895
|
||||
]
|
||||
}
|
||||
},
|
||||
"Banner": {
|
||||
"mesh": "Pole",
|
||||
"triangles": 74,
|
||||
"vertices": 48,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_brass",
|
||||
"PR_Banner"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-1.13,
|
||||
0.0,
|
||||
-0.0866
|
||||
],
|
||||
"max": [
|
||||
0.1,
|
||||
4.5,
|
||||
0.0866
|
||||
]
|
||||
}
|
||||
},
|
||||
"EdgeCliff": {
|
||||
"mesh": "Block_0",
|
||||
"triangles": 700,
|
||||
"vertices": 378,
|
||||
"ngons": 0,
|
||||
"materials": [
|
||||
"ENV_cliff",
|
||||
"ENV_leaf_mid"
|
||||
],
|
||||
"uv_layers": [],
|
||||
"color_attributes": [],
|
||||
"active_color": null,
|
||||
"custom_normals": false,
|
||||
"normals_unit_length": true,
|
||||
"shape_keys": 0,
|
||||
"skinned": false,
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-7.3684,
|
||||
0.4308,
|
||||
-2.0375
|
||||
],
|
||||
"max": [
|
||||
7.4555,
|
||||
4.1121,
|
||||
1.9761
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"armatures": {},
|
||||
"empties": {},
|
||||
"bounds_unity": {
|
||||
"min": [
|
||||
-7.3684,
|
||||
-1.3,
|
||||
-3.9
|
||||
],
|
||||
"max": [
|
||||
7.4555,
|
||||
5.244,
|
||||
3.9
|
||||
]
|
||||
},
|
||||
"clips": [],
|
||||
"expected_from_godot": {},
|
||||
"meshes_without_uv": [
|
||||
"Banner",
|
||||
"Bridge",
|
||||
"Curb",
|
||||
"EdgeCliff",
|
||||
"Oak_0",
|
||||
"Oak_1",
|
||||
"Oak_2",
|
||||
"Pine_0",
|
||||
"Pine_1",
|
||||
"Pine_2",
|
||||
"Rock_0",
|
||||
"Rock_1",
|
||||
"Rock_2",
|
||||
"Shrub_0",
|
||||
"Shrub_1"
|
||||
],
|
||||
"triangles": 7338,
|
||||
"fbx": "Assets/Luneraria/Art/Environment/map_props.fbx",
|
||||
"fbx_bytes": 236284,
|
||||
"ok": true
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 712d173cb82314d19a6d0689762cb0ef
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Environment/map_props.fbx
Normal file
111
Assets/Luneraria/Art/Environment/map_props.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9a6862867d0c9498892d42d256fbe886
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Art/Units.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 01c1714cee0714bbe9b65e1e6009cd0c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
4747
Assets/Luneraria/Art/Units/g01.export.json
Normal file
7
Assets/Luneraria/Art/Units/g01.export.json.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d7a4fb253a9584d0ba79fa033c20eb6b
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Luneraria/Art/Units/g01.fbx
Normal file
111
Assets/Luneraria/Art/Units/g01.fbx.meta
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 416c29115e263420dbef5a876b74571c
|
||||
ModelImporter:
|
||||
serializedVersion: 24300
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 2
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 1
|
||||
searchTexturesGlobally: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 0
|
||||
optimizeGameObjects: 0
|
||||
removeConstantScaleCurves: 0
|
||||
motionNodeName:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 0
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations: []
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importPhysicalCameras: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 0
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
nodeNameCollisionStrategy: 1
|
||||
fileIdsGeneration: 2
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 1
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
optimizeBones: 1
|
||||
generateMeshLods: 0
|
||||
meshLodGenerationFlags: 0
|
||||
maximumMeshLod: -1
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 0
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 1
|
||||
strictVertexDataChecks: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 0
|
||||
normalCalculationMode: 4
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 0
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton: []
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 0
|
||||
skeletonHasParents: 1
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 0
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||
importBlendShapeDeformPercent: 1
|
||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Editor.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4460d353d8e864b71bbfb46336516b2d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Editor/Art.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 793ae230624f046acb4639e9b27fa0be
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
45
Assets/Luneraria/Editor/Art/ExportReport.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Luneraria.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// The facts and checks that tools/blender/lune_fbx_export.py writes next to every FBX
|
||||
/// (<id>.export.json). The importer reads the clip data from it; the verifier compares
|
||||
/// the imported model with the Blender side.
|
||||
/// </summary>
|
||||
public sealed class ExportReport
|
||||
{
|
||||
public readonly string Path;
|
||||
public readonly JObject Data;
|
||||
|
||||
ExportReport(string path, JObject data)
|
||||
{
|
||||
Path = path;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public string Id { get { return (string)Data["id"]; } }
|
||||
public string Kind { get { return (string)Data["kind"]; } }
|
||||
public bool Skinned { get { return Kind == "skinned"; } }
|
||||
public bool BlenderOk { get { return (bool)Data["ok"]; } }
|
||||
public JObject Meshes { get { return (JObject)Data["meshes"]; } }
|
||||
public JArray Clips { get { return (JArray)Data["clips"] ?? new JArray(); } }
|
||||
|
||||
/// <summary>Report of an FBX asset path, or null if the model was not exported by the pipeline.</summary>
|
||||
public static ExportReport ForModel(string modelPath)
|
||||
{
|
||||
string path = System.IO.Path.ChangeExtension(modelPath, ".export.json");
|
||||
if (!File.Exists(path))
|
||||
return null;
|
||||
return new ExportReport(path, JObject.Parse(File.ReadAllText(path)));
|
||||
}
|
||||
|
||||
public static IEnumerable<string> AllModels(string root)
|
||||
{
|
||||
foreach (string path in Directory.GetFiles(root, "*.export.json", SearchOption.AllDirectories))
|
||||
yield return path.Replace('\\', '/').Replace(".export.json", ".fbx");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Luneraria/Editor/Art/ExportReport.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2ea3ae2e05fa54b17a8ef5eed98cad51
|
||||
159
Assets/Luneraria/Editor/Art/LuneAssetPreview.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Luneraria.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders every pipeline asset in a neutral preview scene (URP, one sun, 3/4 front view) to
|
||||
/// docs/port/screenshots/u2a/. Buildings show their intact state; the tower also its ruin;
|
||||
/// rigged figures their bind pose and the hit frame of attack_a.
|
||||
/// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneAssetPreview.RenderAll
|
||||
/// </summary>
|
||||
public static class LuneAssetPreview
|
||||
{
|
||||
const int Width = 1600;
|
||||
const int Height = 1000;
|
||||
|
||||
public static void RenderAll()
|
||||
{
|
||||
int code = 0;
|
||||
try
|
||||
{
|
||||
string folder = Path.Combine(Path.GetDirectoryName(Application.dataPath), "docs/port/screenshots/u2a");
|
||||
Directory.CreateDirectory(folder);
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||||
var sun = new GameObject("Sun").AddComponent<Light>();
|
||||
sun.type = LightType.Directional;
|
||||
sun.intensity = 1.6f;
|
||||
sun.color = new Color(1f, .89f, .74f);
|
||||
sun.shadows = LightShadows.Soft;
|
||||
sun.transform.rotation = Quaternion.Euler(48f, 150f, 0f);
|
||||
RenderSettings.ambientMode = AmbientMode.Trilight;
|
||||
RenderSettings.ambientSkyColor = new Color(.55f, .6f, .68f);
|
||||
RenderSettings.ambientEquatorColor = new Color(.42f, .42f, .44f);
|
||||
RenderSettings.ambientGroundColor = new Color(.2f, .19f, .18f);
|
||||
var ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
||||
ground.transform.localScale = new Vector3(20f, 1f, 20f);
|
||||
var camera = new GameObject("PreviewCamera").AddComponent<Camera>();
|
||||
camera.clearFlags = CameraClearFlags.SolidColor;
|
||||
camera.backgroundColor = new Color(.16f, .18f, .21f);
|
||||
camera.fieldOfView = 30f;
|
||||
foreach (string model in ExportReport.AllModels("Assets/Luneraria/Art").OrderBy(p => p, StringComparer.Ordinal))
|
||||
{
|
||||
ExportReport report = ExportReport.ForModel(model);
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(model);
|
||||
foreach (var shot in Shots(report))
|
||||
{
|
||||
var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
|
||||
shot.Value(instance);
|
||||
Render(camera, instance, Path.Combine(folder, report.Id + shot.Key + ".png"));
|
||||
UnityEngine.Object.DestroyImmediate(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Debug.LogError("LUNE_PREVIEW failed: " + error);
|
||||
code = 1;
|
||||
}
|
||||
EditorApplication.Exit(code);
|
||||
}
|
||||
|
||||
static IEnumerable<KeyValuePair<string, Action<GameObject>>> Shots(ExportReport report)
|
||||
{
|
||||
string group = (string)report.Data["group"];
|
||||
if (group == "Buildings")
|
||||
{
|
||||
yield return Shot("", go => Show(go, n => !n.StartsWith("Upper_Damaged") && !n.StartsWith("Debris") && !n.StartsWith("Ruin")));
|
||||
if (report.Id == "grenzwacht")
|
||||
yield return Shot("-ruin", go => Show(go, n => n.StartsWith("Ruin")));
|
||||
}
|
||||
else if (group == "Environment")
|
||||
{
|
||||
yield return Shot("", Row);
|
||||
}
|
||||
else if (report.Skinned)
|
||||
{
|
||||
yield return Shot("", go => Sample(go, "idle", 0f));
|
||||
yield return Shot("-attack_a", go => Sample(go, "attack_a", .9f));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return Shot("", go => { });
|
||||
}
|
||||
}
|
||||
|
||||
static KeyValuePair<string, Action<GameObject>> Shot(string suffix, Action<GameObject> prepare)
|
||||
{
|
||||
return new KeyValuePair<string, Action<GameObject>>(suffix, prepare);
|
||||
}
|
||||
|
||||
static void Show(GameObject root, Func<string, bool> visible)
|
||||
{
|
||||
foreach (Renderer renderer in root.GetComponentsInChildren<Renderer>(true))
|
||||
renderer.enabled = visible(renderer.gameObject.name);
|
||||
}
|
||||
|
||||
/// <summary>The prop library keeps every prop at the origin; the preview sets them out in a grid.</summary>
|
||||
static void Row(GameObject root)
|
||||
{
|
||||
const int columns = 5;
|
||||
const float cell = 7.5f;
|
||||
int index = 0;
|
||||
foreach (Transform child in root.transform.Cast<Transform>().OrderBy(t => t.name, StringComparer.Ordinal).ToList())
|
||||
{
|
||||
var renderer = child.GetComponent<Renderer>();
|
||||
if (renderer == null)
|
||||
continue;
|
||||
Vector3 center = renderer.bounds.center;
|
||||
var slot = new Vector3((index % columns) * cell, 0f, -(index / columns) * cell);
|
||||
child.position += slot - new Vector3(center.x, 0f, center.z);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sample(GameObject root, string clipName, float seconds)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(PrefabUtility.GetCorrespondingObjectFromSource(root));
|
||||
AnimationClip clip = AssetDatabase.LoadAllAssetsAtPath(path).OfType<AnimationClip>().FirstOrDefault(c => c.name == clipName);
|
||||
if (clip != null)
|
||||
clip.SampleAnimation(root, seconds);
|
||||
}
|
||||
|
||||
static void Render(Camera camera, GameObject root, string file)
|
||||
{
|
||||
var renderers = root.GetComponentsInChildren<Renderer>().Where(r => r.enabled).ToList();
|
||||
Bounds bounds = renderers[0].bounds;
|
||||
foreach (Renderer renderer in renderers)
|
||||
bounds.Encapsulate(renderer.bounds);
|
||||
// 3/4 front view: the models face +Z, the camera stands in front, to the right, above.
|
||||
Vector3 direction = new Vector3(.62f, .42f, 1f).normalized;
|
||||
float radius = bounds.extents.magnitude;
|
||||
float distance = radius / Mathf.Sin(camera.fieldOfView * .5f * Mathf.Deg2Rad) * .92f;
|
||||
camera.aspect = (float)Width / Height;
|
||||
camera.transform.position = bounds.center + direction * distance;
|
||||
camera.transform.LookAt(bounds.center);
|
||||
camera.nearClipPlane = Mathf.Max(.01f, distance - radius * 2f);
|
||||
camera.farClipPlane = distance + radius * 4f;
|
||||
var target = new RenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32) { antiAliasing = 8 };
|
||||
camera.targetTexture = target;
|
||||
camera.Render();
|
||||
RenderTexture.active = target;
|
||||
var image = new Texture2D(Width, Height, TextureFormat.RGB24, false);
|
||||
image.ReadPixels(new Rect(0, 0, Width, Height), 0, 0);
|
||||
image.Apply();
|
||||
File.WriteAllBytes(file, image.EncodeToPNG());
|
||||
RenderTexture.active = null;
|
||||
camera.targetTexture = null;
|
||||
UnityEngine.Object.DestroyImmediate(target);
|
||||
UnityEngine.Object.DestroyImmediate(image);
|
||||
Debug.Log("LUNE_PREVIEW wrote " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Luneraria/Editor/Art/LuneAssetPreview.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50634406ba3e34d398502bba3379f6af
|
||||
262
Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Luneraria.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks every imported FBX of the Blender pipeline against the facts Blender wrote next to it
|
||||
/// (U2A): transforms free of axis rotations, mesh names, triangles, bounds, material slots,
|
||||
/// normals, tangents, UVs, vertex colours, root bone and bone names, clips with loop flags and
|
||||
/// contact events, forward direction. Batch entry:
|
||||
/// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneAssetVerifier.VerifyAll
|
||||
/// Result: docs/port/logs/u2a/unity-verify.json; exit code 0 only if every check passed.
|
||||
/// </summary>
|
||||
public static class LuneAssetVerifier
|
||||
{
|
||||
const string Root = "Assets/Luneraria/Art";
|
||||
const float BoundsTolerance = 0.002f;
|
||||
|
||||
/// <summary>Re-imports every pipeline model (after import rules or the render pipeline changed).</summary>
|
||||
public static void ReimportArt()
|
||||
{
|
||||
AssetDatabase.ImportAsset(Root, ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceUpdate | ImportAssetOptions.ForceSynchronousImport);
|
||||
Debug.Log("LUNE_VERIFY reimported " + Root);
|
||||
EditorApplication.Exit(0);
|
||||
}
|
||||
|
||||
public static void VerifyAll()
|
||||
{
|
||||
int code = 1;
|
||||
try
|
||||
{
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
||||
var results = new JArray();
|
||||
bool all = true;
|
||||
foreach (string model in ExportReport.AllModels(Root).OrderBy(p => p, StringComparer.Ordinal))
|
||||
{
|
||||
JObject result = Verify(model);
|
||||
results.Add(result);
|
||||
all &= (bool)result["ok"];
|
||||
var failed = ((JArray)result["checks"]).Where(c => !(bool)c["ok"]).ToList();
|
||||
Debug.Log(string.Format("LUNE_VERIFY {0} {1}: {2} checks, {3} failed{4}", failed.Count == 0 ? "OK" : "FAIL", result["id"],
|
||||
((JArray)result["checks"]).Count, failed.Count, string.Concat(failed.Select(c => "\n FAIL " + c["check"] + ": " + c["detail"]))));
|
||||
}
|
||||
string logs = Path.Combine(Path.GetDirectoryName(Application.dataPath), "docs/port/logs/u2a");
|
||||
Directory.CreateDirectory(logs);
|
||||
var summary = new JObject { ["unity"] = Application.unityVersion, ["ok"] = all, ["assets"] = results };
|
||||
File.WriteAllText(Path.Combine(logs, "unity-verify.json"), summary.ToString() + "\n");
|
||||
code = all ? 0 : 2;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Debug.LogError("LUNE_VERIFY crashed: " + error);
|
||||
}
|
||||
EditorApplication.Exit(code);
|
||||
}
|
||||
|
||||
sealed class Checks
|
||||
{
|
||||
public readonly JArray List = new JArray();
|
||||
|
||||
public void Add(string name, bool ok, object detail = null)
|
||||
{
|
||||
List.Add(new JObject { ["check"] = name, ["ok"] = ok, ["detail"] = detail == null ? "" : JToken.FromObject(detail).ToString(Newtonsoft.Json.Formatting.None) });
|
||||
}
|
||||
|
||||
public bool Ok { get { return List.All(c => (bool)c["ok"]); } }
|
||||
}
|
||||
|
||||
public static JObject Verify(string modelPath)
|
||||
{
|
||||
ExportReport report = ExportReport.ForModel(modelPath);
|
||||
var checks = new Checks();
|
||||
var facts = new JObject();
|
||||
var root = AssetDatabase.LoadAssetAtPath<GameObject>(modelPath);
|
||||
checks.Add("blender_checks_passed", report.BlenderOk);
|
||||
checks.Add("imported", root != null, modelPath);
|
||||
if (root == null)
|
||||
return Result(report, checks, facts);
|
||||
var importer = (ModelImporter)AssetImporter.GetAtPath(modelPath);
|
||||
checks.Add("import_rules_applied", importer.globalScale == 1f && importer.useFileScale && importer.bakeAxisConversion
|
||||
&& importer.importNormals == ModelImporterNormals.Import && importer.importTangents == ModelImporterTangents.Import);
|
||||
checks.Add("root_transform_identity", IsIdentity(root.transform), Describe(root.transform));
|
||||
var bones = new HashSet<Transform>();
|
||||
foreach (var skinned in root.GetComponentsInChildren<SkinnedMeshRenderer>(true))
|
||||
foreach (Transform bone in skinned.bones)
|
||||
bones.Add(bone);
|
||||
// Blender objects carry no rotation or scale; after the axis bake every node that is not
|
||||
// a bone must be clean, otherwise the conversion ended up in the hierarchy.
|
||||
var rotated = root.GetComponentsInChildren<Transform>(true).Where(t => t != root.transform && !bones.Contains(t) && !IsClean(t)).Select(Describe).ToList();
|
||||
checks.Add("node_transforms_axis_clean", rotated.Count == 0, rotated.Take(8).ToList());
|
||||
|
||||
var renderers = root.GetComponentsInChildren<Renderer>(true).Where(r => r is MeshRenderer || r is SkinnedMeshRenderer).ToList();
|
||||
var names = renderers.Select(r => r.gameObject.name).OrderBy(n => n, StringComparer.Ordinal).ToList();
|
||||
var expectedNames = report.Meshes.Properties().Select(p => p.Name).OrderBy(n => n, StringComparer.Ordinal).ToList();
|
||||
checks.Add("mesh_names", names.SequenceEqual(expectedNames), names.Except(expectedNames).Concat(expectedNames.Except(names)).Take(12).ToList());
|
||||
|
||||
int triangles = 0;
|
||||
var wrongTriangles = new List<string>();
|
||||
var wrongMaterials = new List<string>();
|
||||
var badNormals = new List<string>();
|
||||
var badTangents = new List<string>();
|
||||
var missingUv = new List<string>();
|
||||
var missingColors = new List<string>();
|
||||
var low = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
|
||||
var high = new Vector3(float.MinValue, float.MinValue, float.MinValue);
|
||||
int withoutTangents = 0;
|
||||
foreach (Renderer renderer in renderers)
|
||||
{
|
||||
Mesh mesh = renderer is SkinnedMeshRenderer skinned ? skinned.sharedMesh : renderer.GetComponent<MeshFilter>().sharedMesh;
|
||||
string name = renderer.gameObject.name;
|
||||
var blender = (JObject)report.Meshes[name];
|
||||
int count = mesh.triangles.Length / 3;
|
||||
triangles += count;
|
||||
if (blender != null && (int)blender["triangles"] != count)
|
||||
wrongTriangles.Add(name + " " + count + "/" + blender["triangles"]);
|
||||
if (blender != null)
|
||||
{
|
||||
var want = ((JArray)blender["materials"]).Select(m => (string)m).OrderBy(m => m, StringComparer.Ordinal).ToList();
|
||||
var got = renderer.sharedMaterials.Select(m => m != null ? m.name : "<none>").OrderBy(m => m, StringComparer.Ordinal).ToList();
|
||||
if (!want.SequenceEqual(got))
|
||||
wrongMaterials.Add(name + ": " + string.Join(",", got) + " / " + string.Join(",", want));
|
||||
bool hasUv = ((JArray)blender["uv_layers"]).Count > 0;
|
||||
if (hasUv && mesh.uv.Length != mesh.vertexCount)
|
||||
missingUv.Add(name);
|
||||
if (((JArray)blender["color_attributes"]).Count > 0 && mesh.colors.Length != mesh.vertexCount)
|
||||
missingColors.Add(name);
|
||||
Vector4[] tangents = mesh.tangents;
|
||||
if (hasUv)
|
||||
{
|
||||
if (tangents.Length != mesh.vertexCount || tangents.Any(t => Mathf.Abs(Mathf.Abs(t.w) - 1f) > 1e-3f))
|
||||
badTangents.Add(name);
|
||||
}
|
||||
else if (tangents.Length == 0)
|
||||
{
|
||||
withoutTangents++;
|
||||
}
|
||||
}
|
||||
Vector3[] normals = mesh.normals;
|
||||
if (normals.Length != mesh.vertexCount || normals.Any(n => Mathf.Abs(n.magnitude - 1f) > 1e-3f))
|
||||
badNormals.Add(name);
|
||||
Matrix4x4 toRoot = root.transform.worldToLocalMatrix * renderer.transform.localToWorldMatrix;
|
||||
foreach (Vector3 vertex in mesh.vertices)
|
||||
{
|
||||
Vector3 p = toRoot.MultiplyPoint3x4(vertex);
|
||||
low = Vector3.Min(low, p);
|
||||
high = Vector3.Max(high, p);
|
||||
}
|
||||
}
|
||||
facts["triangles"] = triangles;
|
||||
facts["renderers"] = renderers.Count;
|
||||
facts["meshes_without_uv_and_tangents"] = withoutTangents;
|
||||
checks.Add("triangles", triangles == (int)report.Data["triangles"] && wrongTriangles.Count == 0, triangles + " unity / " + report.Data["triangles"] + " blender " + string.Join("; ", wrongTriangles.Take(5)));
|
||||
checks.Add("material_slots", wrongMaterials.Count == 0, wrongMaterials.Take(5).ToList());
|
||||
checks.Add("normals_unit_length", badNormals.Count == 0, badNormals.Take(8).ToList());
|
||||
checks.Add("tangents_where_uv", badTangents.Count == 0, badTangents.Take(8).ToList());
|
||||
checks.Add("uvs_where_blender_has_uv", missingUv.Count == 0, missingUv.Take(8).ToList());
|
||||
checks.Add("vertex_colors", missingColors.Count == 0, missingColors.Take(8).ToList());
|
||||
|
||||
var bounds = (JObject)report.Data["bounds_unity"];
|
||||
if (bounds != null)
|
||||
{
|
||||
var wantLow = ToVector((JArray)bounds["min"]);
|
||||
var wantHigh = ToVector((JArray)bounds["max"]);
|
||||
float worst = Mathf.Max(MaxAbs(low - wantLow), MaxAbs(high - wantHigh));
|
||||
facts["bounds_min"] = new JArray(low.x, low.y, low.z);
|
||||
facts["bounds_max"] = new JArray(high.x, high.y, high.z);
|
||||
checks.Add("bounds_axes_scale", worst < BoundsTolerance, string.Format("largest difference {0:0.00000} m; unity {1} {2}", worst, low.ToString("F3"), high.ToString("F3")));
|
||||
}
|
||||
|
||||
JObject empties = (JObject)report.Data["empties"];
|
||||
JProperty forward = empties?.Properties().FirstOrDefault(p => p.Name.StartsWith("Forward"));
|
||||
if (forward != null)
|
||||
{
|
||||
Transform marker = root.GetComponentsInChildren<Transform>(true).FirstOrDefault(t => t.name.StartsWith("Forward"));
|
||||
Vector3 at = marker != null ? root.transform.InverseTransformPoint(marker.position) : Vector3.zero;
|
||||
checks.Add("forward_is_plus_z", marker != null && at.z > 0.1f && Mathf.Abs(at.x) < 1e-3f, at.ToString("F3"));
|
||||
}
|
||||
|
||||
if (report.Skinned)
|
||||
VerifyRig(modelPath, report, root, checks, facts);
|
||||
return Result(report, checks, facts);
|
||||
}
|
||||
|
||||
static void VerifyRig(string modelPath, ExportReport report, GameObject root, Checks checks, JObject facts)
|
||||
{
|
||||
var skinned = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
||||
checks.Add("skinned_mesh", skinned.Length >= 1, skinned.Length);
|
||||
var armature = (JObject)((JObject)report.Data["armatures"]).Properties().First().Value;
|
||||
var wantBones = ((JArray)armature["bones"]).Select(b => (string)b).OrderBy(b => b, StringComparer.Ordinal).ToList();
|
||||
string wantRoot = (string)((JArray)armature["roots"])[0];
|
||||
foreach (SkinnedMeshRenderer renderer in skinned)
|
||||
{
|
||||
var got = renderer.bones.Select(b => b.name).Distinct().OrderBy(b => b, StringComparer.Ordinal).ToList();
|
||||
checks.Add("bone_names " + renderer.name, got.SequenceEqual(wantBones), got.Except(wantBones).Concat(wantBones.Except(got)).ToList());
|
||||
checks.Add("root_bone " + renderer.name, renderer.rootBone != null && renderer.rootBone.name == wantRoot, renderer.rootBone != null ? renderer.rootBone.name : "none");
|
||||
}
|
||||
UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(modelPath);
|
||||
var avatar = assets.OfType<Avatar>().FirstOrDefault();
|
||||
checks.Add("generic_avatar", avatar != null && avatar.isValid && !avatar.isHuman, avatar != null ? avatar.name : "none");
|
||||
var clips = assets.OfType<AnimationClip>().Where(c => !c.name.StartsWith("__preview__")).ToDictionary(c => c.name, c => c);
|
||||
var wrong = new List<string>();
|
||||
foreach (JToken clip in report.Clips)
|
||||
{
|
||||
string name = (string)clip["name"];
|
||||
if (!clips.TryGetValue(name, out AnimationClip unity))
|
||||
{
|
||||
wrong.Add(name + " missing");
|
||||
continue;
|
||||
}
|
||||
float seconds = (float)clip["seconds"];
|
||||
float frame = 1f / (float)report.Data["fps"];
|
||||
if (Mathf.Abs(unity.length - seconds) > frame * 0.5f)
|
||||
wrong.Add(string.Format("{0} length {1:0.000}/{2:0.000}", name, unity.length, seconds));
|
||||
if (unity.isLooping != (bool)clip["loop"])
|
||||
wrong.Add(name + " loop " + unity.isLooping);
|
||||
double contact = (double)clip["contact_seconds"];
|
||||
AnimationEvent[] events = AnimationUtility.GetAnimationEvents(unity);
|
||||
bool hasContact = events.Any(e => e.functionName == LuneModelPostprocessor.ContactEvent && Mathf.Abs(e.time - (float)contact) < frame);
|
||||
if (contact > 0 && !hasContact)
|
||||
wrong.Add(name + " contact event");
|
||||
}
|
||||
var extra = clips.Keys.Except(report.Clips.Select(c => (string)c["name"])).ToList();
|
||||
checks.Add("clips", wrong.Count == 0 && extra.Count == 0, wrong.Concat(extra.Select(e => e + " unexpected")).ToList());
|
||||
facts["clips"] = new JArray(clips.Values.OrderBy(c => c.name).Select(c => new JObject { ["name"] = c.name, ["length"] = c.length, ["loop"] = c.isLooping, ["events"] = AnimationUtility.GetAnimationEvents(c).Length }));
|
||||
}
|
||||
|
||||
static JObject Result(ExportReport report, Checks checks, JObject facts)
|
||||
{
|
||||
return new JObject { ["id"] = report.Id, ["kind"] = report.Kind, ["ok"] = checks.Ok, ["checks"] = checks.List, ["facts"] = facts };
|
||||
}
|
||||
|
||||
static bool IsIdentity(Transform t)
|
||||
{
|
||||
return t.localPosition.sqrMagnitude < 1e-10f && IsClean(t);
|
||||
}
|
||||
|
||||
static bool IsClean(Transform t)
|
||||
{
|
||||
return Quaternion.Angle(t.localRotation, Quaternion.identity) < 0.01f && (t.localScale - Vector3.one).sqrMagnitude < 1e-8f;
|
||||
}
|
||||
|
||||
static string Describe(Transform t)
|
||||
{
|
||||
return string.Format("{0} pos {1} rot {2} scale {3}", t.name, t.localPosition.ToString("F4"), t.localEulerAngles.ToString("F2"), t.localScale.ToString("F4"));
|
||||
}
|
||||
|
||||
static Vector3 ToVector(JArray values)
|
||||
{
|
||||
return new Vector3((float)values[0], (float)values[1], (float)values[2]);
|
||||
}
|
||||
|
||||
static float MaxAbs(Vector3 v)
|
||||
{
|
||||
return Mathf.Max(Mathf.Abs(v.x), Mathf.Max(Mathf.Abs(v.y), Mathf.Abs(v.z)));
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 588d50b5a3531448691e7370abd8dc6e
|
||||
78
Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Luneraria.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Import rules for every FBX of the Blender pipeline under Assets/Luneraria/Art (U2A).
|
||||
/// Metres stay metres, Blender's Z-up axes are converted by baking (no root rotation),
|
||||
/// normals and tangents come from the file, rigs are generic with the Blender bone names,
|
||||
/// and clips get their Blender action names, loop flags and contact events.
|
||||
/// </summary>
|
||||
public sealed class LuneModelPostprocessor : AssetPostprocessor
|
||||
{
|
||||
public const string ArtRoot = "Assets/Luneraria/Art/";
|
||||
/// <summary>Raised on the figure at the hit frame of attack and ability clips.</summary>
|
||||
public const string ContactEvent = "OnLuneContact";
|
||||
|
||||
public override uint GetVersion() { return 3; }
|
||||
|
||||
void OnPreprocessModel()
|
||||
{
|
||||
if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx"))
|
||||
return;
|
||||
ExportReport report = ExportReport.ForModel(assetPath);
|
||||
var importer = (ModelImporter)assetImporter;
|
||||
importer.globalScale = 1f;
|
||||
importer.useFileScale = true;
|
||||
importer.bakeAxisConversion = true;
|
||||
importer.importCameras = false;
|
||||
importer.importLights = false;
|
||||
importer.importVisibility = false;
|
||||
importer.importBlendShapes = false;
|
||||
importer.importNormals = ModelImporterNormals.Import;
|
||||
importer.importTangents = ModelImporterTangents.Import;
|
||||
importer.meshCompression = ModelImporterMeshCompression.Off;
|
||||
importer.isReadable = true;
|
||||
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
|
||||
importer.materialLocation = ModelImporterMaterialLocation.InPrefab;
|
||||
bool skinned = report != null && report.Skinned;
|
||||
importer.animationType = skinned ? ModelImporterAnimationType.Generic : ModelImporterAnimationType.None;
|
||||
importer.avatarSetup = skinned ? ModelImporterAvatarSetup.CreateFromThisModel : ModelImporterAvatarSetup.NoAvatar;
|
||||
importer.importAnimation = skinned;
|
||||
importer.optimizeGameObjects = false;
|
||||
importer.animationCompression = ModelImporterAnimationCompression.Off;
|
||||
importer.resampleCurves = false;
|
||||
}
|
||||
|
||||
void OnPreprocessAnimation()
|
||||
{
|
||||
if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx"))
|
||||
return;
|
||||
ExportReport report = ExportReport.ForModel(assetPath);
|
||||
if (report == null || !report.Skinned)
|
||||
return;
|
||||
var importer = (ModelImporter)assetImporter;
|
||||
var blender = report.Clips.ToDictionary(c => (string)c["name"], c => c);
|
||||
var clips = new List<ModelImporterClipAnimation>();
|
||||
foreach (ModelImporterClipAnimation clip in importer.defaultClipAnimations)
|
||||
{
|
||||
// Blender names takes "<armature>|<action>"; Unity keeps the action name.
|
||||
string name = clip.takeName.Contains("|") ? clip.takeName.Substring(clip.takeName.LastIndexOf('|') + 1) : clip.takeName;
|
||||
clip.name = name;
|
||||
if (blender.TryGetValue(name, out var facts))
|
||||
{
|
||||
clip.loopTime = (bool)facts["loop"];
|
||||
double contact = (double)facts["contact_seconds"];
|
||||
double seconds = (double)facts["seconds"];
|
||||
if (contact > 0.0 && seconds > 0.0)
|
||||
clip.events = new[] { new AnimationEvent { functionName = ContactEvent, time = (float)(contact / seconds) } };
|
||||
}
|
||||
clips.Add(clip);
|
||||
}
|
||||
importer.clipAnimations = clips.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3eb06f326c30446a4a9e3e2be3aee948
|
||||
22
Assets/Luneraria/Editor/Luneraria.Editor.asmdef
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "Luneraria.Editor",
|
||||
"rootNamespace": "Luneraria.EditorTools",
|
||||
"references": [
|
||||
"Luneraria.Core",
|
||||
"Unity.RenderPipelines.Core.Runtime",
|
||||
"Unity.RenderPipelines.Universal.Runtime"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"Newtonsoft.Json.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/Luneraria/Editor/Luneraria.Editor.asmdef.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f6cff9d287b764627a17a7e3c7b99a6b
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Editor/Setup.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 695e40eeb3cef4a898659650d64902e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
80
Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Luneraria.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Rendering setup of the project (URP asset and renderer, linear colour space), idempotent.
|
||||
/// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneProjectSetup.ConfigureRendering
|
||||
/// </summary>
|
||||
public static class LuneProjectSetup
|
||||
{
|
||||
public const string SettingsFolder = "Assets/Luneraria/Settings/Rendering";
|
||||
public const string PipelinePath = SettingsFolder + "/Luneraria_URP.asset";
|
||||
public const string RendererPath = SettingsFolder + "/Luneraria_URP_Renderer.asset";
|
||||
|
||||
public static void ConfigureRendering()
|
||||
{
|
||||
int code = 0;
|
||||
try
|
||||
{
|
||||
Configure();
|
||||
}
|
||||
catch (System.Exception error)
|
||||
{
|
||||
Debug.LogError("LUNE_SETUP failed: " + error);
|
||||
code = 1;
|
||||
}
|
||||
EditorApplication.Exit(code);
|
||||
}
|
||||
|
||||
public static UniversalRenderPipelineAsset Configure()
|
||||
{
|
||||
Directory.CreateDirectory(SettingsFolder);
|
||||
AssetDatabase.Refresh();
|
||||
var asset = AssetDatabase.LoadAssetAtPath<UniversalRenderPipelineAsset>(PipelinePath);
|
||||
if (asset == null)
|
||||
{
|
||||
var renderer = ScriptableObject.CreateInstance<UniversalRendererData>();
|
||||
AssetDatabase.CreateAsset(renderer, RendererPath);
|
||||
ResourceReloader.ReloadAllNullIn(renderer, UniversalRenderPipelineAsset.packagePath);
|
||||
asset = UniversalRenderPipelineAsset.Create(renderer);
|
||||
AssetDatabase.CreateAsset(asset, PipelinePath);
|
||||
}
|
||||
// The Godot sun reaches 190 m with four splits (scripts/luneraria/view/lune_world.gd).
|
||||
asset.shadowDistance = 190f;
|
||||
asset.shadowCascadeCount = 4;
|
||||
asset.supportsHDR = true;
|
||||
asset.msaaSampleCount = 4;
|
||||
asset.useSRPBatcher = true;
|
||||
EditorUtility.SetDirty(asset);
|
||||
GraphicsSettings.defaultRenderPipeline = asset;
|
||||
int current = QualitySettings.GetQualityLevel();
|
||||
for (int level = 0; level < QualitySettings.names.Length; level++)
|
||||
{
|
||||
QualitySettings.SetQualityLevel(level, false);
|
||||
QualitySettings.renderPipeline = asset;
|
||||
}
|
||||
QualitySettings.SetQualityLevel(current, false);
|
||||
PlayerSettings.colorSpace = ColorSpace.Linear;
|
||||
MoveInto("Assets/UniversalRenderPipelineGlobalSettings.asset", SettingsFolder + "/UniversalRenderPipelineGlobalSettings.asset");
|
||||
MoveInto("Assets/DefaultVolumeProfile.asset", SettingsFolder + "/DefaultVolumeProfile.asset");
|
||||
AssetDatabase.SaveAssets();
|
||||
Debug.Log("LUNE_SETUP rendering: " + PipelinePath + ", colour space " + PlayerSettings.colorSpace);
|
||||
return asset;
|
||||
}
|
||||
|
||||
static void MoveInto(string from, string to)
|
||||
{
|
||||
if (File.Exists(from) && !File.Exists(to))
|
||||
{
|
||||
string error = AssetDatabase.MoveAsset(from, to);
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
Debug.LogWarning("LUNE_SETUP move " + from + ": " + error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e7bff4280437a4ab7bbe7bcaef5cf486
|
||||
8
Assets/Luneraria/Settings.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9ca8da48623284af8ad6bdfdb0af7a1a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Luneraria/Settings/Rendering.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7d08bc5b72ee04727bf259d3ad7f45e0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
143
Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
|
||||
m_Name: Luneraria_URP
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset
|
||||
k_AssetVersion: 13
|
||||
k_AssetPreviousVersion: 13
|
||||
m_RendererType: 1
|
||||
m_RendererData: {fileID: 0}
|
||||
m_RendererDataList:
|
||||
- {fileID: 11400000, guid: 4f1d1577e34314798a12f2f2556faaec, type: 2}
|
||||
m_DefaultRendererIndex: 0
|
||||
m_RequireDepthTexture: 0
|
||||
m_RequireOpaqueTexture: 0
|
||||
m_OpaqueDownsampling: 1
|
||||
m_SupportsTerrainHoles: 1
|
||||
m_SupportsHDR: 1
|
||||
m_HDRColorBufferPrecision: 0
|
||||
m_MSAA: 4
|
||||
m_RenderScale: 1
|
||||
m_UpscalingFilter: 0
|
||||
m_FsrOverrideSharpness: 0
|
||||
m_FsrSharpness: 0.92
|
||||
m_EnableLODCrossFade: 1
|
||||
m_LODCrossFadeDitheringType: 1
|
||||
m_ShEvalMode: 0
|
||||
m_LightProbeSystem: 0
|
||||
m_ProbeVolumeMemoryBudget: 1024
|
||||
m_ProbeVolumeBlendingMemoryBudget: 256
|
||||
m_SupportProbeVolumeGPUStreaming: 0
|
||||
m_SupportProbeVolumeDiskStreaming: 0
|
||||
m_SupportProbeVolumeScenarios: 0
|
||||
m_SupportProbeVolumeScenarioBlending: 0
|
||||
m_ProbeVolumeSHBands: 1
|
||||
m_MainLightRenderingMode: 1
|
||||
m_MainLightShadowsSupported: 1
|
||||
m_MainLightShadowmapResolution: 2048
|
||||
m_AdditionalLightsRenderingMode: 1
|
||||
m_AdditionalLightsPerObjectLimit: 4
|
||||
m_AdditionalLightShadowsSupported: 0
|
||||
m_AdditionalLightsShadowmapResolution: 2048
|
||||
m_AdditionalLightsShadowResolutionTierLow: 256
|
||||
m_AdditionalLightsShadowResolutionTierMedium: 512
|
||||
m_AdditionalLightsShadowResolutionTierHigh: 1024
|
||||
m_ReflectionProbeBlending: 0
|
||||
m_ReflectionProbeBoxProjection: 0
|
||||
m_ReflectionProbeAtlas: 1
|
||||
m_ShadowDistance: 190
|
||||
m_ShadowCascadeCount: 4
|
||||
m_Cascade2Split: 0.25
|
||||
m_Cascade3Split: {x: 0.1, y: 0.3}
|
||||
m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467}
|
||||
m_CascadeBorder: 0.2
|
||||
m_ShadowDepthBias: 1
|
||||
m_ShadowNormalBias: 1
|
||||
m_AnyShadowsSupported: 1
|
||||
m_SoftShadowsSupported: 0
|
||||
m_ConservativeEnclosingSphere: 1
|
||||
m_NumIterationsEnclosingSphere: 64
|
||||
m_SoftShadowQuality: 2
|
||||
m_AdditionalLightsCookieResolution: 2048
|
||||
m_AdditionalLightsCookieFormat: 3
|
||||
m_UseSRPBatcher: 1
|
||||
m_SupportsDynamicBatching: 0
|
||||
m_MixedLightingSupported: 1
|
||||
m_SupportsLightCookies: 1
|
||||
m_SupportsLightLayers: 0
|
||||
m_DebugLevel: 0
|
||||
m_StoreActionsOptimization: 0
|
||||
m_UseAdaptivePerformance: 1
|
||||
m_ColorGradingMode: 0
|
||||
m_ColorGradingLutSize: 32
|
||||
m_AllowPostProcessAlphaOutput: 0
|
||||
m_UseFastSRGBLinearConversion: 0
|
||||
m_SupportDataDrivenLensFlare: 1
|
||||
m_SupportScreenSpaceLensFlare: 1
|
||||
m_GPUResidentDrawerMode: 0
|
||||
m_SmallMeshScreenPercentage: 0
|
||||
m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0
|
||||
m_ShadowType: 1
|
||||
m_LocalShadowsSupported: 0
|
||||
m_LocalShadowsAtlasResolution: 256
|
||||
m_MaxPixelLights: 0
|
||||
m_ShadowAtlasResolution: 256
|
||||
m_VolumeFrameworkUpdateMode: 0
|
||||
m_VolumeProfile: {fileID: 0}
|
||||
apvScenesData:
|
||||
obsoleteSceneBounds:
|
||||
m_Keys: []
|
||||
m_Values: []
|
||||
obsoleteHasProbeVolumes:
|
||||
m_Keys: []
|
||||
m_Values:
|
||||
m_PrefilteringModeMainLightShadows: 1
|
||||
m_PrefilteringModeAdditionalLight: 4
|
||||
m_PrefilteringModeAdditionalLightShadows: 1
|
||||
m_PrefilterXRKeywords: 0
|
||||
m_PrefilteringModeForwardPlus: 1
|
||||
m_PrefilteringModeDeferredRendering: 1
|
||||
m_PrefilteringModeScreenSpaceOcclusion: 1
|
||||
m_PrefilterDebugKeywords: 0
|
||||
m_PrefilterWriteRenderingLayers: 0
|
||||
m_PrefilterHDROutput: 0
|
||||
m_PrefilterAlphaOutput: 0
|
||||
m_PrefilterSSAODepthNormals: 0
|
||||
m_PrefilterSSAOSourceDepthLow: 0
|
||||
m_PrefilterSSAOSourceDepthMedium: 0
|
||||
m_PrefilterSSAOSourceDepthHigh: 0
|
||||
m_PrefilterSSAOInterleaved: 0
|
||||
m_PrefilterSSAOBlueNoise: 0
|
||||
m_PrefilterSSAOSampleCountLow: 0
|
||||
m_PrefilterSSAOSampleCountMedium: 0
|
||||
m_PrefilterSSAOSampleCountHigh: 0
|
||||
m_PrefilterDBufferMRT1: 0
|
||||
m_PrefilterDBufferMRT2: 0
|
||||
m_PrefilterDBufferMRT3: 0
|
||||
m_PrefilterSoftShadowsQualityLow: 0
|
||||
m_PrefilterSoftShadowsQualityMedium: 0
|
||||
m_PrefilterSoftShadowsQualityHigh: 0
|
||||
m_PrefilterSoftShadows: 0
|
||||
m_PrefilterScreenCoord: 0
|
||||
m_PrefilterScreenSpaceIrradiance: 0
|
||||
m_PrefilterNativeRenderPass: 0
|
||||
m_PrefilterUseLegacyLightmaps: 0
|
||||
m_PrefilterBicubicLightmapSampling: 0
|
||||
m_PrefilterReflectionProbeRotation: 0
|
||||
m_PrefilterReflectionProbeBlending: 0
|
||||
m_PrefilterReflectionProbeBoxProjection: 0
|
||||
m_PrefilterReflectionProbeAtlas: 0
|
||||
m_ShaderVariantLogLevel: 0
|
||||
m_ShadowCascades: 0
|
||||
m_Textures:
|
||||
blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}
|
||||
bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 88b2e99a809584b278f95d7e2a3dc890
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3}
|
||||
m_Name: Luneraria_URP_Renderer
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRendererData
|
||||
debugShaders:
|
||||
debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3}
|
||||
hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3}
|
||||
probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3}
|
||||
probeVolumeResources:
|
||||
probeVolumeDebugShader: {fileID: 0}
|
||||
probeVolumeFragmentationDebugShader: {fileID: 0}
|
||||
probeVolumeOffsetDebugShader: {fileID: 0}
|
||||
probeVolumeSamplingDebugShader: {fileID: 0}
|
||||
probeSamplingDebugMesh: {fileID: 0}
|
||||
probeSamplingDebugTexture: {fileID: 0}
|
||||
probeVolumeBlendStatesCS: {fileID: 0}
|
||||
m_RendererFeatures: []
|
||||
m_RendererFeatureMap:
|
||||
m_UseNativeRenderPass: 0
|
||||
postProcessData: {fileID: 0}
|
||||
m_AssetVersion: 3
|
||||
m_PrepassLayerMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_OpaqueLayerMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_TransparentLayerMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_DefaultStencilState:
|
||||
overrideStencilState: 0
|
||||
stencilReference: 0
|
||||
stencilCompareFunction: 8
|
||||
passOperation: 2
|
||||
failOperation: 0
|
||||
zFailOperation: 0
|
||||
m_ShadowTransparentReceive: 1
|
||||
m_RenderingMode: 0
|
||||
m_DepthPrimingMode: 0
|
||||
m_CopyDepthMode: 1
|
||||
m_DepthAttachmentFormat: 0
|
||||
m_DepthTextureFormat: 0
|
||||
m_AccurateGbufferNormals: 0
|
||||
m_IntermediateTextureMode: 1
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4f1d1577e34314798a12f2f2556faaec
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -37,7 +37,7 @@ GraphicsSettings:
|
|||
m_PreloadedShaders: []
|
||||
m_PreloadShadersBatchTimeLimit: -1
|
||||
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_CustomRenderPipeline: {fileID: 0}
|
||||
m_CustomRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
m_TransparencySortMode: 0
|
||||
m_TransparencySortAxis: {x: 0, y: 0, z: 1}
|
||||
m_DefaultRenderingPath: 1
|
||||
|
|
@ -61,8 +61,8 @@ GraphicsSettings:
|
|||
UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 6f0ce73cdc8074fc283478fba3d0ede7, type: 2}
|
||||
m_ShaderBuildSettings:
|
||||
keywordDeclarationOverrides: []
|
||||
m_LightsUseLinearIntensity: 0
|
||||
m_LightsUseColorTemperature: 0
|
||||
m_LightsUseLinearIntensity: 1
|
||||
m_LightsUseColorTemperature: 1
|
||||
m_LogWhenShaderIsCompiled: 0
|
||||
m_LightProbeOutsideHullStrategy: 1
|
||||
m_CameraRelativeLightCulling: 0
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ PlayerSettings:
|
|||
defaultScreenWidthWeb: 960
|
||||
defaultScreenHeightWeb: 600
|
||||
m_StereoRenderingPath: 0
|
||||
m_ActiveColorSpace: 0
|
||||
m_ActiveColorSpace: 1
|
||||
unsupportedMSAAFallback: 0
|
||||
m_SpriteBatchMaxVertexCount: 65535
|
||||
m_SpriteBatchVertexThreshold: 300
|
||||
|
|
@ -160,14 +160,18 @@ PlayerSettings:
|
|||
useHDRDisplay: 0
|
||||
hdrBitDepth: 0
|
||||
m_ColorGamuts: 00000000
|
||||
targetPixelDensity: 0
|
||||
targetPixelDensity: 30
|
||||
resolutionScalingMode: 0
|
||||
resetResolutionOnWindowResize: 0
|
||||
androidSupportedAspectRatio: 1
|
||||
androidMaxAspectRatio: 2.4
|
||||
androidMinAspectRatio: 1
|
||||
applicationIdentifier: {}
|
||||
buildNumber: {}
|
||||
buildNumber:
|
||||
Standalone: 0
|
||||
VisionOS: 0
|
||||
iPhone: 0
|
||||
tvOS: 0
|
||||
overrideDefaultApplicationIdentifier: 0
|
||||
AndroidBundleVersionCode: 1
|
||||
AndroidMinSdkVersion: 25
|
||||
|
|
@ -188,13 +192,13 @@ PlayerSettings:
|
|||
VertexChannelCompressionMask: 4054
|
||||
iPhoneSdkVersion: 988
|
||||
iOSSimulatorArchitecture: 0
|
||||
iOSTargetOSVersionString:
|
||||
iOSTargetOSVersionString: 15.0
|
||||
tvOSSdkVersion: 0
|
||||
tvOSSimulatorArchitecture: 0
|
||||
tvOSRequireExtendedGameController: 0
|
||||
tvOSTargetOSVersionString:
|
||||
tvOSTargetOSVersionString: 15.0
|
||||
VisionOSSdkVersion: 0
|
||||
VisionOSTargetOSVersionString:
|
||||
VisionOSTargetOSVersionString: 1.0
|
||||
uIPrerenderedIcon: 0
|
||||
uIRequiresPersistentWiFi: 0
|
||||
uIRequiresFullScreen: 1
|
||||
|
|
@ -326,7 +330,7 @@ PlayerSettings:
|
|||
locationUsageDescription:
|
||||
microphoneUsageDescription:
|
||||
bluetoothUsageDescription:
|
||||
macOSTargetOSVersion:
|
||||
macOSTargetOSVersion: 12.0
|
||||
switchNMETAOverride:
|
||||
switchNetLibKey:
|
||||
switchSocketMemoryPoolSize: 6144
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ QualitySettings:
|
|||
asyncUploadBufferSize: 16
|
||||
asyncUploadPersistentBuffer: 1
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
customRenderPipeline: {fileID: 0}
|
||||
customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
terrainQualityOverrides: 0
|
||||
terrainPixelError: 1
|
||||
terrainDetailDensityScale: 1
|
||||
|
|
@ -101,7 +101,7 @@ QualitySettings:
|
|||
asyncUploadBufferSize: 16
|
||||
asyncUploadPersistentBuffer: 1
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
customRenderPipeline: {fileID: 0}
|
||||
customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
terrainQualityOverrides: 0
|
||||
terrainPixelError: 1
|
||||
terrainDetailDensityScale: 1
|
||||
|
|
@ -154,7 +154,7 @@ QualitySettings:
|
|||
asyncUploadBufferSize: 16
|
||||
asyncUploadPersistentBuffer: 1
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
customRenderPipeline: {fileID: 0}
|
||||
customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
terrainQualityOverrides: 0
|
||||
terrainPixelError: 1
|
||||
terrainDetailDensityScale: 1
|
||||
|
|
@ -207,7 +207,7 @@ QualitySettings:
|
|||
asyncUploadBufferSize: 16
|
||||
asyncUploadPersistentBuffer: 1
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
customRenderPipeline: {fileID: 0}
|
||||
customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
terrainQualityOverrides: 0
|
||||
terrainPixelError: 1
|
||||
terrainDetailDensityScale: 1
|
||||
|
|
@ -260,7 +260,7 @@ QualitySettings:
|
|||
asyncUploadBufferSize: 16
|
||||
asyncUploadPersistentBuffer: 1
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
customRenderPipeline: {fileID: 0}
|
||||
customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
terrainQualityOverrides: 0
|
||||
terrainPixelError: 1
|
||||
terrainDetailDensityScale: 1
|
||||
|
|
@ -287,7 +287,7 @@ QualitySettings:
|
|||
globalTextureMipmapLimit: 0
|
||||
textureMipmapLimitSettings: []
|
||||
anisotropicTextures: 2
|
||||
antiAliasing: 2
|
||||
antiAliasing: 4
|
||||
softParticles: 1
|
||||
softVegetation: 1
|
||||
realtimeReflectionProbes: 1
|
||||
|
|
@ -313,7 +313,7 @@ QualitySettings:
|
|||
asyncUploadBufferSize: 16
|
||||
asyncUploadPersistentBuffer: 1
|
||||
resolutionScalingFixedDPIFactor: 1
|
||||
customRenderPipeline: {fileID: 0}
|
||||
customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2}
|
||||
terrainQualityOverrides: 0
|
||||
terrainPixelError: 1
|
||||
terrainDetailDensityScale: 1
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
# U2 · Unity-Spielwelt
|
||||
|
||||
Stand: 30. September 2026 · **nicht begonnen**.
|
||||
Stand: 30. September 2026.
|
||||
|
||||
Voraussetzungen: U1 grün (erfüllt außerhalb von Unity) und aktive Unity-Lizenz (fehlt).
|
||||
| Teil | Inhalt | Zustand |
|
||||
| --- | --- | --- |
|
||||
| U2A | Blender→FBX-Pipeline, sechs repräsentative Assets vollständig geprüft | **fertig** |
|
||||
| U2B | Weltgeometrie (G1-Karte, Türme, Ancients, Grotte, Aufstellungsbereiche), Materialsystem | offen |
|
||||
| U2C | Simulation/Darstellung: fester Takt, Interpolation, Bildraten-Unabhängigkeit | offen |
|
||||
| U2D | spielbare Unity-Partie, Vertical Function Test | offen |
|
||||
|
||||
Voraussetzung U1.5 ist erfüllt ([U1.5-UNITY.md](U1.5-UNITY.md)).
|
||||
|
||||
## Ziel
|
||||
|
||||
Die bestehende Partie läuft sichtbar in Unity (URP). Das ist noch keine grafische Neugestaltung.
|
||||
Die bestehende Partie läuft sichtbar in Unity (URP). Das ist noch keine grafische Neugestaltung; die kommt erst mit U5.
|
||||
|
||||
Zuerst kommen:
|
||||
- die G1-Drei-Lane-Karte,
|
||||
|
|
@ -17,35 +24,127 @@ Zuerst kommen:
|
|||
|
||||
## Vorgaben
|
||||
|
||||
- **Adapter:** Unity treibt `LuneMatch` im festen Takt (0,05 s) über einen Akkumulator, unabhängig von der Bildrate. Ansichten lesen nur; sie schreiben nie in die Regeln.
|
||||
- **Gemeinsames Materialsystem** (URP, Shader Graph oder HLSL): Stein, Metall, Holz, Vegetation, Kristall, Runen, Wasser. Die G2-Shader aus Godot (stone, metal, crystal, rune, cloth, vein, water_glow, hide) dienen als fachliche Vorlage. Automatische Materialkonvertierungen werden nicht ungeprüft übernommen.
|
||||
- **Assets:** Quelle sind die Blender-Dateien und Generatoren im Referenz-Repository. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX für Unity; GLB nur, wo keine bearbeitbare Quelle existiert.
|
||||
- **Adapter:** Unity treibt `LuneMatch` im festen Takt (0,05 s) über einen Akkumulator, unabhängig von der Bildrate. Ansichten lesen nur; sie schreiben nie in die Regeln. Beispiel: `Gebäude-HP = 0` führt zu Einsturz und Ruine, nie umgekehrt eine Animation zu einer Regelwirkung.
|
||||
- **Gemeinsames Materialsystem** (URP): Stein, Metall, Holz, Vegetation, Kristall, Runen, Wasser. Die G2-Shader aus Godot (stone, metal, crystal, rune, cloth, vein, water_glow, hide) dienen als fachliche Vorlage.
|
||||
- **Assets:** Quelle sind die Blender-Dateien und Generatoren im Referenz-Repository. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX; GLB nur, wo keine bearbeitbare Quelle existiert.
|
||||
- **Reihenfolge:** Erst sechs repräsentative Assets vollständig prüfen, dann die Welt und eine vollständige Bot-Partie. Den Batchlauf über alle Assets gibt es erst nach dem Vertical Function Test.
|
||||
|
||||
## Bestand an Quellen (Godot-Referenz)
|
||||
## U2A · Blender→FBX-Pipeline
|
||||
|
||||
| Gruppe | GLB | Blender-Quelle |
|
||||
| --- | ---: | --- |
|
||||
| Truppen, Monster, Sendungen (`assets/models`) | 59 | `assets-source/phase4/blend` (59 `.blend`) |
|
||||
| Figuren mit Skelett (`assets/characters`) | 6 | `assets-source/phase10`–`phase19` (je ein `.blend` plus Generator) |
|
||||
| G2-Bauwerke, Grotte, Schlundkrone (`assets/luneraria/g2`) | 6 | `assets-source/luneraria/g2` (`.blend` plus Generatoren) |
|
||||
| Völker (`assets/luneraria/peoples`) | 7 | `assets-source/luneraria/peoples` |
|
||||
| Umgebung, Vergleich, übrige | 11 | teilweise; wird im Exportinventar geklärt |
|
||||
### Aufbau
|
||||
|
||||
## Prüfpunkte der Pipeline
|
||||
| Datei | Aufgabe |
|
||||
| --- | --- |
|
||||
| `tools/blender/export_manifest.json` | Asset-Liste: Blender-Quelle, Art (statisch, starre Teile, Skelett), Exportregeln und Verweis auf den Godot-Manifesteintrag des GLB, das die Referenz benutzt |
|
||||
| `tools/blender/lune_fbx_export.py` | Blender im Hintergrund: Quelle öffnen, Regeln anwenden, prüfen, FBX schreiben, FBX wieder einlesen und erneut prüfen |
|
||||
| `tools/blender/export_fbx.sh` | Einstieg; macht die FBX-Dateien byteidentisch reproduzierbar |
|
||||
| `Assets/Luneraria/Art/<Gruppe>/<id>.fbx` und `<id>.export.json` | Ergebnis: Modell und Protokoll (Blender-Fakten und Prüfungen) |
|
||||
| `Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs` | Importregeln in Unity |
|
||||
| `Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs` | Unity-Prüfung jedes importierten Modells gegen das Blender-Protokoll |
|
||||
| `Assets/Luneraria/Editor/Art/LuneAssetPreview.cs` | Vorschaubilder in URP |
|
||||
|
||||
- Maßstab (1 Einheit = 1 m) und Achsen (Godot Y-oben/−Z-vorn gegenüber Unity Y-oben/+Z-vorn).
|
||||
- Root Bone und Bone-Namen.
|
||||
- Clip-Namen: idle, walk, attack_a, attack_b, hit, ability, death, roar, victory.
|
||||
- Animation Events.
|
||||
- Materialslots.
|
||||
- Normalen und Tangenten.
|
||||
- Blend Shapes, sofern vorhanden.
|
||||
```bash
|
||||
sh tools/blender/export_fbx.sh
|
||||
```
|
||||
|
||||
## Abnahme
|
||||
```bash
|
||||
/Applications/Unity/Hub/Editor/6000.3.20f1/Unity.app/Contents/MacOS/Unity -batchmode -projectPath "$PWD" -executeMethod Luneraria.EditorTools.LuneAssetVerifier.VerifyAll -logFile -
|
||||
```
|
||||
|
||||
Weitere Einstiege: `LuneAssetVerifier.ReimportArt` (nach geänderten Importregeln) und `LuneAssetPreview.RenderAll`.
|
||||
|
||||
### Exportregeln
|
||||
|
||||
Die Regeln wiederholen, was die Godot-Pipeline beim GLB-Export getan hat. Sonst entstünde ein anderes Modell:
|
||||
|
||||
- **Phase-4-Einheiten:** Die Modifikatoren „HIGH RES“ (Unterteilung und Mikrorelief) kamen erst *nach* dem Laufzeitexport in die `.blend`-Datei. Sie werden nicht angewendet (bei `g01`: 36 Stück).
|
||||
- **Logische Namen:** Die Namen stammen aus den Eigenschaften `part_name` und `material_name`; Blender hatte teils Suffixe wie `.004` ergänzt.
|
||||
- **Figuren mit Skelett:** Die `.blend`-Datei ist vor dem Zusammenfügen gespeichert. Der Export fügt die Teile wie in Godot zu einem Skin-Mesh zusammen (Funkenlanze: 104 Teile → `FunkenBody`).
|
||||
- **Achsen:** Die FBX-Datei behält Blenders Z-oben-Achsen; Unity rechnet sie beim Import mit „Bake Axis Conversion“ um, also ohne Wurzelrotation. Blender (x, y, z) wird dabei Unity (x, z, y); die Vorderseite (Blender −Y) läge auf Unity −Z.
|
||||
- Deshalb dreht der Export jedes Asset vorher um 180° um die Hochachse und wendet die Drehung an. Danach gilt Unity = (−x, y, z) der Godot-/glTF-Koordinaten, und die Vorderseite liegt auf +Z wie in Godot.
|
||||
- Blenders „Apply Transform“ ist für Skelette als fehlerhaft dokumentiert und wird nicht benutzt.
|
||||
- **Maßstab und Inhalt:** 1 Blender-Einheit = 1 m; Normalen, Tangenten (MikkTSpace, wo UVs existieren), lineare Vertexfarben; nur Deform-Bones, keine Leaf-Bones; jede Action wird ein Clip.
|
||||
- **Reproduzierbarkeit:** Blenders FBX-Schreiber stempelt die Uhrzeit ein und leitet Objekt-IDs aus Pythons String-Hash ab. Der Export fixiert beides (feste Uhrzeit, `PYTHONHASHSEED=0` mit `--python-use-system-env`). Zwei Läufe liefern byteidentische FBX-Dateien und identische Protokolle.
|
||||
|
||||
### Prüfungen
|
||||
|
||||
Blender-Seite, vor und nach dem Schreiben (Rundreise durch einen FBX-Import):
|
||||
|
||||
| Prüfpunkt | Wie |
|
||||
| --- | --- |
|
||||
| Einheiten, Maßstab | metrisch, `scale_length` 1, keine Objektskalierung, keine negative Skalierung |
|
||||
| Achsen, Vorderseite | Drehung angewendet; Vorwärtsmarker (Phase 4: Empty `Forward`) liegt in Unity auf +Z |
|
||||
| Mesh-Namen | eindeutig; gleich den Knoten des Godot-GLB |
|
||||
| Dreiecke | gleich dem Godot-GLB, auch nach dem Wiedereinlesen |
|
||||
| Materialslots | keine leeren Slots; Materialien gleich dem Godot-GLB |
|
||||
| Normalen | Einheitslänge an allen Ecken |
|
||||
| Tangenten | Voraussetzungen (UVs, keine N-Ecke); Meshes ohne UVs sind vermerkt und werden triplanar oder unbeleuchtet schattiert |
|
||||
| Maße | Ruhelage gleich den `bounds_godot` des Godot-Manifests (Türme und Ancient: ohne Schadens- und Ruinenteile, wie dort gemessen) |
|
||||
| Skelett | genau eine Armature, ein Root Bone `Root`, Bone-Namen und -Anzahl wie im Godot-GLB, portable Namen |
|
||||
| Clips | Namen und Längen wie im Godot-GLB; Pflichtclips vorhanden; Loop-Flag und Kontaktzeit aus den Action-Eigenschaften |
|
||||
| Blend Shapes | keine in den Quellen |
|
||||
|
||||
Unity-Seite (`LuneAssetVerifier`, gegen das Blender-Protokoll):
|
||||
|
||||
| Prüfpunkt | Wie |
|
||||
| --- | --- |
|
||||
| Importregeln | Maßstab 1, Dateieinheiten, Achsen-Bake, Normalen und Tangenten aus der Datei |
|
||||
| Achsen | Wurzel und alle Nicht-Bone-Knoten ohne Rotation und Skalierung |
|
||||
| Mesh-Namen, Dreiecke | Menge und Anzahl je Mesh gleich |
|
||||
| Maße | aus den Vertices berechnet, Abweichung höchstens 2 mm; gemessen höchstens 0,05 mm |
|
||||
| Materialslots | Namen je Renderer gleich den Blender-Slots |
|
||||
| Normalen, Tangenten, UVs, Vertexfarben | vorhanden und gültig, wo Blender sie hat; Tangenten mit w = ±1 |
|
||||
| Vorderseite | Vorwärtsmarker auf +Z |
|
||||
| Skelett | Root Bone, Bone-Namen, gültiger Generic-Avatar |
|
||||
| Clips | Namen, Längen (auf einen halben Frame genau), Loop-Flags, Kontakt-Events (`OnLuneContact`) |
|
||||
|
||||
### Ergebnis: sechs repräsentative Assets und drei Szenenbauten
|
||||
|
||||
| Asset | vertritt | Dreiecke (= Godot-GLB) | Blender-Prüfungen | Unity-Prüfungen |
|
||||
| --- | --- | ---: | --- | --- |
|
||||
| `g01` Kohlenbeißer | normale Einheit, 131 benannte Teile | 79.780 | 18/18 | 14/14 |
|
||||
| `funkenlanze` | Einheit mit Skelett (Held), 26 Bones, 9 Clips | 24.036 | 26/26 | 18/18 |
|
||||
| `grenzwacht` | Turm (mit Schadens- und Ruinenteilen) | 6.516 | 18/18 | 13/13 |
|
||||
| `ancient` Mondherz | Ancient | 19.032 | 18/18 | 13/13 |
|
||||
| `schlundkrone` | Schlundkrone (Boss), 24 Bones, 11 Clips | 5.712 | 28/28 | 18/18 |
|
||||
| `map_props` | Vegetation und Kartenrequisiten (Eichen, Kiefern, Sträucher, Felsen, Brücke, Randsteine) | 7.338 | 14/14 | 13/13 |
|
||||
| `bastion`, `kernwacht`, `bossgrotte` | für die Szene in U2B (Innen- und Basisturm, Mondschlund) | 9.364, 9.224, 15.182 | je 18/18 | je 13/13 |
|
||||
|
||||
Summe: 176 Blender-Prüfungen und 128 Unity-Prüfungen, alle bestanden. Protokolle:
|
||||
- `Assets/Luneraria/Art/*/*.export.json` (Blender).
|
||||
- `docs/port/logs/u2a/unity-verify.json` (Unity).
|
||||
|
||||
Bilder unter `docs/port/screenshots/u2a/`:
|
||||
- je Asset eine Ansicht von vorn-rechts,
|
||||
- die Grenzwacht zusätzlich als Ruine,
|
||||
- Funkenlanze und Schlundkrone zusätzlich im Kontaktframe von `attack_a` (Clips laufen).
|
||||
|
||||
### Bekannte Grenzen
|
||||
|
||||
- **Materialien:** Die Vorschau benutzt URP-Lit-Materialien, die Unity aus den FBX-Materialbeschreibungen erzeugt (Blender-Palettenfarben). Das eigentliche Materialsystem (Stein, Metall, Kristall, Runen, Stoff, Wasser; Teamfarben; Vertex-AO) folgt in U2B.
|
||||
- Stoff (Wimpel, Banner) ist einseitig modelliert und braucht dort doppelseitiges Rendern; in der Vorschau fehlt er deshalb.
|
||||
- **Ohne UVs:** Diese Meshes haben keine Tangenten (Unity meldet das beim Import): Kristalle, Trümmer, Felsen, Kartenrequisiten und einige Phase-4-Kleinteile. Sie brauchen triplanare oder unbeleuchtete Materialien.
|
||||
- **Starre Einheiten:** Die Phase-4-Einheiten werden in Godot aus benannten Teilen prozedural animiert. Die Teile kommen mit, die Animation folgt mit den Einheitenansichten.
|
||||
- **Größe:** Die FBX-Dateien liegen direkt im Repository (9 Dateien, 16 MB). Für den Batchlauf über alle Assets ist Git LFS zu erwägen.
|
||||
|
||||
### Batchlauf (nach dem Vertical Function Test)
|
||||
|
||||
Das Manifest enthält bisher die 9 Assets der Szene. Die übrigen Assets kommen erst nach U2D in das Manifest und werden dann mit denselben Regeln und Prüfungen exportiert:
|
||||
- 58 weitere Phase-4-Modelle.
|
||||
- 5 Figuren mit Skelett.
|
||||
- 7 Völker-Modelle. Für Zwerg und Troll fehlt die `.blend`-Datei im Referenz-Repository; sie entsteht aus dem Generator `build_peoples.py`.
|
||||
|
||||
Bauten aus einer GLB ohne Quelle folgen nur nach Einzelfallprüfung.
|
||||
|
||||
## U2B bis U2D
|
||||
|
||||
Folgen in diesem Dokument.
|
||||
|
||||
## Abnahme (gesamt)
|
||||
|
||||
- Die Partie läuft sichtbar.
|
||||
- Die Kamera entspricht der Godot-Kamera.
|
||||
- Screenshots neben den Godot-G2-Bildern mit vergleichbarer Kamera.
|
||||
- Leistung gemessen, einschließlich Mono-Simulationszeit.
|
||||
- Bekannte Unterschiede dokumentiert.
|
||||
- Commit auf `luneraria/u2`.
|
||||
- Commits U2A bis U2D auf `luneraria/u2`.
|
||||
|
|
|
|||
968
docs/port/logs/u2a/unity-verify.json
Normal file
|
|
@ -0,0 +1,968 @@
|
|||
{
|
||||
"unity": "6000.3.20f1",
|
||||
"ok": true,
|
||||
"assets": [
|
||||
{
|
||||
"id": "ancient",
|
||||
"kind": "static",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Buildings/ancient.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"ancient pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"19032 unity / 19032 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00005 m; unity (-4.204, -0.988, -4.000) (4.204, 10.367, 4.000)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 19032,
|
||||
"renderers": 27,
|
||||
"meshes_without_uv_and_tangents": 14,
|
||||
"bounds_min": [
|
||||
-4.20353031,
|
||||
-0.9881463,
|
||||
-4.0
|
||||
],
|
||||
"bounds_max": [
|
||||
4.20352936,
|
||||
10.3668232,
|
||||
4.0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bastion",
|
||||
"kind": "static",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Buildings/bastion.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"bastion pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"9364 unity / 9364 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00005 m; unity (-2.116, -0.389, -2.539) (2.901, 7.161, 1.950)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 9364,
|
||||
"renderers": 11,
|
||||
"meshes_without_uv_and_tangents": 6,
|
||||
"bounds_min": [
|
||||
-2.11555481,
|
||||
-0.3890798,
|
||||
-2.538877
|
||||
],
|
||||
"bounds_max": [
|
||||
2.90077925,
|
||||
7.160508,
|
||||
1.94963574
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bossgrotte",
|
||||
"kind": "static",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Buildings/bossgrotte.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"bossgrotte pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"15182 unity / 15182 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00004 m; unity (-7.777, -1.930, -10.465) (10.544, 7.693, 7.798)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 15182,
|
||||
"renderers": 12,
|
||||
"meshes_without_uv_and_tangents": 4,
|
||||
"bounds_min": [
|
||||
-7.77746248,
|
||||
-1.93,
|
||||
-10.4646072
|
||||
],
|
||||
"bounds_max": [
|
||||
10.5441828,
|
||||
7.69265556,
|
||||
7.79764366
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "grenzwacht",
|
||||
"kind": "static",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Buildings/grenzwacht.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"grenzwacht pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"6516 unity / 6516 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00005 m; unity (-2.258, -0.065, -2.553) (1.966, 6.060, 1.368)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 6516,
|
||||
"renderers": 7,
|
||||
"meshes_without_uv_and_tangents": 2,
|
||||
"bounds_min": [
|
||||
-2.25751829,
|
||||
-0.06533188,
|
||||
-2.55256557
|
||||
],
|
||||
"bounds_max": [
|
||||
1.96584618,
|
||||
6.060136,
|
||||
1.36833835
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "kernwacht",
|
||||
"kind": "static",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Buildings/kernwacht.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"kernwacht pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"9224 unity / 9224 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00004 m; unity (-6.076, -2.396, -2.194) (2.396, 8.330, 1.813)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 9224,
|
||||
"renderers": 9,
|
||||
"meshes_without_uv_and_tangents": 2,
|
||||
"bounds_min": [
|
||||
-6.07622528,
|
||||
-2.39588761,
|
||||
-2.19388914
|
||||
],
|
||||
"bounds_max": [
|
||||
2.39623713,
|
||||
8.33,
|
||||
1.81258774
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "funkenlanze",
|
||||
"kind": "skinned",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Characters/funkenlanze.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"funkenlanze pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"24036 unity / 24036 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00005 m; unity (-0.565, -0.010, -0.295) (0.430, 2.021, 1.435)\""
|
||||
},
|
||||
{
|
||||
"check": "skinned_mesh",
|
||||
"ok": true,
|
||||
"detail": "1"
|
||||
},
|
||||
{
|
||||
"check": "bone_names FunkenBody",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "root_bone FunkenBody",
|
||||
"ok": true,
|
||||
"detail": "\"Root\""
|
||||
},
|
||||
{
|
||||
"check": "generic_avatar",
|
||||
"ok": true,
|
||||
"detail": "\"funkenlanzeAvatar\""
|
||||
},
|
||||
{
|
||||
"check": "clips",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 24036,
|
||||
"renderers": 1,
|
||||
"meshes_without_uv_and_tangents": 0,
|
||||
"bounds_min": [
|
||||
-0.5651692,
|
||||
-0.0104093477,
|
||||
-0.2945487
|
||||
],
|
||||
"bounds_max": [
|
||||
0.43,
|
||||
2.02119541,
|
||||
1.43500006
|
||||
],
|
||||
"clips": [
|
||||
{
|
||||
"name": "ability",
|
||||
"length": 1.3,
|
||||
"loop": false,
|
||||
"events": 1
|
||||
},
|
||||
{
|
||||
"name": "attack_a",
|
||||
"length": 1.3,
|
||||
"loop": false,
|
||||
"events": 1
|
||||
},
|
||||
{
|
||||
"name": "attack_b",
|
||||
"length": 1.3,
|
||||
"loop": false,
|
||||
"events": 1
|
||||
},
|
||||
{
|
||||
"name": "death",
|
||||
"length": 2.0,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "hit",
|
||||
"length": 0.5,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "idle",
|
||||
"length": 3.0,
|
||||
"loop": true,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"length": 0.4,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "stop",
|
||||
"length": 0.4,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "walk",
|
||||
"length": 1.2,
|
||||
"loop": true,
|
||||
"events": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "schlundkrone",
|
||||
"kind": "skinned",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Characters/schlundkrone.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"schlundkrone pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"5712 unity / 5712 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00005 m; unity (-1.327, 0.005, -0.553) (1.231, 3.318, 0.925)\""
|
||||
},
|
||||
{
|
||||
"check": "skinned_mesh",
|
||||
"ok": true,
|
||||
"detail": "1"
|
||||
},
|
||||
{
|
||||
"check": "bone_names SchlundkroneBody",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "root_bone SchlundkroneBody",
|
||||
"ok": true,
|
||||
"detail": "\"Root\""
|
||||
},
|
||||
{
|
||||
"check": "generic_avatar",
|
||||
"ok": true,
|
||||
"detail": "\"schlundkroneAvatar\""
|
||||
},
|
||||
{
|
||||
"check": "clips",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 5712,
|
||||
"renderers": 1,
|
||||
"meshes_without_uv_and_tangents": 0,
|
||||
"bounds_min": [
|
||||
-1.32726932,
|
||||
0.00534708425,
|
||||
-0.5531612
|
||||
],
|
||||
"bounds_max": [
|
||||
1.23073983,
|
||||
3.31821656,
|
||||
0.9253263
|
||||
],
|
||||
"clips": [
|
||||
{
|
||||
"name": "ability",
|
||||
"length": 1.3,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "attack_a",
|
||||
"length": 1.3,
|
||||
"loop": false,
|
||||
"events": 1
|
||||
},
|
||||
{
|
||||
"name": "attack_b",
|
||||
"length": 1.3,
|
||||
"loop": false,
|
||||
"events": 1
|
||||
},
|
||||
{
|
||||
"name": "death",
|
||||
"length": 2.2,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "hit",
|
||||
"length": 0.5,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "idle",
|
||||
"length": 3.0,
|
||||
"loop": true,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "roar",
|
||||
"length": 2.0,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"length": 0.4,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "stop",
|
||||
"length": 0.4,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "victory",
|
||||
"length": 2.0,
|
||||
"loop": false,
|
||||
"events": 0
|
||||
},
|
||||
{
|
||||
"name": "walk",
|
||||
"length": 1.6,
|
||||
"loop": true,
|
||||
"events": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "map_props",
|
||||
"kind": "static",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Environment/map_props.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"map_props pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"7338 unity / 7338 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00002 m; unity (-7.368, -1.300, -3.900) (7.455, 5.244, 3.900)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 7338,
|
||||
"renderers": 15,
|
||||
"meshes_without_uv_and_tangents": 15,
|
||||
"bounds_min": [
|
||||
-7.368419,
|
||||
-1.3,
|
||||
-3.90000057
|
||||
],
|
||||
"bounds_max": [
|
||||
7.455483,
|
||||
5.244,
|
||||
3.90000057
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "g01",
|
||||
"kind": "rigid",
|
||||
"ok": true,
|
||||
"checks": [
|
||||
{
|
||||
"check": "blender_checks_passed",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "imported",
|
||||
"ok": true,
|
||||
"detail": "\"Assets/Luneraria/Art/Units/g01.fbx\""
|
||||
},
|
||||
{
|
||||
"check": "import_rules_applied",
|
||||
"ok": true,
|
||||
"detail": ""
|
||||
},
|
||||
{
|
||||
"check": "root_transform_identity",
|
||||
"ok": true,
|
||||
"detail": "\"g01 pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||
},
|
||||
{
|
||||
"check": "node_transforms_axis_clean",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "mesh_names",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "triangles",
|
||||
"ok": true,
|
||||
"detail": "\"79780 unity / 79780 blender \""
|
||||
},
|
||||
{
|
||||
"check": "material_slots",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "normals_unit_length",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "tangents_where_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "uvs_where_blender_has_uv",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "vertex_colors",
|
||||
"ok": true,
|
||||
"detail": "[]"
|
||||
},
|
||||
{
|
||||
"check": "bounds_axes_scale",
|
||||
"ok": true,
|
||||
"detail": "\"largest difference 0.00004 m; unity (-0.792, 0.000, -0.447) (0.792, 1.350, 0.447)\""
|
||||
},
|
||||
{
|
||||
"check": "forward_is_plus_z",
|
||||
"ok": true,
|
||||
"detail": "\"(0.000, 0.000, 0.750)\""
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"triangles": 79780,
|
||||
"renderers": 131,
|
||||
"meshes_without_uv_and_tangents": 38,
|
||||
"bounds_min": [
|
||||
-0.792443752,
|
||||
0.0,
|
||||
-0.447301447
|
||||
],
|
||||
"bounds_max": [
|
||||
0.7924438,
|
||||
1.35,
|
||||
0.447301567
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
docs/port/screenshots/u2a/ancient.png
Normal file
|
After Width: | Height: | Size: 230 KiB |
BIN
docs/port/screenshots/u2a/bastion.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
docs/port/screenshots/u2a/bossgrotte.png
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
docs/port/screenshots/u2a/funkenlanze-attack_a.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
docs/port/screenshots/u2a/funkenlanze.png
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
docs/port/screenshots/u2a/g01.png
Normal file
|
After Width: | Height: | Size: 400 KiB |
BIN
docs/port/screenshots/u2a/grenzwacht-ruin.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
docs/port/screenshots/u2a/grenzwacht.png
Normal file
|
After Width: | Height: | Size: 191 KiB |
BIN
docs/port/screenshots/u2a/kernwacht.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
docs/port/screenshots/u2a/map_props.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
docs/port/screenshots/u2a/schlundkrone-attack_a.png
Normal file
|
After Width: | Height: | Size: 231 KiB |
BIN
docs/port/screenshots/u2a/schlundkrone.png
Normal file
|
After Width: | Height: | Size: 241 KiB |
11
tools/blender/export_fbx.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
# Blender -> FBX export of the Unity port (U2A): sh tools/blender/export_fbx.sh [id,id,...]
|
||||
# Without ids every asset of tools/blender/export_manifest.json is exported. Needs Blender 5.2
|
||||
# (BLENDER, default "blender") and the Godot reference (GODOT_PROJECT, default ../saumwacht-godot).
|
||||
# PYTHONHASHSEED=0 with --python-use-system-env makes the FBX object ids reproducible.
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
BLENDER="${BLENDER:-blender}"
|
||||
GODOT_PROJECT="${GODOT_PROJECT:-../saumwacht-godot}"
|
||||
PYTHONHASHSEED=0 "$BLENDER" --background --factory-startup --python-use-system-env \
|
||||
--python tools/blender/lune_fbx_export.py -- --godot "$GODOT_PROJECT" --ids "${1:-}"
|
||||
58
tools/blender/export_manifest.json
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"comment": "Export rules per asset for tools/blender/lune_fbx_export.py. source: Blender file in the Godot reference (../saumwacht-godot). godot_manifest: the manifest entry of the GLB the reference game uses; the FBX must match it (triangles, names, materials, bounds, bones, clips). kind: static | rigid (named parts, animated by the view) | skinned.",
|
||||
"assets": [
|
||||
{
|
||||
"id": "g01", "group": "Units", "kind": "rigid", "representative": "normal unit (Glutpakt melee, 131 named parts)",
|
||||
"source": "assets-source/phase4/blend/g01.blend",
|
||||
"godot_manifest": {"file": "assets/phase4_manifest.json", "id": "g01"},
|
||||
"rules": {"skip_modifiers": ["HIGH RES"], "logical_names": true, "forward_marker": "Forward", "check_parts": false}
|
||||
},
|
||||
{
|
||||
"id": "funkenlanze", "group": "Characters", "kind": "skinned", "representative": "rigged unit (hero Funkenlanze)",
|
||||
"source": "assets-source/phase18/funkenlanze.blend",
|
||||
"godot_manifest": {"file": "assets/phase18_manifest.json", "id": "g05"},
|
||||
"rules": {"join": {"parent": "FunkenRig", "into": "FunkenBody"}, "rest_action": null, "root_bone": "Root",
|
||||
"required_clips": ["idle", "walk", "attack_a", "attack_b", "hit", "ability", "death"]}
|
||||
},
|
||||
{
|
||||
"id": "grenzwacht", "group": "Buildings", "kind": "static", "representative": "tower (outer lane tower)",
|
||||
"source": "assets-source/luneraria/g2/grenzwacht.blend",
|
||||
"godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "grenzwacht"},
|
||||
"rules": {"bounds_exclude": ["Upper_Damaged", "Debris", "Ruin", "Pennant", "Banner"]}
|
||||
},
|
||||
{
|
||||
"id": "ancient", "group": "Buildings", "kind": "static", "representative": "Ancient (Mondherz)",
|
||||
"source": "assets-source/luneraria/g2/ancient.blend",
|
||||
"godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "ancient"},
|
||||
"rules": {"bounds_exclude": ["Banner", "Ruin_"]}
|
||||
},
|
||||
{
|
||||
"id": "schlundkrone", "group": "Characters", "kind": "skinned", "representative": "Schlundkrone (boss)",
|
||||
"source": "assets-source/luneraria/g2/schlundkrone.blend",
|
||||
"godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "schlundkrone"},
|
||||
"rules": {"rest_action": null, "root_bone": "Root",
|
||||
"required_clips": ["idle", "walk", "attack_a", "attack_b", "hit", "ability", "death", "roar", "victory"]}
|
||||
},
|
||||
{
|
||||
"id": "map_props", "group": "Environment", "kind": "static", "representative": "vegetation and map props (oaks, pines, shrubs, rocks, bridge, curb)",
|
||||
"source": "assets-source/luneraria/map_props.blend"
|
||||
},
|
||||
{
|
||||
"id": "bastion", "group": "Buildings", "kind": "static",
|
||||
"source": "assets-source/luneraria/g2/bastion.blend",
|
||||
"godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "bastion"},
|
||||
"rules": {"bounds_exclude": ["Upper_Damaged", "Debris", "Ruin", "Pennant", "Banner"]}
|
||||
},
|
||||
{
|
||||
"id": "kernwacht", "group": "Buildings", "kind": "static",
|
||||
"source": "assets-source/luneraria/g2/kernwacht.blend",
|
||||
"godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "kernwacht"},
|
||||
"rules": {"bounds_exclude": ["Upper_Damaged", "Debris", "Ruin", "Pennant", "Banner"]}
|
||||
},
|
||||
{
|
||||
"id": "bossgrotte", "group": "Buildings", "kind": "static",
|
||||
"source": "assets-source/luneraria/g2/bossgrotte.blend",
|
||||
"godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "bossgrotte"}
|
||||
}
|
||||
]
|
||||
}
|
||||
33
tools/blender/inspect_blend.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
"""Prints a JSON summary of a .blend file (objects, meshes, materials, armatures, actions).
|
||||
Usage: blender --background <file.blend> --python tools/blender/inspect_blend.py -- <out.json>"""
|
||||
import bpy, json, sys
|
||||
out = sys.argv[sys.argv.index('--') + 1] if '--' in sys.argv else None
|
||||
scene = bpy.context.scene
|
||||
info = {'file': bpy.data.filepath, 'unit_system': scene.unit_settings.system, 'scale_length': scene.unit_settings.scale_length,
|
||||
'fps': scene.render.fps, 'objects': [], 'actions': []}
|
||||
for obj in bpy.data.objects:
|
||||
entry = {'name': obj.name, 'type': obj.type, 'parent': obj.parent.name if obj.parent else None,
|
||||
'location': [round(v, 4) for v in obj.location], 'rotation': [round(v, 4) for v in obj.rotation_euler],
|
||||
'scale': [round(v, 4) for v in obj.scale], 'in_scene': obj.name in scene.objects,
|
||||
'hide_render': obj.hide_render}
|
||||
if obj.type == 'MESH':
|
||||
me = obj.data
|
||||
entry.update({'mesh': me.name, 'verts': len(me.vertices), 'polys': len(me.polygons),
|
||||
'ngons': sum(1 for p in me.polygons if len(p.vertices) > 4),
|
||||
'materials': [m.name if m else None for m in me.materials], 'uv_layers': [uv.name for uv in me.uv_layers],
|
||||
'color_attributes': [(c.name, c.domain, c.data_type) for c in me.color_attributes],
|
||||
'custom_normals': me.has_custom_normals, 'shape_keys': [k.name for k in me.shape_keys.key_blocks] if me.shape_keys else [],
|
||||
'modifiers': [(m.type, m.name) for m in obj.modifiers], 'vertex_groups': len(obj.vertex_groups)})
|
||||
if obj.type == 'ARMATURE':
|
||||
arm = obj.data
|
||||
entry.update({'bones': len(arm.bones), 'roots': [b.name for b in arm.bones if b.parent is None],
|
||||
'bone_names': [b.name for b in arm.bones][:80], 'action': obj.animation_data.action.name if obj.animation_data and obj.animation_data.action else None,
|
||||
'nla': [(t.name, [s.action.name for s in t.strips if s.action]) for t in obj.animation_data.nla_tracks] if obj.animation_data else []})
|
||||
info['objects'].append(entry)
|
||||
for act in bpy.data.actions:
|
||||
info['actions'].append({'name': act.name, 'range': [round(v, 2) for v in act.frame_range], 'users': act.users, 'fake_user': act.use_fake_user})
|
||||
text = json.dumps(info, indent=1)
|
||||
if out:
|
||||
open(out, 'w').write(text)
|
||||
else:
|
||||
print(text)
|
||||
454
tools/blender/lune_fbx_export.py
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
"""Reproducible Blender -> FBX export for the Unity port (docs/port/U2-WORLD.md, U2A).
|
||||
|
||||
Runs headless on the Blender sources of the Godot reference, applies the per-asset export
|
||||
rules of tools/blender/export_manifest.json, checks the result and writes, per asset:
|
||||
|
||||
Assets/Luneraria/Art/<group>/<id>.fbx the model for Unity
|
||||
Assets/Luneraria/Art/<group>/<id>.export.json facts and checks (read by Unity's importer)
|
||||
|
||||
Checks: units and scale, up and forward axis, object transforms, mesh names, triangle counts,
|
||||
material slots, UVs, normals, tangent prerequisites, vertex colours, root bone, bone names,
|
||||
clips (names, lengths, loop flags, contact events), bounds. Expectations come from the Godot
|
||||
manifests of the GLBs the reference game uses, so the FBX must describe the same model.
|
||||
After writing, the FBX is imported into an empty scene and checked again (round trip).
|
||||
|
||||
Usage (from the Unity project root): sh tools/blender/export_fbx.sh [id,id,...]
|
||||
(runs blender --background --factory-startup --python-use-system-env with PYTHONHASHSEED=0
|
||||
--python tools/blender/lune_fbx_export.py -- --godot ../saumwacht-godot --ids <ids>)
|
||||
Exit code 0 only if every check of every asset passed.
|
||||
"""
|
||||
import bpy
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from mathutils import Matrix, Vector
|
||||
|
||||
UNITY_ROOT = Path(__file__).resolve().parents[2]
|
||||
EXPORTER_VERSION = 5
|
||||
|
||||
# One export setting for every asset. The file keeps Blender's Z-up axes; Unity's importer
|
||||
# converts them with "Bake Axis Conversion" as Unity (x, y, z) = Blender (x, z, y), so no root
|
||||
# carries a rotation and animation data is converted with the meshes (Blender's own "Apply
|
||||
# Transform" is documented as broken for armatures). Before export every asset is turned by 180
|
||||
# degrees about Blender's Z and the turn is applied (face_unity_forward): the front (Blender -Y,
|
||||
# glTF/Godot +Z) then becomes Unity +Z, and Unity = (-x, y, z) of the Godot coordinates.
|
||||
FBX_SETTINGS = dict(
|
||||
use_selection=True, use_visible=False, use_active_collection=False,
|
||||
global_scale=1.0, apply_unit_scale=True, apply_scale_options='FBX_SCALE_UNITS',
|
||||
axis_forward='Y', axis_up='Z', bake_space_transform=False,
|
||||
object_types={'EMPTY', 'MESH', 'ARMATURE'},
|
||||
use_mesh_modifiers=True, use_mesh_modifiers_render=True,
|
||||
mesh_smooth_type='OFF', use_subsurf=False, use_mesh_edges=False, use_tspace=True,
|
||||
use_triangles=False, colors_type='LINEAR', prioritize_active_color=True,
|
||||
use_custom_props=False,
|
||||
add_leaf_bones=False, primary_bone_axis='Y', secondary_bone_axis='X',
|
||||
use_armature_deform_only=True, armature_nodetype='NULL',
|
||||
bake_anim=True, bake_anim_use_all_bones=True, bake_anim_use_nla_strips=False,
|
||||
bake_anim_use_all_actions=True, bake_anim_force_startend_keying=True,
|
||||
bake_anim_step=1.0, bake_anim_simplify_factor=0.0,
|
||||
path_mode='STRIP', embed_textures=False, batch_mode='OFF',
|
||||
)
|
||||
|
||||
|
||||
def args():
|
||||
argv = sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []
|
||||
result = {'manifest': str(UNITY_ROOT / 'tools/blender/export_manifest.json'), 'godot': str(UNITY_ROOT.parent / 'saumwacht-godot'), 'ids': ''}
|
||||
for i in range(0, len(argv) - 1, 2):
|
||||
result[argv[i].lstrip('-')] = argv[i + 1]
|
||||
return result
|
||||
|
||||
|
||||
class Report:
|
||||
def __init__(self, spec):
|
||||
self.data = {'id': spec['id'], 'group': spec['group'], 'source': spec['source'], 'exporter_version': EXPORTER_VERSION,
|
||||
'blender': bpy.app.version_string, 'fbx_settings': {k: (sorted(v) if isinstance(v, set) else v) for k, v in FBX_SETTINGS.items()},
|
||||
'checks': []}
|
||||
|
||||
def check(self, name, ok, detail=''):
|
||||
self.data['checks'].append({'check': name, 'ok': bool(ok), 'detail': str(detail)})
|
||||
return ok
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return all(c['ok'] for c in self.data['checks'])
|
||||
|
||||
|
||||
def godot_expectations(spec, godot_root):
|
||||
"""Facts of the GLB the reference uses, from its manifest (triangles, nodes, bounds, ...)."""
|
||||
source = spec.get('godot_manifest')
|
||||
if not source:
|
||||
return {}
|
||||
data = json.loads((godot_root / source['file']).read_text())
|
||||
assets = data['assets'] if isinstance(data, dict) and 'assets' in data else data
|
||||
for entry in assets:
|
||||
if entry.get('id') == source['id']:
|
||||
return entry
|
||||
raise KeyError('no entry %s in %s' % (source['id'], source['file']))
|
||||
|
||||
|
||||
def triangles(mesh):
|
||||
return sum(len(p.vertices) - 2 for p in mesh.polygons)
|
||||
|
||||
|
||||
def evaluated_mesh(obj, depsgraph):
|
||||
evaluated = obj.evaluated_get(depsgraph)
|
||||
return evaluated, evaluated.to_mesh()
|
||||
|
||||
|
||||
def prepare(spec, report):
|
||||
"""Applies the export rules of the manifest to the opened .blend (never saved)."""
|
||||
rules = spec.get('rules', {})
|
||||
skip = tuple(rules.get('skip_modifiers', ()))
|
||||
removed = 0
|
||||
if skip:
|
||||
for obj in bpy.data.objects:
|
||||
for modifier in list(obj.modifiers):
|
||||
if modifier.name.startswith(skip):
|
||||
obj.modifiers.remove(modifier)
|
||||
removed += 1
|
||||
report.data['removed_modifiers'] = removed
|
||||
if rules.get('logical_names'):
|
||||
logical_names(report)
|
||||
join = rules.get('join')
|
||||
if join:
|
||||
parts = [o for o in bpy.context.scene.objects if o.type == 'MESH' and o.parent and o.parent.name == join['parent']]
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for obj in parts:
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = parts[0]
|
||||
bpy.ops.object.join()
|
||||
bpy.context.object.name = join['into']
|
||||
bpy.context.object.data.name = join['into']
|
||||
report.data['joined_parts'] = len(parts)
|
||||
face_unity_forward(report)
|
||||
rest_action = rules.get('rest_action')
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'ARMATURE' and obj.animation_data:
|
||||
# Export the bind pose, not the last evaluated frame of some action.
|
||||
obj.animation_data.action = bpy.data.actions.get(rest_action) if rest_action else None
|
||||
bpy.context.scene.frame_set(0)
|
||||
|
||||
|
||||
def face_unity_forward(report):
|
||||
"""Turns every root 180 degrees about Z and applies the turn to all objects (meshes, empties,
|
||||
armatures with their rest pose). Bone animation is stored relative to the rest pose and
|
||||
stays valid. Shared mesh data is made single-user first."""
|
||||
turn = Matrix.Rotation(math.pi, 4, 'Z')
|
||||
scene_objects = [o for o in bpy.context.scene.objects if o.type in ('MESH', 'ARMATURE', 'EMPTY')]
|
||||
for obj in scene_objects:
|
||||
if obj.parent is None:
|
||||
obj.matrix_world = turn @ obj.matrix_world
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for obj in scene_objects:
|
||||
obj.hide_set(False)
|
||||
obj.hide_select = False
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = scene_objects[0]
|
||||
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, isolate_users=True)
|
||||
turned = [o.name for o in scene_objects if o.matrix_world.to_euler().z != 0.0 and abs(o.matrix_world.to_euler().z) > 1e-5]
|
||||
report.check('turn_applied', not turned, turned[:8])
|
||||
|
||||
|
||||
def logical_names(report):
|
||||
"""Phase-4 sources keep their logical names in custom properties (part_name, material_name);
|
||||
Blender may have suffixed the datablocks (.004). The Godot pipeline renamed the GLB nodes the
|
||||
same way (assets-source/phase4/blender/pipeline.py, _canonical_glb_names). Materials that share
|
||||
a logical name are one material and are merged."""
|
||||
renamed = 0
|
||||
for obj in list(bpy.data.objects):
|
||||
if 'part_name' in obj.keys():
|
||||
obj.name = '__lune_tmp_' + obj.name
|
||||
for obj in list(bpy.data.objects):
|
||||
if 'part_name' in obj.keys():
|
||||
obj.name = obj['part_name']
|
||||
renamed += int(obj.name == obj['part_name'])
|
||||
groups = {}
|
||||
for material in list(bpy.data.materials):
|
||||
logical = material.get('material_name')
|
||||
if logical:
|
||||
groups.setdefault(logical, []).append(material)
|
||||
merged = 0
|
||||
for logical, materials in groups.items():
|
||||
keep = materials[0]
|
||||
for other in materials[1:]:
|
||||
other.user_remap(keep)
|
||||
merged += 1
|
||||
for material in materials[1:]:
|
||||
bpy.data.materials.remove(material)
|
||||
keep.name = '__lune_tmp_' + logical
|
||||
for logical in groups:
|
||||
bpy.data.materials['__lune_tmp_' + logical].name = logical
|
||||
collisions = [o.name for o in bpy.data.objects if 'part_name' in o.keys() and o.name != o['part_name']]
|
||||
report.check('logical_names_unique', not collisions, collisions[:12])
|
||||
report.data['logical_names'] = {'objects': renamed, 'materials': len(groups), 'merged_materials': merged}
|
||||
|
||||
|
||||
def export_objects(spec):
|
||||
include = spec.get('rules', {}).get('objects')
|
||||
objects = []
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type not in ('MESH', 'ARMATURE', 'EMPTY'):
|
||||
continue
|
||||
if include and obj.name not in include:
|
||||
continue
|
||||
if obj.hide_render:
|
||||
continue
|
||||
objects.append(obj)
|
||||
return objects
|
||||
|
||||
|
||||
def to_unity(v):
|
||||
"""Blender (x, y, z), after the turn of face_unity_forward -> Unity (x, y, z) = (x, z, y)."""
|
||||
return Vector((v.x, v.z, v.y))
|
||||
|
||||
|
||||
def facts(objects, depsgraph):
|
||||
"""Scene facts in Unity coordinates: meshes, materials, bounds, bones, actions."""
|
||||
meshes = {}
|
||||
low = Vector((math.inf,) * 3)
|
||||
high = Vector((-math.inf,) * 3)
|
||||
for obj in objects:
|
||||
if obj.type != 'MESH':
|
||||
continue
|
||||
evaluated, mesh = evaluated_mesh(obj, depsgraph)
|
||||
world = evaluated.matrix_world
|
||||
# Skinned meshes: bounds of the rest pose (armature modifier is evaluated in the bind pose).
|
||||
mesh_low = Vector((math.inf,) * 3)
|
||||
mesh_high = Vector((-math.inf,) * 3)
|
||||
for vertex in mesh.vertices:
|
||||
p = to_unity(world @ vertex.co)
|
||||
mesh_low = Vector(map(min, mesh_low, p))
|
||||
mesh_high = Vector(map(max, mesh_high, p))
|
||||
low = Vector(map(min, low, mesh_low))
|
||||
high = Vector(map(max, high, mesh_high))
|
||||
normals_ok = all(abs(n.vector.length - 1.0) < 1e-3 for n in mesh.corner_normals)
|
||||
meshes[obj.name] = {
|
||||
'mesh': obj.data.name, 'triangles': triangles(mesh), 'vertices': len(mesh.vertices),
|
||||
'ngons': sum(1 for p in mesh.polygons if len(p.vertices) > 4),
|
||||
'materials': [slot.material.name if slot.material else None for slot in obj.material_slots],
|
||||
'uv_layers': [uv.name for uv in mesh.uv_layers],
|
||||
'color_attributes': [c.name for c in mesh.color_attributes],
|
||||
'active_color': mesh.color_attributes.active_color.name if mesh.color_attributes.active_color else None,
|
||||
'custom_normals': obj.data.has_custom_normals, 'normals_unit_length': normals_ok,
|
||||
'shape_keys': len(obj.data.shape_keys.key_blocks) - 1 if obj.data.shape_keys else 0,
|
||||
'skinned': any(m.type == 'ARMATURE' for m in obj.modifiers),
|
||||
'scale': [round(s, 6) for s in obj.matrix_world.to_scale()],
|
||||
'bounds_unity': {'min': [round(c, 4) for c in mesh_low], 'max': [round(c, 4) for c in mesh_high]},
|
||||
}
|
||||
evaluated.to_mesh_clear()
|
||||
armatures = {}
|
||||
for obj in objects:
|
||||
if obj.type == 'ARMATURE':
|
||||
bones = [b for b in obj.data.bones if b.use_deform]
|
||||
armatures[obj.name] = {'bones': [b.name for b in bones], 'roots': [b.name for b in bones if b.parent is None or not b.parent.use_deform]}
|
||||
empties = {o.name: [round(c, 4) for c in to_unity(o.matrix_world.translation)] for o in objects if o.type == 'EMPTY'}
|
||||
return {'meshes': meshes, 'armatures': armatures, 'empties': empties,
|
||||
'bounds_unity': {'min': [round(c, 4) for c in low], 'max': [round(c, 4) for c in high]} if meshes else None}
|
||||
|
||||
|
||||
def clip_facts(fps):
|
||||
clips = []
|
||||
for action in bpy.data.actions:
|
||||
start, end = action.frame_range
|
||||
clips.append({'name': action.name, 'frames': [round(start, 3), round(end, 3)], 'seconds': round((end - start) / fps, 4),
|
||||
'loop': bool(action.get('loop', action.name in ('idle', 'walk'))),
|
||||
'contact_seconds': float(action.get('contact_seconds', -1.0))})
|
||||
return clips
|
||||
|
||||
|
||||
def godot_to_unity_bounds(bounds):
|
||||
"""Godot/glTF bounds (x, y, z) -> Unity (-x, y, z)."""
|
||||
lo, hi = bounds['min'], bounds['max']
|
||||
return {'min': [-hi[0], lo[1], lo[2]], 'max': [-lo[0], hi[1], hi[2]]}
|
||||
|
||||
|
||||
def run_checks(spec, report, before, clips, expect):
|
||||
scene = bpy.context.scene
|
||||
report.check('units_metric', scene.unit_settings.system == 'METRIC', scene.unit_settings.system)
|
||||
report.check('unit_scale_1', abs(scene.unit_settings.scale_length - 1.0) < 1e-9, scene.unit_settings.scale_length)
|
||||
meshes = before['meshes']
|
||||
bad_scale = {n: m['scale'] for n, m in meshes.items() if any(abs(s - 1.0) > 1e-4 for s in m['scale'])}
|
||||
negative = {n: s for n, s in bad_scale.items() if any(c < 0 for c in s)}
|
||||
report.check('no_negative_scale', not negative, negative)
|
||||
report.check('object_scale_1', not bad_scale or spec.get('rules', {}).get('allow_object_scale', False), bad_scale)
|
||||
names = [m['mesh'] for m in meshes.values()]
|
||||
report.check('mesh_names_unique', len(set(meshes)) == len(meshes), sorted(meshes))
|
||||
empty_slots = {n: m['materials'] for n, m in meshes.items() if None in m['materials'] or not m['materials']}
|
||||
report.check('material_slots_filled', not empty_slots, empty_slots)
|
||||
report.check('normals_unit_length', all(m['normals_unit_length'] for m in meshes.values()),
|
||||
[n for n, m in meshes.items() if not m['normals_unit_length']])
|
||||
# Tangents need UVs and faces with at most four corners; meshes without UVs are shaded
|
||||
# triplanar or unlit and carry no tangents (recorded, not an error).
|
||||
tangent_blockers = {n: m['ngons'] for n, m in meshes.items() if m['uv_layers'] and m['ngons']}
|
||||
report.check('tangent_prerequisites', not tangent_blockers, tangent_blockers)
|
||||
report.data['meshes_without_uv'] = sorted(n for n, m in meshes.items() if not m['uv_layers'])
|
||||
# Blend shapes: none of the sources uses them; Unity imports them only when they exist.
|
||||
shapes = {n: m['shape_keys'] for n, m in meshes.items() if m['shape_keys']}
|
||||
report.check('no_blend_shapes', not shapes or spec.get('rules', {}).get('blend_shapes', False), shapes)
|
||||
total = sum(m['triangles'] for m in meshes.values())
|
||||
report.data['triangles'] = total
|
||||
if 'triangles' in expect:
|
||||
report.check('triangles_match_godot', total == expect['triangles'], '%d fbx / %d godot' % (total, expect['triangles']))
|
||||
if 'nodes' in expect:
|
||||
report.check('mesh_names_match_godot', sorted(meshes) == sorted(expect['nodes']), sorted(set(meshes) ^ set(expect['nodes'])))
|
||||
if 'parts' in expect and spec.get('rules', {}).get('check_parts', True):
|
||||
report.check('mesh_names_match_godot', sorted(meshes) == sorted(expect['parts']), sorted(set(meshes) ^ set(expect['parts']))[:12])
|
||||
if 'materials' in expect:
|
||||
used = sorted({name for m in meshes.values() for name in m['materials'] if name})
|
||||
report.check('materials_match_godot', used == sorted(expect['materials']), sorted(set(used) ^ set(expect['materials'])))
|
||||
if expect.get('bounds_godot') and before['bounds_unity']:
|
||||
# The Godot manifests measure the intact model (towers: without damaged upper part,
|
||||
# debris, ruin and cloth); bounds_exclude names those parts.
|
||||
exclude = tuple(spec.get('rules', {}).get('bounds_exclude', ()))
|
||||
chosen = [m['bounds_unity'] for n, m in meshes.items() if not (exclude and n.startswith(exclude))]
|
||||
got = {'min': [min(b['min'][i] for b in chosen) for i in range(3)], 'max': [max(b['max'][i] for b in chosen) for i in range(3)]}
|
||||
want = godot_to_unity_bounds(expect['bounds_godot'])
|
||||
worst = max(abs(a - b) for key in ('min', 'max') for a, b in zip(got[key], want[key]))
|
||||
report.check('bounds_match_godot', worst < 2e-3, 'largest difference %.5f m' % worst)
|
||||
armatures = before['armatures']
|
||||
if spec['kind'] == 'skinned':
|
||||
report.check('one_armature', len(armatures) == 1, sorted(armatures))
|
||||
for name, arm in armatures.items():
|
||||
report.check('single_root_bone', len(arm['roots']) == 1, arm['roots'])
|
||||
want_root = spec.get('rules', {}).get('root_bone', 'Root')
|
||||
report.check('root_bone_name', arm['roots'] == [want_root], arm['roots'])
|
||||
if 'bone_names' in expect:
|
||||
report.check('bone_names_match_godot', sorted(arm['bones']) == sorted(expect['bone_names']), sorted(set(arm['bones']) ^ set(expect['bone_names'])))
|
||||
if 'bones' in expect:
|
||||
report.check('bone_count_match_godot', len(arm['bones']) == expect['bones'], '%d / %d' % (len(arm['bones']), expect['bones']))
|
||||
bad = [b for b in arm['bones'] if not b.replace('.', '').replace('_', '').isalnum()]
|
||||
report.check('bone_names_portable', not bad, bad)
|
||||
report.check('skinned_meshes_present', any(m['skinned'] for m in meshes.values()), '')
|
||||
names = sorted(c['name'] for c in clips)
|
||||
if 'clips' in expect:
|
||||
report.check('clips_match_godot', names == sorted(expect['clips']), sorted(set(names) ^ set(expect['clips'])))
|
||||
required = spec.get('rules', {}).get('required_clips', [])
|
||||
report.check('required_clips_present', all(c in names for c in required), [c for c in required if c not in names])
|
||||
if 'clip_seconds' in expect:
|
||||
worst = max(abs(c['seconds'] - expect['clip_seconds'][c['name']]) for c in clips if c['name'] in expect['clip_seconds'])
|
||||
report.check('clip_lengths_match_godot', worst < 1e-3, 'largest difference %.4f s' % worst)
|
||||
else:
|
||||
report.check('no_armature', not armatures, sorted(armatures))
|
||||
forward = spec.get('rules', {}).get('forward_marker')
|
||||
if forward:
|
||||
marker = next((p for n, p in before['empties'].items() if n.startswith(forward)), None)
|
||||
report.check('forward_marker_unity_plus_z', marker is not None and marker[2] > 0.1 and abs(marker[0]) < 1e-3, marker)
|
||||
|
||||
|
||||
def reproducible_fbx():
|
||||
"""Byte-identical FBX for identical sources: Blender's FBX writer stamps the current time into
|
||||
the header and derives object ids from Python's string hash. The clock is fixed here; the hash
|
||||
seed comes from PYTHONHASHSEED=0 with --python-use-system-env (tools/blender/export_fbx.sh)."""
|
||||
import datetime
|
||||
import io_scene_fbx.export_fbx_bin as writer
|
||||
|
||||
class FixedClock(datetime.datetime):
|
||||
@classmethod
|
||||
def now(cls, tz=None):
|
||||
return cls(2026, 1, 1, 0, 0, 0)
|
||||
|
||||
class Clock:
|
||||
datetime = FixedClock
|
||||
|
||||
writer.datetime = Clock
|
||||
|
||||
|
||||
def export_fbx(path, objects):
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for obj in objects:
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = objects[0]
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
bpy.ops.export_scene.fbx(filepath=str(path), **FBX_SETTINGS)
|
||||
|
||||
|
||||
def round_trip(path, spec, report, before, clips):
|
||||
"""Imports the written FBX into an empty file and compares names and counts."""
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
bpy.ops.import_scene.fbx(filepath=str(path), use_custom_normals=True, use_anim=True, automatic_bone_orientation=False)
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
imported = [o for o in bpy.context.scene.objects]
|
||||
meshes = {o.name: o for o in imported if o.type == 'MESH'}
|
||||
report.check('roundtrip_mesh_names', sorted(meshes) == sorted(before['meshes']), sorted(set(meshes) ^ set(before['meshes'])))
|
||||
tri = 0
|
||||
for obj in meshes.values():
|
||||
evaluated, mesh = evaluated_mesh(obj, depsgraph)
|
||||
tri += triangles(mesh)
|
||||
evaluated.to_mesh_clear()
|
||||
report.check('roundtrip_triangles', tri == report.data['triangles'], '%d / %d' % (tri, report.data['triangles']))
|
||||
materials = sorted({s.material.name for o in meshes.values() for s in o.material_slots if s.material})
|
||||
want = sorted({name for m in before['meshes'].values() for name in m['materials'] if name})
|
||||
report.check('roundtrip_materials', materials == want, sorted(set(materials) ^ set(want)))
|
||||
if spec['kind'] == 'skinned':
|
||||
arm = next(o for o in imported if o.type == 'ARMATURE')
|
||||
bones = sorted(b.name for b in arm.data.bones)
|
||||
want_bones = sorted(next(iter(before['armatures'].values()))['bones'])
|
||||
report.check('roundtrip_bones', bones == want_bones, sorted(set(bones) ^ set(want_bones)))
|
||||
takes = sorted(a.name.split('|')[-1] for a in bpy.data.actions)
|
||||
report.check('roundtrip_clips', takes == sorted(c['name'] for c in clips), takes)
|
||||
|
||||
|
||||
def export_asset(spec, godot_root):
|
||||
report = Report(spec)
|
||||
source = godot_root / spec['source']
|
||||
bpy.ops.wm.open_mainfile(filepath=str(source))
|
||||
report.data['source_sha256'] = hashlib.sha256(source.read_bytes()).hexdigest()
|
||||
expect = godot_expectations(spec, godot_root)
|
||||
fps = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base
|
||||
prepare(spec, report)
|
||||
objects = export_objects(spec)
|
||||
# Facts of the bind pose (rest), like the Godot manifests; the animation bake needs POSE again.
|
||||
armatures = [o for o in objects if o.type == 'ARMATURE']
|
||||
for arm in armatures:
|
||||
arm.data.pose_position = 'REST'
|
||||
bpy.context.view_layer.update()
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
before = facts(objects, depsgraph)
|
||||
for arm in armatures:
|
||||
arm.data.pose_position = 'POSE'
|
||||
bpy.context.view_layer.update()
|
||||
clips = clip_facts(fps) if spec['kind'] == 'skinned' else []
|
||||
report.data.update({'kind': spec['kind'], 'fps': fps, 'objects': len(objects), 'meshes': before['meshes'], 'armatures': before['armatures'],
|
||||
'empties': before['empties'], 'bounds_unity': before['bounds_unity'], 'clips': clips,
|
||||
'expected_from_godot': {k: expect[k] for k in ('triangles', 'bounds_godot', 'bones', 'clips', 'resource_path') if k in expect}})
|
||||
run_checks(spec, report, before, clips, expect)
|
||||
out = UNITY_ROOT / 'Assets/Luneraria/Art' / spec['group'] / (spec['id'] + '.fbx')
|
||||
export_fbx(out, objects)
|
||||
report.data['fbx'] = str(out.relative_to(UNITY_ROOT))
|
||||
report.data['fbx_bytes'] = out.stat().st_size
|
||||
round_trip(out, spec, report, before, clips)
|
||||
report.data['ok'] = report.ok
|
||||
(out.with_suffix('.export.json')).write_text(json.dumps(report.data, indent=1) + '\n')
|
||||
failed = [c for c in report.data['checks'] if not c['ok']]
|
||||
print('LUNE_EXPORT %s %s: %d checks, %d failed%s' % ('OK' if not failed else 'FAIL', spec['id'], len(report.data['checks']), len(failed),
|
||||
''.join('\n FAIL %s: %s' % (c['check'], c['detail']) for c in failed)))
|
||||
return report.ok
|
||||
|
||||
|
||||
def main():
|
||||
reproducible_fbx()
|
||||
options = args()
|
||||
manifest = json.loads(Path(options['manifest']).read_text())
|
||||
godot_root = Path(options['godot']).resolve()
|
||||
wanted = [i for i in options['ids'].split(',') if i]
|
||||
specs = [s for s in manifest['assets'] if not wanted or s['id'] in wanted]
|
||||
missing = set(wanted) - {s['id'] for s in specs}
|
||||
ok = not missing
|
||||
if missing:
|
||||
print('LUNE_EXPORT FAIL unknown ids', sorted(missing))
|
||||
for spec in specs:
|
||||
try:
|
||||
ok = export_asset(spec, godot_root) and ok
|
||||
except Exception as error: # a broken asset must not stop the batch
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
print('LUNE_EXPORT FAIL %s: %s' % (spec['id'], error))
|
||||
ok = False
|
||||
print('LUNE_EXPORT_DONE ok=%s assets=%d' % (ok, len(specs)))
|
||||
sys.exit(0 if ok else 1)
|
||||
|
||||
|
||||
main()
|
||||