+Add : Simple floating label & font

This commit is contained in:
Ferlat Thibaud
2026-03-25 19:52:15 +01:00
parent 3467886a8a
commit f1d06c7b87
54 changed files with 11395 additions and 424 deletions
@@ -8,3 +8,6 @@ c5ffa67b650768b48a1dfee14cde0434 RobotHolo5.fbx
9c7ca22fec5fc2346ba0334a486cab7e Chungus.fbx 9c7ca22fec5fc2346ba0334a486cab7e Chungus.fbx
0aeae8387e5b14d4bac920f0def12124 Robot_Animation_013.fbx 0aeae8387e5b14d4bac920f0def12124 Robot_Animation_013.fbx
2e9f82ecbb3dd7540a6bcaf166140266 Robot_Animation_013.fbx 2e9f82ecbb3dd7540a6bcaf166140266 Robot_Animation_013.fbx
a117ffd897689164e9b74b1b8b10f644 Diapason.fbx
c1945069c65686a48a85348ceba705d4 arms.fbx
5fd19d2221bd83b45bbf93526c6b203e SpiralStairs.fbx
@@ -1,8 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a26b05d43b978ff47ae3a92b33d85574 guid: 44e55b2c78b1ebd4c943f221649c0512
NativeFormatImporter: folderAsset: yes
DefaultImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 2100000
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
@@ -1,137 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-9117709120641243210
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: column
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
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: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
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}
- 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:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -1,137 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: railing
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
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: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
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}
- 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:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
--- !u!114 &778862498368873942
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
@@ -1,137 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-1839528334568172394
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: stairs
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
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: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
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}
- 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:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 388a82029b37fbf48aebca3087e3bad6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d48fca45cfc64af48aa4308a01e231ad
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c36a602318957f9439df9cc07ff45521
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 02687631db8c07d44996a68548b9aefb guid: fe5a29ea836fa14488a4c431b83a59ec
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3638aa82715aa0c45ab160d2e25e2dfd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: d3211c627be47a9499c1aa33fadf1c8c guid: d8e3f3d5cc4dcef47bf4187c4f6aa58f
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e28ced1006dd2fa4f856444cd615e8f2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ab83a96a74a3637429bd26996b09a57a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2d27820539fd76a4fa85ce4e3e3e8a5a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8353dc0bafe627446b6917f757084c02
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ba6950fe95f51164b915f999037f3c7c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -104,7 +104,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: a1fe462730ebdae488f89f5868a4c74c, type: 3} m_Script: {fileID: 11500000, guid: a1fe462730ebdae488f89f5868a4c74c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Core.Interaction.ObjectDescriptionTrigger m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Core.Interaction.ObjectDescriptionTrigger
_descriptionTextLocalized: {fileID: 0} _descriptionTextLocalized: {fileID: 11400000, guid: 8f44c824f79dd5c4c9296d9ab04f2af1, type: 2}
_descriptionText: 'chair ? ' _descriptionText: 'chair ? '
_settings: {fileID: 11400000, guid: fee419f396620dc478da35ec057d6830, type: 2} _settings: {fileID: 11400000, guid: fee419f396620dc478da35ec057d6830, type: 2}
_raycastDistance: 100 _raycastDistance: 100
@@ -0,0 +1,21 @@
%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: cbde7b14ca8fbf24c917c47aa3c51676, type: 3}
m_Name: text_chair_A__descriptionTextLocalized
m_EditorClassIdentifier: OctoCore.Runtime::OctoCore.Localization.OctoLocalizedTextData
Languages:
_keys:
- English
- French
_values:
- Chair ?
- 'Chaise ? '
@@ -1,8 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: db02b4e9b007dc04b8610ecf4e8da230 guid: 8f44c824f79dd5c4c9296d9ab04f2af1
NativeFormatImporter: NativeFormatImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 2100000 mainObjectFileID: 11400000
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f8674be8125105d4e95cb52d0cbf7384
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0142edfd6e1b952479749b47c1fb613e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -67,8 +67,8 @@ MonoBehaviour:
m_Calls: [] m_Calls: []
m_text: CHOICE m_text: CHOICE
m_isRightToLeft: 0 m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} m_fontAsset: {fileID: 11400000, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_sharedMaterial: {fileID: 2100000, guid: c94e5321bbf1d474e9c598921b1709f0, type: 2} m_sharedMaterial: {fileID: -5327274041433782887, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_fontSharedMaterials: [] m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0} m_fontMaterial: {fileID: 0}
m_fontMaterials: [] m_fontMaterials: []
@@ -100,7 +100,7 @@ MonoBehaviour:
m_fontSizeMax: 72 m_fontSizeMax: 72
m_fontStyle: 0 m_fontStyle: 0
m_HorizontalAlignment: 2 m_HorizontalAlignment: 2
m_VerticalAlignment: 256 m_VerticalAlignment: 512
m_textAlignment: 65535 m_textAlignment: 65535
m_characterSpacing: 0 m_characterSpacing: 0
m_characterHorizontalScale: 1 m_characterHorizontalScale: 1
@@ -0,0 +1,229 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4914436633015142662
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3893100950868132933}
- component: {fileID: 7737385374125659027}
- component: {fileID: 6128282898479855387}
- component: {fileID: 5820989873902797426}
- component: {fileID: 4494761007484843882}
m_Layer: 0
m_Name: FloatingLabel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3893100950868132933
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4914436633015142662}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 5, y: 1}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!23 &7737385374125659027
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4914436633015142662}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: -5327274041433782887, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &6128282898479855387
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4914436633015142662}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Sample text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_sharedMaterial: {fileID: -5327274041433782887, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 4
m_fontSizeBase: 4
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 0
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
_SortingLayer: 0
_SortingLayerID: 0
_SortingOrder: 0
m_hasFontAssetChanged: 0
m_renderer: {fileID: 7737385374125659027}
m_maskType: 0
--- !u!114 &5820989873902797426
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4914436633015142662}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f7a1b2f9cb1305a4993ea145d8106942, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Features.Dialogue.UI.FloatingLabel
_overrideText:
_textComponent: {fileID: 6128282898479855387}
_maxVisibleDistance: 5
_fadeRange: 1
_minDistance: 0.2
_nearFadeRange: 0.8
_enableAdaptiveScale: 1
_referenceDistance: 2.5
_minScaleFactor: 0.5
_maxScaleFactor: 3
_enableOrganicShake: 0
_shakeRadius: 0.05
_shakeSpeed: 1.5
_shakeSmoothness: 2
_enableGhostTrail: 0
_ghostAlpha: 0.3
_ghostDelay: 0.15
_ghostDepthOffset: 0.02
_fadeInDuration: 0.5
_cullCheckInterval: 0.4
--- !u!114 &4494761007484843882
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4914436633015142662}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 222282a8dbdde4d418b8c85126583bf1, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Features.Dialogue.UI.BillboardUI
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 33aceb76d5023f1449962aa926352661
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90041413272d4da47b4bdff9d53b7b86
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cffad0c89422ccd4d8f433260f360d6d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a322405baae7a7642a62ca1b43ed10f6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 748da3ab254fa4b42b9a2efee10cfc82 guid: 3869cf2b20de29941ae6f72f4ea67434
NativeFormatImporter: NativeFormatImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 2100000 mainObjectFileID: 11400000
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7feb38bf07d95284fb9774c14f2fccfd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 27ecc31524c1c704c95a68f8cbb36e17
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- Merchande Print Serif
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -196,6 +196,14 @@ PrefabInstance:
propertyPath: m_LocalPosition.y propertyPath: m_LocalPosition.y
value: 2.79 value: 2.79
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2633624042163943620, guid: 639055b404705a24cb022290319ad5ce, type: 3}
propertyPath: m_LocalPosition.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2633624042163943620, guid: 639055b404705a24cb022290319ad5ce, type: 3}
propertyPath: m_LocalPosition.z
value: -0.251
objectReference: {fileID: 0}
- target: {fileID: 4410329705852039462, guid: 639055b404705a24cb022290319ad5ce, type: 3} - target: {fileID: 4410329705852039462, guid: 639055b404705a24cb022290319ad5ce, type: 3}
propertyPath: m_Size.x propertyPath: m_Size.x
value: 5 value: 5
@@ -252,6 +260,10 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: PlayGround value: PlayGround
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8187987596769813043, guid: 639055b404705a24cb022290319ad5ce, type: 3}
propertyPath: _settings
value:
objectReference: {fileID: 11400000, guid: 5379258b76906ca42b12c1bd312af432, type: 2}
m_RemovedComponents: m_RemovedComponents:
- {fileID: 1168080479735007497, guid: 639055b404705a24cb022290319ad5ce, type: 3} - {fileID: 1168080479735007497, guid: 639055b404705a24cb022290319ad5ce, type: 3}
m_RemovedGameObjects: [] m_RemovedGameObjects: []
@@ -269,6 +281,233 @@ Transform:
m_CorrespondingSourceObject: {fileID: 6410463785956836991, guid: 639055b404705a24cb022290319ad5ce, type: 3} m_CorrespondingSourceObject: {fileID: 6410463785956836991, guid: 639055b404705a24cb022290319ad5ce, type: 3}
m_PrefabInstance: {fileID: 206216246} m_PrefabInstance: {fileID: 206216246}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
--- !u!1 &235141070
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 235141073}
- component: {fileID: 235141072}
- component: {fileID: 235141071}
- component: {fileID: 235141074}
- component: {fileID: 235141075}
m_Layer: 0
m_Name: FloatingLabel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &235141071
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 235141070}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Sample text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_sharedMaterial: {fileID: -5327274041433782887, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 4
m_fontSizeBase: 4
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 0
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
_SortingLayer: 0
_SortingLayerID: 0
_SortingOrder: 0
m_hasFontAssetChanged: 0
m_renderer: {fileID: 235141072}
m_maskType: 0
--- !u!23 &235141072
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 235141070}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: -5327274041433782887, guid: 3869cf2b20de29941ae6f72f4ea67434, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!224 &235141073
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 235141070}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 1.778}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -1.275, y: 1.279}
m_SizeDelta: {x: 5, y: 1}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &235141074
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 235141070}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f7a1b2f9cb1305a4993ea145d8106942, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Features.Dialogue.UI.FloatingLabel
_overrideText:
_textComponent: {fileID: 235141071}
_maxVisibleDistance: 5
_fadeRange: 1
_minDistance: 0.2
_nearFadeRange: 0.8
_enableAdaptiveScale: 1
_referenceDistance: 2.5
_minScaleFactor: 0.5
_maxScaleFactor: 3
_enableOrganicShake: 0
_shakeRadius: 0.05
_shakeSpeed: 1.5
_shakeSmoothness: 2
_enableGhostTrail: 0
_ghostAlpha: 0.3
_ghostDelay: 0.15
_ghostDepthOffset: 0.02
_fadeInDuration: 0.5
_cullCheckInterval: 0.4
--- !u!114 &235141075
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 235141070}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 222282a8dbdde4d418b8c85126583bf1, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Features.Dialogue.UI.BillboardUI
--- !u!1001 &264903928 --- !u!1001 &264903928
PrefabInstance: PrefabInstance:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -893,3 +1132,4 @@ SceneRoots:
- {fileID: 896025416} - {fileID: 896025416}
- {fileID: 924767417} - {fileID: 924767417}
- {fileID: 810547992} - {fileID: 810547992}
- {fileID: 235141073}
@@ -0,0 +1,354 @@
using UnityEngine;
using TMPro;
using System.Collections.Generic;
namespace Unheimlich.Features.Dialogue.UI
{
/// <summary>
/// Non-interactive floating word/phrase for world-space storytelling (thoughts, guidance, atmosphere).
/// Uses TextMeshPro 3D (not Canvas). Designed to sit alongside BillboardUI on the same prefab.
///
/// Features:
/// - Adaptive scale: label always appears the same angular size in the player's camera.
/// - Max distance: fades out progressively when player is far away.
/// - Min distance: label is pushed away from the camera so it never clips into the player's face.
/// - Optional organic shake: label drifts gently around its home position.
/// - Optional ghost trail: a semi-transparent copy follows with a position delay.
/// </summary>
public class FloatingLabel : MonoBehaviour
{
[Header("Text")]
[Tooltip("Leave empty to keep text set directly on the TextMeshPro component.")]
[SerializeField] [TextArea] private string _overrideText;
[SerializeField] private TextMeshPro _textComponent;
[Header("Visibility")]
[Tooltip("Player distance beyond which the label becomes invisible.")]
[SerializeField] private float _maxVisibleDistance = 10f;
[Tooltip("Distance range over which the label fades in/out near the max visibility boundary.")]
[SerializeField] private float _fadeRange = 1.5f;
[Header("Min Distance")]
[Tooltip("When the camera is closer than this, the label slides away to stay readable.")]
[SerializeField] private float _minDistance = 0.5f;
[Tooltip("Distance range over which the label fades out as the player approaches min distance.")]
[SerializeField] private float _nearFadeRange = 0.8f;
[Header("Adaptive Scale")]
[Tooltip("Scale adjusts so the label always appears the same size in the camera view.")]
[SerializeField] private bool _enableAdaptiveScale = true;
[Tooltip("Distance at which the label renders at its Inspector-set scale (1:1 reference).")]
[SerializeField] private float _referenceDistance = 3f;
[Tooltip("Minimum scale multiplier (relative to base scale). Prevents the label from shrinking too much up close.")]
[SerializeField] private float _minScaleFactor = 0.2f;
[Tooltip("Maximum scale multiplier (relative to base scale). Prevents the label from growing too large at a distance.")]
[SerializeField] private float _maxScaleFactor = 3f;
[Header("Organic Shake (Optional)")]
[SerializeField] private bool _enableOrganicShake = false;
[Tooltip("Max drift radius in world units around the home position.")]
[SerializeField] private float _shakeRadius = 0.05f;
[Tooltip("How often a new shake target is picked (per second).")]
[SerializeField] private float _shakeSpeed = 1.5f;
[Tooltip("Higher = smoother drift transition.")]
[SerializeField] private float _shakeSmoothness = 2f;
[Header("Ghost Trail (Optional)")]
[SerializeField] private bool _enableGhostTrail = false;
[Tooltip("Opacity of the ghost copy.")]
[SerializeField] [Range(0f, 1f)] private float _ghostAlpha = 0.3f;
[Tooltip("How many seconds the ghost lags behind the main label.")]
[SerializeField] private float _ghostDelay = 0.15f;
[Tooltip("How far behind the main label the ghost is pushed (along the camera-to-label ray). Ensures the ghost is always occluded by the main word regardless of viewing angle.")]
[SerializeField] private float _ghostDepthOffset = 0.02f;
[Header("Reappear Fade")]
[Tooltip("Duration of the fade-in when the label reappears after being culled.")]
[SerializeField] private float _fadeInDuration = 0.5f;
[Header("Performance")]
[Tooltip("How often (in seconds) distance culling is evaluated. Higher = cheaper but slightly delayed visibility toggle.")]
[SerializeField] private float _cullCheckInterval = 0.4f;
// ── State ──────────────────────────────────────────────────────────────
private Camera _camera;
private Vector3 _homePosition;
private Vector3 _baseScale;
// Culling & fade-in
private bool _isActive = true;
private float _cullTimer;
private float _fadeInAlpha = 1f;
// Shake
private bool _isShaking;
private Vector3 _shakeOffset;
private Vector3 _shakeTarget;
private float _shakeTimer;
// Ghost trail
private TextMeshPro _ghostText;
private Queue<Vector3> _positionHistory = new Queue<Vector3>();
private float _historyTimer;
private const float HISTORY_SAMPLE_RATE = 0.016f;
// ── Unity ──────────────────────────────────────────────────────────────
private void Awake()
{
_camera = Camera.main;
if (_textComponent == null)
_textComponent = GetComponent<TextMeshPro>();
}
private void Start()
{
_homePosition = transform.position;
_baseScale = transform.localScale;
if (_textComponent != null && !string.IsNullOrEmpty(_overrideText))
_textComponent.text = _overrideText;
SetupGhostTrail();
if (_enableOrganicShake)
StartShake();
}
private void Update()
{
if (_camera == null)
{
_camera = Camera.main;
return;
}
// Low-frequency distance cull: skip all logic and disable renderers when out of range.
_cullTimer += Time.deltaTime;
if (_cullTimer >= _cullCheckInterval)
{
_cullTimer = 0f;
bool shouldBeActive = Vector3.Distance(_camera.transform.position, _homePosition)
<= _maxVisibleDistance + _fadeRange;
if (shouldBeActive != _isActive)
{
_isActive = shouldBeActive;
_textComponent.enabled = _isActive;
if (_ghostText != null) _ghostText.enabled = _isActive;
// Reset fade-in so the label doesn't pop in abruptly.
if (_isActive) _fadeInAlpha = 0f;
}
}
if (!_isActive) return;
UpdatePosition();
UpdateVisibility();
UpdateAdaptiveScale();
if (_isShaking)
UpdateShake();
UpdateGhostTrail();
}
// ── Position ───────────────────────────────────────────────────────────
private void UpdatePosition()
{
Vector3 toHome = _homePosition - _camera.transform.position;
float dist = toHome.magnitude;
if (dist < _minDistance && dist > 0.001f)
{
// Push label away so it stays at least _minDistance from the camera.
transform.position = _camera.transform.position + toHome.normalized * _minDistance;
}
else
{
transform.position = _homePosition + _shakeOffset;
}
}
// ── Visibility (distance fade) ─────────────────────────────────────────
private void UpdateVisibility()
{
if (_textComponent == null) return;
if (_fadeInAlpha < 1f)
_fadeInAlpha = Mathf.MoveTowards(_fadeInAlpha, 1f, Time.deltaTime / Mathf.Max(_fadeInDuration, 0.001f));
float dist = Vector3.Distance(_camera.transform.position, _homePosition);
float alpha = ComputeAlpha(dist) * _fadeInAlpha;
SetTextAlpha(_textComponent, alpha);
if (_ghostText != null)
SetTextAlpha(_ghostText, alpha * _ghostAlpha);
}
private float ComputeAlpha(float dist)
{
// Far fade-out
if (dist >= _maxVisibleDistance)
return 0f;
float farFadeStart = _maxVisibleDistance - _fadeRange;
if (dist > farFadeStart && _fadeRange > 0f)
return 1f - (dist - farFadeStart) / _fadeRange;
// Near fade-out
float nearFadeEnd = _minDistance + _nearFadeRange;
if (dist < nearFadeEnd && _nearFadeRange > 0f)
return Mathf.Clamp01((dist - _minDistance) / _nearFadeRange);
return 1f;
}
private static void SetTextAlpha(TextMeshPro text, float alpha)
{
Color c = text.color;
c.a = alpha;
text.color = c;
}
// ── Adaptive Scale ─────────────────────────────────────────────────────
private void UpdateAdaptiveScale()
{
if (!_enableAdaptiveScale) return;
float dist = Vector3.Distance(_camera.transform.position, transform.position);
float scaleFactor = Mathf.Clamp(dist / Mathf.Max(_referenceDistance, 0.001f), _minScaleFactor, _maxScaleFactor);
transform.localScale = _baseScale * scaleFactor;
// Keep ghost in sync — it has its own BillboardUI for rotation but we drive scale here.
if (_ghostText != null)
_ghostText.transform.localScale = transform.localScale;
}
// ── Organic Shake ──────────────────────────────────────────────────────
private Vector3 RandomShakeTarget()
{
// XY only — no depth displacement.
float scaledRadius = _shakeRadius * transform.localScale.x;
Vector2 circle = Random.insideUnitCircle * scaledRadius;
return new Vector3(circle.x, circle.y, 0f);
}
private void StartShake()
{
_isShaking = true;
_shakeTimer = 0f;
_shakeTarget = RandomShakeTarget();
}
private void UpdateShake()
{
_shakeTimer += Time.deltaTime * _shakeSpeed;
if (_shakeTimer >= 1f)
{
_shakeTimer = 0f;
_shakeTarget = RandomShakeTarget();
}
_shakeOffset = Vector3.Lerp(_shakeOffset, _shakeTarget, Time.deltaTime * _shakeSmoothness);
}
// ── Ghost Trail ────────────────────────────────────────────────────────
private void SetupGhostTrail()
{
if (!_enableGhostTrail || _textComponent == null) return;
GameObject ghostObj = new GameObject($"Ghost_{gameObject.name}");
ghostObj.transform.SetParent(transform.parent, false);
ghostObj.transform.position = transform.position;
ghostObj.transform.rotation = transform.rotation;
ghostObj.transform.localScale = transform.localScale;
ghostObj.layer = gameObject.layer;
_ghostText = ghostObj.AddComponent<TextMeshPro>();
_ghostText.font = _textComponent.font;
_ghostText.fontSize = _textComponent.fontSize;
_ghostText.alignment = _textComponent.alignment;
_ghostText.text = _textComponent.text;
_ghostText.color = new Color(
_textComponent.color.r,
_textComponent.color.g,
_textComponent.color.b,
_ghostAlpha
);
// Ghost renderer always sorts behind the main word's renderer.
MeshRenderer mainRenderer = _textComponent.GetComponent<MeshRenderer>();
MeshRenderer ghostRenderer = _ghostText.GetComponent<MeshRenderer>();
if (mainRenderer != null && ghostRenderer != null)
{
ghostRenderer.sortingLayerID = mainRenderer.sortingLayerID;
ghostRenderer.sortingOrder = mainRenderer.sortingOrder - 1;
}
// Ghost must also face the player.
ghostObj.AddComponent<BillboardUI>();
}
private void UpdateGhostTrail()
{
if (!_enableGhostTrail || _ghostText == null) return;
// Sample position history at a fixed rate.
_historyTimer += Time.deltaTime;
if (_historyTimer >= HISTORY_SAMPLE_RATE)
{
_positionHistory.Enqueue(transform.position);
_historyTimer = 0f;
int maxSize = Mathf.CeilToInt(_ghostDelay / HISTORY_SAMPLE_RATE);
while (_positionHistory.Count > maxSize)
_positionHistory.Dequeue();
}
Vector3 ghostPos = _positionHistory.Count > 0
? _positionHistory.Peek()
: transform.position;
// Push ghost along camera forward (away from camera) so it always sits
// behind the main word in depth — stable regardless of viewing angle.
_ghostText.transform.position = ghostPos + _camera.transform.forward * _ghostDepthOffset;
// Keep text content and size in sync.
_ghostText.text = _textComponent.text;
_ghostText.fontSize = _textComponent.fontSize;
}
// ── Public API ─────────────────────────────────────────────────────────
/// <summary>Sets the displayed text at runtime.</summary>
public void SetText(string text)
{
_overrideText = text;
if (_textComponent != null) _textComponent.text = text;
if (_ghostText != null) _ghostText.text = text;
}
/// <summary>Teleports the label's home position without animation.</summary>
public void SetHomePosition(Vector3 worldPos)
{
_homePosition = worldPos;
transform.position = worldPos;
}
#if UNITY_EDITOR
private void OnValidate()
{
if (_textComponent != null && !string.IsNullOrEmpty(_overrideText))
_textComponent.text = _overrideText;
}
#endif
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f7a1b2f9cb1305a4993ea145d8106942