Add Majoras Mask, update gitignore

This commit is contained in:
admin committed 2026-07-07 11:16:43 +02:00
1 parent e0bd0f590b
commit 669b4e1308
25 files changed
+2201 -72

No files matched your search

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 32b6b5219a0c6dd4a8b3836dcd1949f9
guid: 2821a78ea9598164f8f591a2e084ee6e
folderAsset: yes
DefaultImporter:
externalObjects: {}
+297
View File
@@ -0,0 +1,297 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-640132432483307768
MonoBehaviour:
m_ObjectHideFlags: 11
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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
version: 10
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Majoras Mask
m_Shader: {fileID: 4800000, guid: 023c98a32f6cc00478e50479839530c5, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _EMISSION
- _NORMALMAP
m_InvalidKeywords: []
m_LightmapFlags: 2
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 1
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 7876530471615878255, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 8714772487333450258, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 8356977545115736127, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 7876530471615878255, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- anisotropyTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 0, y: 0}
m_Offset: {x: 0, y: 0}
- baseColorTexture:
m_Texture: {fileID: 7876530471615878255, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- clearcoatRoughnessTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 0, y: 0}
m_Offset: {x: 0, y: 0}
- clearcoatTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- emissiveTexture:
m_Texture: {fileID: 8356977545115736127, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- iridescenceTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- iridescenceThicknessTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- metallicRoughnessTexture:
m_Texture: {fileID: -3926687174140238800, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- normalTexture:
m_Texture: {fileID: 8714772487333450258, guid: 8003d65e20f5bf644bdb2a254b8e08dc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- occlusionTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- sheenColorTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- sheenRoughnessTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- specularColorTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- specularTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- thicknessTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- transmissionTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _ANISOTROPY: 0
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _BUILTIN_AlphaClip: 0
- _BUILTIN_Blend: 0
- _BUILTIN_CullMode: 0
- _BUILTIN_DstBlend: 0
- _BUILTIN_QueueControl: 0
- _BUILTIN_QueueOffset: 0
- _BUILTIN_SrcBlend: 1
- _BUILTIN_Surface: 0
- _BUILTIN_ZTest: 4
- _BUILTIN_ZWrite: 1
- _BUILTIN_ZWriteControl: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _CLEARCOAT: 0
- _CastShadows: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 0
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _IRIDESCENCE: 0
- _Metallic: 0
- _NormalMapFormatXYZ: 0
- _OcclusionStrength: 1
- _OverrideSurfaceMode: 0
- _Parallax: 0.005
- _QueueControl: 0
- _QueueOffset: 0
- _ReceiveShadows: 1
- _SHEEN: 0
- _SPECULAR: 0
- _Smoothness: 0.3
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _TEXTURE_TRANSFORM: 0
- _VOLUME_ON: 0
- _VOLUME_TRANSMISSION: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZTest: 4
- _ZWrite: 1
- _ZWriteControl: 0
- alphaCutoff: 0.5
- anisotropyRotation: 0
- anisotropyStrength: 0
- anisotropyTextureRotation: 0
- anisotropyTextureTexCoord: 0
- attenuationDistance: 0.001
- baseColorTextureRotation: 0
- baseColorTextureTexCoord: 0
- clearcoatFactor: 0
- clearcoatRoughnessFactor: 0
- clearcoatRoughnessTextureRotation: 0
- clearcoatRoughnessTextureTexCoord: 0
- clearcoatTextureRotation: 0
- clearcoatTextureTexCoord: 0
- dispersion: 0
- emissiveTextureRotation: 0
- emissiveTextureTexCoord: 0
- ior: 1.5
- iridescenceFactor: 0
- iridescenceIor: 1.3
- iridescenceTextureRotation: 0
- iridescenceTextureTexCoord: 0
- iridescenceThicknessMaximum: 400
- iridescenceThicknessMinimum: 100
- iridescenceThicknessTextureRotation: 0
- iridescenceThicknessTextureTexCoord: 0
- metallicFactor: 1
- metallicRoughnessTextureRotation: 0
- metallicRoughnessTextureTexCoord: 0
- normalScale: 1
- normalTextureRotation: 0
- normalTextureTexCoord: 0
- occlusionStrength: 1
- occlusionTextureRotation: 0
- occlusionTextureTexCoord: 0
- roughnessFactor: 1
- sheenColorTextureRotation: 0
- sheenColorTextureTexCoord: 0
- sheenRoughnessFactor: 0
- sheenRoughnessTextureRotation: 0
- sheenRoughnessTextureTexCoord: 0
- specularColorTextureRotation: 0
- specularColorTextureTexCoord: 0
- specularFactor: 1
- specularTextureRotation: 0
- specularTextureTexCoord: 0
- thicknessFactor: 0
- thicknessTextureRotation: 0
- thicknessTextureTexCoord: 0
- transmissionFactor: 0
- transmissionTextureRotation: 0
- transmissionTextureTexCoord: 0
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 2, g: 2, b: 2, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
- attenuationColor: {r: 1, g: 1, b: 1, a: 0}
- baseColorFactor: {r: 1, g: 1, b: 1, a: 1}
- emissiveFactor: {r: 1, g: 1, b: 1, a: 0}
- sheenColorFactor: {r: 0, g: 0, b: 0, a: 0}
- specularColorFactor: {r: 1, g: 1, b: 1, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
--- !u!114 &7479136806524544972
MonoBehaviour:
m_ObjectHideFlags: 11
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: 639247ca83abc874e893eb93af2b5e44, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.ShaderGraph.Editor::UnityEditor.Rendering.BuiltIn.AssetVersion
version: 0
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4f953e23911bb124baa375fe59062a36
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -1,6 +1,5 @@
fileFormatVersion: 2
guid: 71199395ed0c33b4084dffba4b470de4
folderAsset: yes
guid: 8003d65e20f5bf644bdb2a254b8e08dc
DefaultImporter:
externalObjects: {}
userData:
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: ad1fb2c62db69df46b2fd7857497a8eb
Binary file not shown.
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: ee01222a897382e4196db6230b38e589
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 31d2113a2c8b99241a2985c20e1afb97
Binary file not shown.
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 200f3e37d32853044b57825e1fa50378
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 43861f68d3cfa9d4bbc17ba861732b3e
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 220a4b67de45e694ba804e61bcd95122
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+65
View File
@@ -0,0 +1,65 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
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: 9d9a5969691dba845877d0a52b6d9397, type: 3}
m_Name: UnityGLTFSettings
m_EditorClassIdentifier: UnityGLTFScripts::UnityGLTF.GLTFSettings
packageVersion:
shaderStrippingSettings:
stripPassesFromAllShaders: 0
stripPasses: 0
ImportPlugins:
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
ExportPlugins:
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
exportNames: 1
exportFullPath: 0
EditorExportTransformMode: 0
EditorExportFileFormat: 0
useMainCameraVisibility: 1
exportDisabledGameObjects: 0
tryExportTexturesFromDisk: 0
useTextureFileTypeHeuristic: 1
defaultJpegQuality: 90
exportAnimations: 1
bakeAnimationSpeed: 1
uniqueAnimationNames: 0
bakeSkinnedMeshes: 0
blendShapeExportProperties: -1
blendShapeExportSparseAccessors: 1
exportVertexColors: 1
UseCaching: 1
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 26d0c4b037e79dc4eaa8358afb88db79
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:
+74 -58
View File
@@ -14337,63 +14337,6 @@ Transform:
m_Children: []
m_Father: {fileID: 1296216888}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &1809249305
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalPosition.x
value: 8.683
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalPosition.y
value: -0.00000016342725
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalPosition.z
value: 0.664
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalRotation.w
value: 0.94272155
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalRotation.y
value: -0.33358082
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: -38.973
objectReference: {fileID: 0}
- target: {fileID: 1286186539347929011, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1286186539348200367, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
propertyPath: m_Name
value: Vase_Glass Variant
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 9c490d5393576d54cbbc078d985b2f89, type: 3}
--- !u!1001 &1829668765
PrefabInstance:
m_ObjectHideFlags: 0
@@ -15227,6 +15170,79 @@ Transform:
m_CorrespondingSourceObject: {fileID: 3995388244679289692, guid: a5ab89115777da74c8c24290450eed85, type: 3}
m_PrefabInstance: {fileID: 2041471715}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &582345192953145291
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalScale.x
value: 1.7955
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalScale.y
value: 1.7955
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalScale.z
value: 1.7955
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalPosition.x
value: 4.29
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalPosition.y
value: 1.148
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalPosition.z
value: 6.28
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalRotation.w
value: 0.6793215
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalRotation.x
value: -0.19627155
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalRotation.y
value: -0.67932117
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalRotation.z
value: -0.1962715
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: -32.23
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: -90
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5743757411501337991, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_ConstrainProportionsScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8267460007001047088, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
propertyPath: m_Name
value: Majoras Mask
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 220a4b67de45e694ba804e61bcd95122, type: 3}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
@@ -15254,7 +15270,7 @@ SceneRoots:
- {fileID: 1102892367}
- {fileID: 749206003}
- {fileID: 1512960396}
- {fileID: 1809249305}
- {fileID: 1152224768}
- {fileID: 464912566}
- {fileID: 664393683}
- {fileID: 582345192953145291}
@@ -0,0 +1,202 @@
using System.Collections.Generic;
using MeshProcess;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
/// <summary>
/// Editor tool that runs V-HACD (approximate convex decomposition via the native <see cref="VHACD"/>
/// plugin) on an environment mesh and bakes the resulting convex hulls into SAVED mesh assets + child
/// MeshCollider GameObjects — the exact same output plumbing as <see cref="ConcealmentColliderBaker"/>,
/// only the decomposition backend differs (V-HACD's voxel solver instead of the surface-clustering
/// heuristic). Tune the decomposition on the sibling <see cref="VHACD"/> component (its m_parameters),
/// then run "Bake VHACD Colliders".
///
/// The hulls are real child GameObjects referencing hull-mesh assets under
/// <c>Assets/Generated/VHACDColliders</c>, so they survive domain reload / play-mode / scene save
/// (unlike an in-memory-only bake).
/// </summary>
[DisallowMultipleComponent]
[RequireComponent(typeof(VHACD))]
public class VHACDColliderBaker : MonoBehaviour
{
[Tooltip("Optional. If empty, the shared mesh of a MeshFilter on this object (or a child) is used.")]
[SerializeField] private Mesh sourceMesh;
[Header("Output")]
[Tooltip("If true, generated colliders inherit the source object's layer. Otherwise 'Collider Layer' is used.")]
[SerializeField] private bool useSourceLayer = true;
[SerializeField] private int colliderLayer;
[SerializeField, HideInInspector] private List<string> generatedAssetPaths = new List<string>();
private const string ContainerName = "VHACDColliders (generated)";
private const string AssetFolder = "Assets/Generated/VHACDColliders";
#if UNITY_EDITOR
[ContextMenu("Bake VHACD Colliders")]
public void Bake()
{
Mesh mesh = sourceMesh;
Transform meshSpace = transform;
if (!mesh)
{
MeshFilter mf = GetComponentInChildren<MeshFilter>();
if (mf && mf.sharedMesh) { mesh = mf.sharedMesh; meshSpace = mf.transform; }
}
if (!mesh)
{
Debug.LogError($"[VHACDColliderBaker] '{name}': no source mesh (assign one or add a MeshFilter).", this);
return;
}
VHACD vhacd = GetComponent<VHACD>();
if (!vhacd) vhacd = gameObject.AddComponent<VHACD>();
Clear(); // remove previous container + assets first
string baseName = ResolveAssetBaseName();
// V-HACD reads mesh.vertices raw => hulls are in the mesh's LOCAL space, so an identity
// container under meshSpace places them correctly (same convention as ConcealmentColliderBaker).
List<Mesh> hulls = vhacd.GenerateConvexMeshes(mesh);
if (hulls == null || hulls.Count == 0)
{
Debug.LogWarning($"[VHACDColliderBaker] '{name}': V-HACD produced no convex hulls.", this);
return;
}
EnsureFolder();
Transform container = new GameObject(ContainerName).transform;
container.SetParent(meshSpace, false);
container.localPosition = Vector3.zero;
container.localRotation = Quaternion.identity;
container.localScale = Vector3.one;
int outLayer = useSourceLayer ? gameObject.layer : colliderLayer;
int made = 0;
for (int i = 0; i < hulls.Count; i++)
{
Mesh cm = hulls[i];
if (!cm || cm.vertexCount < 4) { if (cm) DestroyImmediate(cm); continue; } // convex hull needs >= 4 verts
cm.name = $"{baseName}_{made}";
cm.RecalculateBounds();
string path = $"{AssetFolder}/{baseName}_{made}.asset";
AssetDatabase.CreateAsset(cm, path);
generatedAssetPaths.Add(path);
GameObject go = new GameObject($"hull_{made}");
go.transform.SetParent(container, false);
go.layer = outLayer;
MeshCollider col = go.AddComponent<MeshCollider>();
col.sharedMesh = cm;
col.convex = true;
col.isTrigger = false;
made++;
}
AssetDatabase.SaveAssets();
EditorUtility.SetDirty(this);
EditorSceneManager.MarkSceneDirty(gameObject.scene);
Debug.Log($"[VHACDColliderBaker] '{name}': baked {made} convex collider(s) via V-HACD ({hulls.Count} hull(s) returned). Save the scene to persist.", this);
}
[ContextMenu("Clear Baked Colliders")]
public void Clear()
{
for (int i = 0; i < generatedAssetPaths.Count; i++)
if (!string.IsNullOrEmpty(generatedAssetPaths[i]))
AssetDatabase.DeleteAsset(generatedAssetPaths[i]);
generatedAssetPaths.Clear();
var all = GetComponentsInChildren<Transform>(true);
for (int i = 0; i < all.Length; i++)
if (all[i] && all[i] != transform && all[i].name == ContainerName)
DestroyImmediate(all[i].gameObject);
EditorUtility.SetDirty(this);
if (gameObject.scene.IsValid())
EditorSceneManager.MarkSceneDirty(gameObject.scene);
}
private static void EnsureFolder()
{
if (!AssetDatabase.IsValidFolder("Assets/Generated"))
AssetDatabase.CreateFolder("Assets", "Generated");
if (!AssetDatabase.IsValidFolder(AssetFolder))
AssetDatabase.CreateFolder("Assets/Generated", "VHACDColliders");
}
/// <summary>
/// Readable, deterministic base name for the generated collider-mesh assets:
/// - Prefab stage: "{assetPath without 'Assets/' and '.prefab'}/{path below the prefab root}"
/// - Scene: "{sceneName}/{full hierarchy path from the scene root}"
/// Sanitized to a filesystem-safe token; on collision with a DIFFERENT baker's assets, "_2", "_3", … is appended.
/// </summary>
private string ResolveAssetBaseName()
{
string raw;
PrefabStage stage = PrefabStageUtility.GetPrefabStage(gameObject);
if (stage != null)
{
string ap = stage.assetPath;
if (ap.StartsWith("Assets/")) ap = ap.Substring("Assets/".Length);
if (ap.EndsWith(".prefab")) ap = ap.Substring(0, ap.Length - ".prefab".Length);
// Path below the prefab root — the root's name already lives in the asset path.
string hier = GetHierarchyPath(transform, stage.prefabContentsRoot.transform);
raw = hier.Length == 0 ? ap : ap + "/" + hier;
}
else
{
string scene = string.IsNullOrEmpty(gameObject.scene.name) ? "Untitled" : gameObject.scene.name;
raw = scene + "/" + GetHierarchyPath(transform, null);
}
string baseName = SanitizeFileName(raw);
if (baseName.Length == 0) baseName = "Bake";
// Clear() already removed THIS baker's assets, so a hit here means another baker resolved to the
// same name -> disambiguate. The per-collider "_0" file is the presence marker of a base name.
string candidate = baseName;
for (int dup = 2; System.IO.File.Exists($"{AssetFolder}/{candidate}_0.asset"); dup++)
candidate = $"{baseName}_{dup}";
return candidate;
}
/// <summary>Slash-joined transform names from <paramref name="t"/> up to (but excluding) <paramref name="stopAt"/> (null = up to the root).</summary>
private static string GetHierarchyPath(Transform t, Transform stopAt)
{
var names = new List<string>();
for (Transform cur = t; cur && cur != stopAt; cur = cur.parent)
names.Add(cur.name);
names.Reverse();
return string.Join("/", names);
}
/// <summary>Collapses every run of non-[A-Za-z0-9-] characters to a single '_' and trims leading/trailing '_'.</summary>
private static string SanitizeFileName(string s)
{
var sb = new System.Text.StringBuilder(s.Length);
bool pendingSep = false;
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
bool keep = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-';
if (keep)
{
if (pendingSep && sb.Length > 0) sb.Append('_');
pendingSep = false;
sb.Append(c);
}
else pendingSep = true;
}
return sb.ToString();
}
#endif
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 36b909ac7146cc94c892046dd1dbccc5