Compare commits
2 commits
d14305d804
...
3febdcf021
| Author | SHA1 | Date | |
|---|---|---|---|
| 3febdcf021 | |||
| 362b76ae75 |
21 changed files with 401 additions and 738 deletions
|
|
@ -34,11 +34,6 @@ MonoBehaviour:
|
|||
SourcePrefabToOverride: {fileID: 0}
|
||||
SourceHashToOverride: 0
|
||||
OverridingTargetPrefab: {fileID: 0}
|
||||
- Override: 0
|
||||
Prefab: {fileID: 7720770984308489338, guid: dff852699e2897b4494fcbc7f7e547d6, type: 3}
|
||||
SourcePrefabToOverride: {fileID: 0}
|
||||
SourceHashToOverride: 0
|
||||
OverridingTargetPrefab: {fileID: 0}
|
||||
- Override: 0
|
||||
Prefab: {fileID: 2664719039363295382, guid: dc2e4a4108e03874a8b2dab88dcc8fba, type: 3}
|
||||
SourcePrefabToOverride: {fileID: 0}
|
||||
|
|
@ -99,3 +94,8 @@ MonoBehaviour:
|
|||
SourcePrefabToOverride: {fileID: 0}
|
||||
SourceHashToOverride: 0
|
||||
OverridingTargetPrefab: {fileID: 0}
|
||||
- Override: 0
|
||||
Prefab: {fileID: 7720770984308489338, guid: dff852699e2897b4494fcbc7f7e547d6, type: 3}
|
||||
SourcePrefabToOverride: {fileID: 0}
|
||||
SourceHashToOverride: 0
|
||||
OverridingTargetPrefab: {fileID: 0}
|
||||
|
|
|
|||
|
|
@ -1,117 +1,5 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2381228775386571742
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2082013748313019226}
|
||||
- component: {fileID: 7119837420184958461}
|
||||
- component: {fileID: 8833246162440246558}
|
||||
- component: {fileID: 1909402251021719060}
|
||||
m_Layer: 0
|
||||
m_Name: Scale Target
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &2082013748313019226
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2381228775386571742}
|
||||
serializedVersion: 2
|
||||
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: 1531733800731892084}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &7119837420184958461
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2381228775386571742}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &8833246162440246558
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2381228775386571742}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
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: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!65 &1909402251021719060
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2381228775386571742}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 1, y: 1, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &4243270647055755528
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -250,7 +138,6 @@ Transform:
|
|||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 2082013748313019226}
|
||||
- {fileID: 1059634071631389929}
|
||||
- {fileID: 3705223059275757242}
|
||||
m_Father: {fileID: 0}
|
||||
|
|
@ -294,14 +181,10 @@ MonoBehaviour:
|
|||
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.BuildSiteVisual
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
tintedRenderers: []
|
||||
scaleTarget: {fileID: 2082013748313019226}
|
||||
queuedMaterial: {fileID: 2100000, guid: f8d951a6841d3f74098bb31255379774, type: 2}
|
||||
constructingMaterial: {fileID: 2100000, guid: 88f1dd7b174716645953857b38fb6948, type: 2}
|
||||
pausedMaterial: {fileID: 0}
|
||||
defaultPhaseSet: {fileID: 11400000, guid: ed951755c09d6d0479b4fd924b6915da, type: 2}
|
||||
dropReticlePrefab: {fileID: 4110617398237858862, guid: f2a37509f5f2e4d4e86cdaf12f99c6c4, type: 3}
|
||||
stageCount: 4
|
||||
queuedYScale: 0.15
|
||||
--- !u!65 &6259437393614329336
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 82e418e7a5a804747a9a4865648b7793
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
%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: c8f2a4e1b9d6437052a1e8c4f7b3d069, type: 3}
|
||||
m_Name: DefaultConstructionSet
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Towers.ConstructionPhaseSet
|
||||
phases:
|
||||
- {fileID: 562891720401665892, guid: e7be86c29087e99439507b508425b612, type: 3}
|
||||
- {fileID: 3284400382278582069, guid: c6dabc822d0afb746adc08fb8602c2b4, type: 3}
|
||||
- {fileID: 2161157853692362223, guid: d00c71c0cfc7e8744b9f8c1d48c2d256, type: 3}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ed951755c09d6d0479b4fd924b6915da
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &562891720401665892
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5433206400477731590}
|
||||
- component: {fileID: 3041202948021905482}
|
||||
- component: {fileID: 2318454595080774531}
|
||||
- component: {fileID: 2971339723339766249}
|
||||
m_Layer: 0
|
||||
m_Name: DefaultConstruction_Phase_1
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &5433206400477731590
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 562891720401665892}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 0.1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &3041202948021905482
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 562891720401665892}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &2318454595080774531
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 562891720401665892}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
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: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!65 &2971339723339766249
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 562891720401665892}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 1, y: 1, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e7be86c29087e99439507b508425b612
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3284400382278582069
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3820746952356246079}
|
||||
- component: {fileID: 3350984935134180217}
|
||||
- component: {fileID: 6336690892943026752}
|
||||
- component: {fileID: 2003287843732108245}
|
||||
m_Layer: 0
|
||||
m_Name: DefaultConstruction_Phase_2
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3820746952356246079
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3284400382278582069}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1.5, y: 0.5, z: 1.5}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &3350984935134180217
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3284400382278582069}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &6336690892943026752
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3284400382278582069}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
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: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!65 &2003287843732108245
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3284400382278582069}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 1, y: 1, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c6dabc822d0afb746adc08fb8602c2b4
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2161157853692362223
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6591719589271492770}
|
||||
- component: {fileID: 3693505870455731207}
|
||||
- component: {fileID: 2366594505425509977}
|
||||
- component: {fileID: 5474707419433840976}
|
||||
m_Layer: 0
|
||||
m_Name: DefaultConstruction_Phase_3
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &6591719589271492770
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2161157853692362223}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1.75, y: 1, z: 1.75}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &3693505870455731207
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2161157853692362223}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &2366594505425509977
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2161157853692362223}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
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: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!65 &5474707419433840976
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2161157853692362223}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 1, y: 1, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d00c71c0cfc7e8744b9f8c1d48c2d256
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -70,6 +70,8 @@ GameObject:
|
|||
- component: {fileID: 805962841523123163}
|
||||
- component: {fileID: 8853488620519990682}
|
||||
- component: {fileID: 5360241685303413177}
|
||||
- component: {fileID: 5793816278935258120}
|
||||
- component: {fileID: 3412005213656160288}
|
||||
m_Layer: 0
|
||||
m_Name: Tower_BasicArrow
|
||||
m_TagString: Untagged
|
||||
|
|
@ -212,6 +214,8 @@ MonoBehaviour:
|
|||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
tintedRenderers:
|
||||
- {fileID: 4028055828417179692}
|
||||
dropHeight: 15
|
||||
landingDuration: 0.4
|
||||
--- !u!114 &805962841523123163
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -252,12 +256,67 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 93bc533262394e1e8b122bbfad89391a, type: 3}
|
||||
m_Name:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Visuals.ConeMesh
|
||||
sides: 4
|
||||
radius: 0.7071068
|
||||
height: 1.5
|
||||
angularOffsetDegrees: 45
|
||||
--- !u!114 &5793816278935258120
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6482414459531823157}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 22d67b2aa780d786a93acfe06d1909b0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerLandedSound
|
||||
landedSound:
|
||||
clip: {fileID: 0}
|
||||
volume: 0
|
||||
minPitch: 0
|
||||
maxPitch: 0
|
||||
--- !u!114 &3412005213656160288
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6482414459531823157}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bf337521317d9e297a652e97c666376f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerLandingVisual
|
||||
fallCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
impactVfxPrefab: {fileID: 0}
|
||||
impactVfxLifetime: 3
|
||||
--- !u!1 &7580197837852108944
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ GameObject:
|
|||
- component: {fileID: 9137031893466587143}
|
||||
- component: {fileID: 805962841523123163}
|
||||
- component: {fileID: 8853488620519990682}
|
||||
- component: {fileID: 3021373172845454683}
|
||||
- component: {fileID: 4003901452716391977}
|
||||
m_Layer: 0
|
||||
m_Name: Tower_SiegeCannon
|
||||
m_TagString: Untagged
|
||||
|
|
@ -181,9 +183,9 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||
GlobalObjectIdHash: 3344551122
|
||||
GlobalObjectIdHash: 2153184693
|
||||
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||
DeferredDespawnTick: 0
|
||||
Ownership: 1
|
||||
|
|
@ -206,11 +208,13 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fb111fc88b3d6a340a3abde5a1502af3, type: 3}
|
||||
m_Name:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.TowerInstance
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
tintedRenderers:
|
||||
- {fileID: 4028055828417179692}
|
||||
dropHeight: 15
|
||||
landingDuration: 0.4
|
||||
--- !u!114 &805962841523123163
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -221,7 +225,7 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7eb6cce6cd96b23478b7d2173cebf74d, type: 3}
|
||||
m_Name:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerCombat
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
enemyLayerMask:
|
||||
|
|
@ -237,10 +241,65 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c0edb0c5206ca454bbd7c300c6cc7574, type: 3}
|
||||
m_Name:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerRangeIndicator
|
||||
rangeProjector: {fileID: 8255517343120954594}
|
||||
projectionDepth: 50
|
||||
--- !u!114 &3021373172845454683
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6482414459531823157}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 22d67b2aa780d786a93acfe06d1909b0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerLandedSound
|
||||
landedSound:
|
||||
clip: {fileID: 0}
|
||||
volume: 0
|
||||
minPitch: 0
|
||||
maxPitch: 0
|
||||
--- !u!114 &4003901452716391977
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6482414459531823157}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bf337521317d9e297a652e97c666376f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerLandingVisual
|
||||
fallCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
impactVfxPrefab: {fileID: 0}
|
||||
impactVfxLifetime: 3
|
||||
--- !u!1 &7580197837852108944
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -283,7 +342,7 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0777d029ed3dffa4692f417d4aba19ca, type: 3}
|
||||
m_Name:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.DecalProjector
|
||||
m_Material: {fileID: 2100000, guid: f99227cbde481ce47a2527e6bca709d2, type: 2}
|
||||
m_DrawDistance: 1000
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ GameObject:
|
|||
- component: {fileID: 4524938955752569428}
|
||||
- component: {fileID: -2590971686077483651}
|
||||
- component: {fileID: 1288485127287735786}
|
||||
- component: {fileID: 1829137298732744432}
|
||||
- component: {fileID: 8125712573731754244}
|
||||
m_Layer: 0
|
||||
m_Name: Tower_TeslaCoil
|
||||
m_TagString: Untagged
|
||||
|
|
@ -147,7 +149,7 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||
GlobalObjectIdHash: 280718094
|
||||
GlobalObjectIdHash: 1363936954
|
||||
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||
DeferredDespawnTick: 0
|
||||
Ownership: 1
|
||||
|
|
@ -175,6 +177,8 @@ MonoBehaviour:
|
|||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
tintedRenderers:
|
||||
- {fileID: 0}
|
||||
dropHeight: 15
|
||||
landingDuration: 0.4
|
||||
--- !u!114 &805962841523123163
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -268,6 +272,61 @@ MonoBehaviour:
|
|||
volume: 0.496
|
||||
minPitch: 1
|
||||
maxPitch: 1
|
||||
--- !u!114 &1829137298732744432
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6482414459531823157}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 22d67b2aa780d786a93acfe06d1909b0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerLandedSound
|
||||
landedSound:
|
||||
clip: {fileID: 0}
|
||||
volume: 0
|
||||
minPitch: 0
|
||||
maxPitch: 0
|
||||
--- !u!114 &8125712573731754244
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6482414459531823157}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bf337521317d9e297a652e97c666376f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerLandingVisual
|
||||
fallCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
impactVfxPrefab: {fileID: 0}
|
||||
impactVfxLifetime: 3
|
||||
--- !u!1 &7101790219931971190
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ namespace TD.Combat
|
|||
// is in range, the tower fires and the timer resets to 1 / AttacksPerSecond.
|
||||
private float attackCooldown;
|
||||
|
||||
// Counts down from towerInstance.LandingDuration, set in OnNetworkSpawn. Combat is
|
||||
// fully inert until it reaches zero, so a tower can't target/fire while its mesh is
|
||||
// still visually falling (TowerLandingVisual). Server-only; independent of whatever
|
||||
// the client-side fall visual is doing to the (possibly shared, on a host) transform.
|
||||
private float landingCooldown;
|
||||
|
||||
// Cached on OnNetworkSpawn — avoids GetComponent every Update.
|
||||
private TowerInstance towerInstance;
|
||||
|
||||
|
|
@ -102,6 +108,7 @@ namespace TD.Combat
|
|||
public override void OnNetworkSpawn()
|
||||
{
|
||||
towerInstance = GetComponent<TowerInstance>();
|
||||
landingCooldown = towerInstance.LandingDuration;
|
||||
replicatedTarget.OnValueChanged += HandleReplicatedTargetChanged;
|
||||
|
||||
// Late-joining clients receive the NV's current value in the initial
|
||||
|
|
@ -128,6 +135,12 @@ namespace TD.Combat
|
|||
{
|
||||
if (!IsServer) return;
|
||||
|
||||
if (landingCooldown > 0f)
|
||||
{
|
||||
landingCooldown -= Time.deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
TowerDefinition def = towerInstance?.Definition;
|
||||
if (def == null || def.Range <= 0f || def.AttacksPerSecond <= 0f) return;
|
||||
|
||||
|
|
|
|||
41
Assets/_Project/Scripts/Combat/TowerLandedSound.cs
Normal file
41
Assets/_Project/Scripts/Combat/TowerLandedSound.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Assets/_Project/Scripts/Combat/TowerLandedSound.cs
|
||||
using TD.Audio;
|
||||
using TD.Gameplay;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TD.Combat
|
||||
{
|
||||
/// <summary>
|
||||
/// Local-only audio for the tower's landing impact. Subscribes to
|
||||
/// <see cref="TowerInstance.OnLandedClient"/> and plays a sound on every peer when the
|
||||
/// tower's fall animation (<see cref="TowerLandingVisual"/>) finishes.
|
||||
/// Attach to any tower prefab and assign its clip in the Inspector.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(TowerInstance))]
|
||||
public class TowerLandedSound : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private SoundConfig landedSound;
|
||||
|
||||
private TowerInstance towerInstance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
towerInstance = GetComponent<TowerInstance>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (towerInstance != null) towerInstance.OnLandedClient += HandleLanded;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (towerInstance != null) towerInstance.OnLandedClient -= HandleLanded;
|
||||
}
|
||||
|
||||
private void HandleLanded()
|
||||
{
|
||||
AudioManager.Instance?.Play(landedSound.clip, AudioCategory.UI, landedSound.RandomPitch(), landedSound.volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/_Project/Scripts/Combat/TowerLandedSound.cs.meta
Normal file
2
Assets/_Project/Scripts/Combat/TowerLandedSound.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 22d67b2aa780d786a93acfe06d1909b0
|
||||
104
Assets/_Project/Scripts/Combat/TowerLandingVisual.cs
Normal file
104
Assets/_Project/Scripts/Combat/TowerLandingVisual.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Assets/_Project/Scripts/Combat/TowerLandingVisual.cs
|
||||
using System.Collections;
|
||||
using TD.Gameplay;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TD.Combat
|
||||
{
|
||||
/// <summary>
|
||||
/// Local-only "falls from the sky and lands" spawn visual. Subscribes to
|
||||
/// <see cref="TowerInstance.OnBuiltClient"/> and, on every client (never on a
|
||||
/// dedicated server, which has no camera to show it to), animates the tower's
|
||||
/// transform down from <see cref="TowerInstance.DropHeight"/> above its already-correct
|
||||
/// resting position over <see cref="TowerInstance.LandingDuration"/> seconds.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>No NetworkTransform involved.</b> Tower prefabs have no NetworkTransform —
|
||||
/// position is a one-shot snapshot sent at spawn. This animation is purely local per
|
||||
/// peer (same pattern as <see cref="TowerBuiltSound"/>'s audio cue); each peer computes
|
||||
/// an identical animation independently from the same replicated landing position and
|
||||
/// the same authored <see cref="TowerInstance.DropHeight"/>/<see cref="TowerInstance.LandingDuration"/>
|
||||
/// values, so no networking is required.</para>
|
||||
///
|
||||
/// <para><b>Safe on a host despite sharing one Transform with server combat logic.</b>
|
||||
/// <see cref="TowerCombat"/> withholds all targeting/attack logic for
|
||||
/// <see cref="TowerInstance.LandingDuration"/> seconds after spawn (see its
|
||||
/// <c>landingCooldown</c> field), so it never reads <c>transform.position</c> while this
|
||||
/// animation is moving it. The two timers start from the same value in the same call
|
||||
/// (<see cref="TowerInstance.OnBuiltClient"/> fires from <c>OnNetworkSpawn</c>), so they
|
||||
/// finish within a frame of each other.</para>
|
||||
///
|
||||
/// <para><b>Root transform, not a child wrapper.</b> Tower prefabs render their mesh
|
||||
/// directly on the root GameObject (no separate "Model" child exists to offset
|
||||
/// instead), so this animates <c>transform.position</c> directly. Footprint/pathing is
|
||||
/// unaffected — <see cref="TowerInstance"/> stamps walkability from its replicated
|
||||
/// anchor tile (grid data), not from <c>transform.position</c>.</para>
|
||||
/// </remarks>
|
||||
[RequireComponent(typeof(TowerInstance))]
|
||||
public class TowerLandingVisual : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Eases the fall over LandingDuration. X = normalized time, Y = normalized " +
|
||||
"fraction of DropHeight already descended (0 = still at drop height, 1 = landed).")]
|
||||
[SerializeField] private AnimationCurve fallCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
|
||||
|
||||
[Tooltip("Optional impact VFX (dust burst, etc.) instantiated at the landing point when " +
|
||||
"the fall finishes. Leave empty for no VFX.")]
|
||||
[SerializeField] private GameObject impactVfxPrefab;
|
||||
|
||||
[Tooltip("Seconds before the instantiated impact VFX is destroyed. Ignored if " +
|
||||
"impactVfxPrefab is unassigned.")]
|
||||
[SerializeField] private float impactVfxLifetime = 3f;
|
||||
|
||||
private TowerInstance towerInstance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
towerInstance = GetComponent<TowerInstance>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (towerInstance != null) towerInstance.OnBuiltClient += HandleBuilt;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (towerInstance != null) towerInstance.OnBuiltClient -= HandleBuilt;
|
||||
}
|
||||
|
||||
private void HandleBuilt()
|
||||
{
|
||||
// Dedicated (non-host) servers have no camera/visuals and must never move the
|
||||
// shared transform. TowerCombat's landing gate is fully independent of this
|
||||
// animation, so skipping it here on a pure server is a harmless no-op.
|
||||
if (!towerInstance.IsClient) return;
|
||||
|
||||
StartCoroutine(AnimateDrop());
|
||||
}
|
||||
|
||||
private IEnumerator AnimateDrop()
|
||||
{
|
||||
Vector3 landedPosition = transform.position; // already correct (SeatOnGround, pre-spawn)
|
||||
float dropHeight = towerInstance.DropHeight;
|
||||
float duration = towerInstance.LandingDuration;
|
||||
|
||||
transform.position = landedPosition + Vector3.up * dropHeight;
|
||||
|
||||
float t = 0f;
|
||||
while (t < duration)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
float u = fallCurve.Evaluate(Mathf.Clamp01(t / duration));
|
||||
transform.position = landedPosition + Vector3.up * dropHeight * (1f - u);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
transform.position = landedPosition; // snap exactly, avoid float drift
|
||||
|
||||
if (impactVfxPrefab != null)
|
||||
Destroy(Instantiate(impactVfxPrefab, landedPosition, Quaternion.identity), impactVfxLifetime);
|
||||
|
||||
towerInstance.ClientNotifyLanded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf337521317d9e297a652e97c666376f
|
||||
|
|
@ -8,15 +8,16 @@ using TD.VFX;
|
|||
namespace TD.Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Visual representation of an in-flight <see cref="BuildJob"/>: the green
|
||||
/// queued ghost, and the staged construction animation (4 stages of growing
|
||||
/// height for the testing cube). One NetworkObject per active job. Despawned
|
||||
/// when the job is cancelled or when the real <see cref="TowerInstance"/>
|
||||
/// takes its place at construction-complete.
|
||||
/// Visual representation of an in-flight <see cref="BuildJob"/>: a static, non-growing
|
||||
/// site marker (color-tinted by stage) plus the ground targeting reticle
|
||||
/// (<see cref="TowerDropReticle"/>) that shrinks as construction progresses. One
|
||||
/// NetworkObject per active job. Despawned when the job is cancelled or when the real
|
||||
/// <see cref="TowerInstance"/> takes its place at construction-complete, at which point
|
||||
/// <c>TowerLandingVisual</c> plays the tower's fall-from-sky arrival.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>Why a separate prefab from TowerInstance.</b> The build-site visual
|
||||
/// has different rendering (transparent green or partial-height cube), no combat,
|
||||
/// has different rendering (translucent green site marker), no combat,
|
||||
/// no grid-stamping (the Builder owns those state transitions), and a much
|
||||
/// shorter lifecycle. Sharing a prefab with TowerInstance would mean adding
|
||||
/// "am I real or a ghost" branching to every TowerInstance code path. Two
|
||||
|
|
@ -27,10 +28,9 @@ namespace TD.Gameplay
|
|||
/// from <c>NetworkManager.ServerTime.TimeAsFloat</c>. Only the server writes;
|
||||
/// clients read.</para>
|
||||
///
|
||||
/// <para><b>Visual model.</b> The prefab inspector points at a re-tinted copy
|
||||
/// of the tower's mesh (the same testing cube). At Stage = Queued, the visual
|
||||
/// is a translucent green cube at full footprint scale but reduced Y. At
|
||||
/// Stage = Constructing, the cube grows in 4 sub-stages over BuildTime.</para>
|
||||
/// <para><b>Visual model.</b> The site marker's material swaps by stage (queued/
|
||||
/// constructing/paused) but never grows or changes shape — construction progress is
|
||||
/// communicated entirely by the reticle shrinking, not by the marker itself.</para>
|
||||
///
|
||||
/// <para><b>No grid stamping here.</b> Walkability and occupancy stamps are
|
||||
/// driven by the Builder (queue-time stamps occupied=true / walkable=true,
|
||||
|
|
@ -48,10 +48,6 @@ namespace TD.Gameplay
|
|||
"MeshRenderer on the prefab. Auto-populated from children if empty.")]
|
||||
[SerializeField] private MeshRenderer[] tintedRenderers;
|
||||
|
||||
[Tooltip("Transform that gets Y-scaled to represent construction progress. " +
|
||||
"Typically the visual mesh's transform. The growth axis is local Y.")]
|
||||
[SerializeField] private Transform scaleTarget;
|
||||
|
||||
[Tooltip("Material applied while the job is Queued (translucent green).")]
|
||||
[SerializeField] private Material queuedMaterial;
|
||||
|
||||
|
|
@ -63,13 +59,6 @@ namespace TD.Gameplay
|
|||
"Suggested: muted/grey-tinted variant of the constructing material.")]
|
||||
[SerializeField] private Material pausedMaterial;
|
||||
|
||||
[Header("Construction phases")]
|
||||
[Tooltip("Project-default construction-stage visuals used when the tower being built " +
|
||||
"doesn't define its own ConstructionPhases. When this (or the tower's set) " +
|
||||
"has phases, the build site swaps between those phase prefabs as it builds. " +
|
||||
"Leave empty to fall back to the legacy cube Y-scale growth below.")]
|
||||
[SerializeField] private ConstructionPhaseSet defaultPhaseSet;
|
||||
|
||||
[Header("Drop reticle FX")]
|
||||
[Tooltip("Optional targeting-reticle effect (ground decal + beam + motes) shown for the " +
|
||||
"life of this build. Spawned as a child on every peer and fed construction " +
|
||||
|
|
@ -77,16 +66,6 @@ namespace TD.Gameplay
|
|||
"this visual at completion/cancel. Leave empty to build with no reticle.")]
|
||||
[SerializeField] private TowerDropReticle dropReticlePrefab;
|
||||
|
||||
[Header("Construction stages (cube fallback)")]
|
||||
[Tooltip("FALLBACK ONLY (no phase set assigned): number of discrete growth stages " +
|
||||
"while constructing. 4 = 1/4 → 2/4 → 3/4 → 4/4 height.")]
|
||||
[SerializeField] private int stageCount = 4;
|
||||
|
||||
[Tooltip("FALLBACK ONLY: Y-scale applied to scaleTarget when Stage == Queued. " +
|
||||
"Visually distinct from any constructing height so the queued ghost reads " +
|
||||
"as 'intent, not progress'.")]
|
||||
[SerializeField] private float queuedYScale = 0.15f;
|
||||
|
||||
// ----- Networked state --------------------------------------------
|
||||
|
||||
// Replicated owner slot for color tinting. Mirrors TowerInstance.
|
||||
|
|
@ -133,7 +112,7 @@ namespace TD.Gameplay
|
|||
readPerm: NetworkVariableReadPermission.Everyone,
|
||||
writePerm: NetworkVariableWritePermission.Server);
|
||||
|
||||
// Current stage. Drives material swap and Y-scale animation.
|
||||
// Current stage. Drives the site marker's material/tint swap.
|
||||
private readonly NetworkVariable<BuildStage> currentStage =
|
||||
new NetworkVariable<BuildStage>(
|
||||
BuildStage.Queued,
|
||||
|
|
@ -244,17 +223,6 @@ namespace TD.Gameplay
|
|||
private int pendingGoldSpent;
|
||||
private bool hasPendingInit;
|
||||
|
||||
// ----- Construction-phase runtime (local, all peers) --------------
|
||||
|
||||
// Resolved on spawn from the tower's ConstructionPhases or the defaultPhaseSet.
|
||||
// When non-null with PhaseCount > 0, the build site swaps between these
|
||||
// instantiated phase prefabs instead of Y-scaling the fallback cube.
|
||||
private ConstructionPhaseSet effectivePhaseSet;
|
||||
private GameObject[] phaseInstances; // one instantiated child per phase
|
||||
private MeshRenderer[][] phaseRenderers; // cached renderers per phase, for tinting
|
||||
private int activePhaseIndex = -1;
|
||||
private bool usePhases;
|
||||
|
||||
// Spawned child targeting-reticle effect (local, all peers). Fed progress in Update;
|
||||
// destroyed automatically with this NetworkObject at completion/cancel.
|
||||
private TowerDropReticle dropReticleInstance;
|
||||
|
|
@ -307,10 +275,6 @@ namespace TD.Gameplay
|
|||
hasPendingInit = false;
|
||||
}
|
||||
|
||||
// Resolve and instantiate the construction-phase visuals (or fall back to the
|
||||
// cube). Depends on towerTypeId, which is replicated by now on every peer.
|
||||
ResolvePhaseSet();
|
||||
|
||||
// Spawn the targeting-reticle FX as a local child. It reads this build site's
|
||||
// replicated progress (fed in Update) and dies with us at completion/cancel.
|
||||
if (dropReticlePrefab != null)
|
||||
|
|
@ -324,7 +288,7 @@ namespace TD.Gameplay
|
|||
currentStage.OnValueChanged += HandleStageChanged;
|
||||
|
||||
// Apply initial visual state based on the (now-replicated) values.
|
||||
ApplyStageVisual(currentStage.Value);
|
||||
ApplyStageMaterialAndTint(currentStage.Value);
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
|
|
@ -376,30 +340,10 @@ namespace TD.Gameplay
|
|||
{
|
||||
// Drive the targeting reticle on every peer, every stage: 0 while Queued
|
||||
// (full-size reticle, awaiting a builder), shrinking while Constructing, frozen
|
||||
// while Paused. Kept before the Constructing early-return so it also animates
|
||||
// the queued/paused states.
|
||||
// while Paused. This is the only per-frame visual effect on the build site —
|
||||
// nothing about the site's mesh grows or changes shape during construction.
|
||||
if (dropReticleInstance != null)
|
||||
dropReticleInstance.SetProgress(ComputeProgressNormalized());
|
||||
|
||||
// While constructing, advance the visual based on server time. Runs on every
|
||||
// peer so visuals stay synchronized. Paused does NOT update — the visual is
|
||||
// frozen at the pause point.
|
||||
if (currentStage.Value != BuildStage.Constructing) return;
|
||||
|
||||
if (usePhases)
|
||||
{
|
||||
int index = PhaseIndexFromProgress();
|
||||
if (index != activePhaseIndex)
|
||||
{
|
||||
ShowPhase(index);
|
||||
// Renderers changed with the swap — re-apply material + owner tint.
|
||||
ApplyStageMaterialAndTint(BuildStage.Constructing);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: smoothly grow the cube's Y-scale through the stages.
|
||||
ApplyYScale(ComputeConstructingYScale());
|
||||
}
|
||||
|
||||
// ----- Server API -------------------------------------------------
|
||||
|
|
@ -522,9 +466,9 @@ namespace TD.Gameplay
|
|||
|
||||
/// <summary>
|
||||
/// Server-only: transitions Constructing → Paused AND writes the new
|
||||
/// accumulated construction time. Y-scale freezes at the level matching
|
||||
/// the accumulated time. After this returns, the visual is fully self-
|
||||
/// describing — it carries enough state to be shelved and later resumed.
|
||||
/// accumulated construction time (freezing the reticle's shrink progress at that
|
||||
/// point). After this returns, the visual is fully self-describing — it carries
|
||||
/// enough state to be shelved and later resumed.
|
||||
/// </summary>
|
||||
public void ServerPauseAndPersistAccumulated(float totalAccumulated)
|
||||
{
|
||||
|
|
@ -542,37 +486,11 @@ namespace TD.Gameplay
|
|||
|
||||
private void HandleStageChanged(BuildStage previous, BuildStage current)
|
||||
{
|
||||
ApplyStageVisual(current);
|
||||
ApplyStageMaterialAndTint(current);
|
||||
}
|
||||
|
||||
private void ApplyStageVisual(BuildStage stage)
|
||||
{
|
||||
if (usePhases)
|
||||
{
|
||||
// Queued shows the first phase; constructing/paused show the phase
|
||||
// matching current progress. ShowPhase repoints tintedRenderers at the
|
||||
// active phase instance, so material + tint are applied AFTER it.
|
||||
int index = stage == BuildStage.Queued ? 0 : PhaseIndexFromProgress();
|
||||
ShowPhase(index);
|
||||
ApplyStageMaterialAndTint(stage);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: legacy cube Y-scale growth (no phase set wired).
|
||||
ApplyStageMaterialAndTint(stage);
|
||||
switch (stage)
|
||||
{
|
||||
case BuildStage.Queued: ApplyYScale(queuedYScale); break;
|
||||
case BuildStage.Constructing: ApplyYScale(ComputeConstructingYScale()); break;
|
||||
// ComputePausedYScale uses accumulatedConstructionTime alone when
|
||||
// constructionStartServerTime is -1 (the pause sentinel).
|
||||
case BuildStage.Paused: ApplyYScale(ComputePausedYScale()); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Applies the stage's material + owner tint to whatever renderers are currently
|
||||
// active — the cube fallback, or the active phase instance's renderers. Paused
|
||||
// falls back to the constructing material if no paused material is assigned.
|
||||
// Applies the stage's material + owner tint to the site marker's renderers.
|
||||
// Paused falls back to the constructing material if no paused material is assigned.
|
||||
private void ApplyStageMaterialAndTint(BuildStage stage)
|
||||
{
|
||||
switch (stage)
|
||||
|
|
@ -591,115 +509,6 @@ namespace TD.Gameplay
|
|||
}
|
||||
}
|
||||
|
||||
// ----- Construction phases ----------------------------------------
|
||||
|
||||
// Resolves the effective phase set (tower's own, else the project default) and
|
||||
// instantiates one inactive child per phase. Sets usePhases=false (cube fallback)
|
||||
// if neither set has any phases. Runs on every peer in OnNetworkSpawn.
|
||||
private void ResolvePhaseSet()
|
||||
{
|
||||
var def = TowerPlacementManager.GetDefinition(towerTypeId.Value);
|
||||
effectivePhaseSet =
|
||||
(def != null && def.ConstructionPhases != null && def.ConstructionPhases.PhaseCount > 0)
|
||||
? def.ConstructionPhases
|
||||
: defaultPhaseSet;
|
||||
|
||||
int n = effectivePhaseSet != null ? effectivePhaseSet.PhaseCount : 0;
|
||||
if (n <= 0)
|
||||
{
|
||||
usePhases = false;
|
||||
return;
|
||||
}
|
||||
|
||||
usePhases = true;
|
||||
phaseInstances = new GameObject[n];
|
||||
phaseRenderers = new MeshRenderer[n][];
|
||||
|
||||
// Hide the legacy fallback cube — the instantiated phase prefabs replace it.
|
||||
if (scaleTarget != null) scaleTarget.gameObject.SetActive(false);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
var prefab = effectivePhaseSet.GetPhase(i);
|
||||
if (prefab == null) continue;
|
||||
|
||||
var go = Instantiate(prefab, transform);
|
||||
go.transform.localPosition = Vector3.zero;
|
||||
go.transform.localRotation = Quaternion.identity;
|
||||
go.SetActive(false);
|
||||
|
||||
phaseInstances[i] = go;
|
||||
phaseRenderers[i] = go.GetComponentsInChildren<MeshRenderer>(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Activates only phase <paramref name="index"/> and points tintedRenderers at its
|
||||
// renderers so the existing material/tint helpers drive the active phase.
|
||||
private void ShowPhase(int index)
|
||||
{
|
||||
if (phaseInstances == null) return;
|
||||
index = Mathf.Clamp(index, 0, phaseInstances.Length - 1);
|
||||
|
||||
for (int i = 0; i < phaseInstances.Length; i++)
|
||||
if (phaseInstances[i] != null)
|
||||
phaseInstances[i].SetActive(i == index);
|
||||
|
||||
activePhaseIndex = index;
|
||||
tintedRenderers = phaseRenderers[index];
|
||||
}
|
||||
|
||||
// Maps current normalized progress to a phase index (0..PhaseCount-1).
|
||||
private int PhaseIndexFromProgress()
|
||||
{
|
||||
int n = effectivePhaseSet != null ? effectivePhaseSet.PhaseCount : 1;
|
||||
if (n <= 1) return 0;
|
||||
float p = ComputeProgressNormalized();
|
||||
return Mathf.Clamp(Mathf.FloorToInt(p * n), 0, n - 1);
|
||||
}
|
||||
|
||||
// Stage index 0..stageCount-1 based on elapsed server time PLUS any accumulated
|
||||
// time from previous Constructing runs (resume support).
|
||||
// Returned Y-scale is (stageIndex + 1) / stageCount, so stage 0 = 1/4,
|
||||
// stage 1 = 2/4, ..., stage stageCount-1 = 4/4 = full height.
|
||||
private float ComputeConstructingYScale()
|
||||
{
|
||||
float bt = buildTime.Value;
|
||||
if (bt <= 0f || stageCount <= 0) return 1f;
|
||||
|
||||
float currentRunElapsed = (float)NetworkManager.Singleton.ServerTime.Time
|
||||
- constructionStartServerTime.Value;
|
||||
float total = currentRunElapsed + accumulatedConstructionTime.Value;
|
||||
|
||||
float perStage = bt / stageCount;
|
||||
int stageIndex = Mathf.Clamp(
|
||||
Mathf.FloorToInt(total / perStage),
|
||||
0, stageCount - 1);
|
||||
|
||||
return (stageIndex + 1f) / stageCount;
|
||||
}
|
||||
|
||||
// While Paused, only the accumulated time matters (no current run is in flight).
|
||||
private float ComputePausedYScale()
|
||||
{
|
||||
float bt = buildTime.Value;
|
||||
if (bt <= 0f || stageCount <= 0) return 1f;
|
||||
|
||||
float total = accumulatedConstructionTime.Value;
|
||||
float perStage = bt / stageCount;
|
||||
int stageIndex = Mathf.Clamp(
|
||||
Mathf.FloorToInt(total / perStage),
|
||||
0, stageCount - 1);
|
||||
|
||||
return (stageIndex + 1f) / stageCount;
|
||||
}
|
||||
|
||||
private void ApplyYScale(float y)
|
||||
{
|
||||
if (scaleTarget == null) return;
|
||||
Vector3 s = scaleTarget.localScale;
|
||||
scaleTarget.localScale = new Vector3(s.x, y, s.z);
|
||||
}
|
||||
|
||||
// ----- Material handling ------------------------------------------
|
||||
|
||||
private void SwapMaterial(Material mat)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,18 @@ namespace TD.Gameplay
|
|||
"to exclude specific children.")]
|
||||
[SerializeField] private MeshRenderer[] tintedRenderers;
|
||||
|
||||
[Header("Landing (post-construction drop)")]
|
||||
[Tooltip("World-unit height the tower visually drops from when construction completes. " +
|
||||
"Consumed only by the client-side fall visual (TowerLandingVisual).")]
|
||||
[SerializeField] private float dropHeight = 15f;
|
||||
|
||||
[Tooltip("Seconds the fall-and-land animation takes. Single source of truth: " +
|
||||
"TowerCombat withholds targeting/attacks for exactly this long " +
|
||||
"(server-authoritative), and TowerLandingVisual uses the same value to time " +
|
||||
"its client-side animation, so the two stay in lockstep without duplicating " +
|
||||
"the number.")]
|
||||
[SerializeField] private float landingDuration = 0.4f;
|
||||
|
||||
// ----- Networked state ------------------------------------------------
|
||||
|
||||
// The TowerTypeId (index into TowerPlacementManager's catalog) for this tower.
|
||||
|
|
@ -132,6 +144,13 @@ namespace TD.Gameplay
|
|||
/// <summary>The footprint anchor tile (SW corner, world-tile coords).</summary>
|
||||
public Vector2Int AnchorTile => anchorTile.Value;
|
||||
|
||||
/// <summary>World-unit height the post-construction drop animation falls from.</summary>
|
||||
public float DropHeight => dropHeight;
|
||||
|
||||
/// <summary>Seconds the drop/land animation takes. Also how long TowerCombat withholds
|
||||
/// targeting/attacks after construction completes.</summary>
|
||||
public float LandingDuration => landingDuration;
|
||||
|
||||
// ----- ISelectable ----------------------------------------------------
|
||||
|
||||
// Absolute world-unit margin that the selection ring extends beyond the
|
||||
|
|
@ -171,6 +190,16 @@ namespace TD.Gameplay
|
|||
/// <summary>Fired on ALL peers when this tower finishes construction and spawns.</summary>
|
||||
public event System.Action OnBuiltClient;
|
||||
|
||||
/// <summary>Fired locally on this peer when the client-side fall/land animation
|
||||
/// finishes (see <see cref="TD.Combat.TowerLandingVisual"/>). Analogous to
|
||||
/// <see cref="OnBuiltClient"/>, but delayed by <see cref="LandingDuration"/>.</summary>
|
||||
public event System.Action OnLandedClient;
|
||||
|
||||
/// <summary>Called by <see cref="TD.Combat.TowerLandingVisual"/> when its local
|
||||
/// fall/land animation finishes. Purely local — never invoked on a dedicated
|
||||
/// (non-client) server, which never runs that animation.</summary>
|
||||
public void ClientNotifyLanded() => OnLandedClient?.Invoke();
|
||||
|
||||
// ----- Server-only initialization -------------------------------------
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue