Adding VFX package, cleaning up texture on terrain slightly, and adding new build FX asset for orbital drop visuals.

This commit is contained in:
Matt F 2026-06-30 22:22:58 -07:00
parent 2fbee5fd99
commit 28b0e2cdf2
24 changed files with 15522 additions and 10 deletions

Binary file not shown.

View file

@ -0,0 +1,321 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &587313432172278041
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3307296712732805768}
- component: {fileID: 6748923292346508847}
- component: {fileID: 2507891176384043687}
m_Layer: 0
m_Name: Cylinder
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3307296712732805768
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 587313432172278041}
serializedVersion: 2
m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0, y: 0, z: 0.5}
m_LocalScale: {x: 0.12, y: 0.5, z: 0.11999997}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5473658900712571368}
m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
--- !u!33 &6748923292346508847
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 587313432172278041}
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &2507891176384043687
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 587313432172278041}
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: 12fa78231d5bf3a4f90e4624b9a6a15f, 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!1 &1864447562612895463
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5785595502933998838}
- component: {fileID: 4110617398237858862}
m_Layer: 0
m_Name: FX_TowerDropReticle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5785595502933998838
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1864447562612895463}
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:
- {fileID: 5473658900712571368}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4110617398237858862
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1864447562612895463}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: baac389882e721248bb426ee40fbf74f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TD.VFX.TowerDropReticle
decal: {fileID: 0}
progressRenderers: []
progressProperty: _Progress
--- !u!1 &2400385455731221705
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5473658900712571368}
- component: {fileID: 2323768173093437429}
m_Layer: 0
m_Name: DecalProjector_TowerDrop
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5473658900712571368
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2400385455731221705}
serializedVersion: 2
m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0, y: -0.003, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3307296712732805768}
- {fileID: 6501670922619832963}
m_Father: {fileID: 5785595502933998838}
m_LocalEulerAnglesHint: {x: -90, y: 0, z: 0}
--- !u!114 &2323768173093437429
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2400385455731221705}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0777d029ed3dffa4692f417d4aba19ca, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.DecalProjector
m_Material: {fileID: 2100000, guid: f794f3140d09f724d924caaf96359b81, type: 2}
m_DrawDistance: 1000
m_FadeScale: 0.9
m_StartAngleFade: 180
m_EndAngleFade: 180
m_UVScale: {x: 1, y: 1}
m_UVBias: {x: 0, y: 0}
m_RenderingLayerMask:
serializedVersion: 0
m_Bits: 1
m_ScaleMode: 0
m_Offset: {x: 0, y: 0, z: 0.5}
m_Size: {x: 2, y: 2, z: 1}
m_FadeFactor: 1
m_VisibleInScene: 1
version: 1
m_DecalLayerMask: 1
--- !u!1 &6154284915429400602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6501670922619832963}
- component: {fileID: 3102875668348154800}
- component: {fileID: 339468895080198894}
m_Layer: 0
m_Name: FX_Motes
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6501670922619832963
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6154284915429400602}
serializedVersion: 2
m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5473658900712571368}
m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
--- !u!2083052967 &3102875668348154800
VisualEffect:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6154284915429400602}
m_Enabled: 1
m_Asset: {fileID: 8926484042661614526, guid: 142a41eb3c31cc3479182408de1b3ffe, type: 3}
m_InitialEventName: OnPlay
m_InitialEventNameOverriden: 0
m_StartSeed: 0
m_ResetSeedOnPlay: 1
m_AllowInstancing: 1
m_ResourceVersion: 1
m_PropertySheet:
m_Float:
m_Array: []
m_Vector2f:
m_Array: []
m_Vector3f:
m_Array: []
m_Vector4f:
m_Array: []
m_Uint:
m_Array: []
m_Int:
m_Array: []
m_Matrix4x4f:
m_Array: []
m_AnimationCurve:
m_Array: []
m_Gradient:
m_Array: []
m_NamedObject:
m_Array: []
m_Bool:
m_Array: []
--- !u!73398921 &339468895080198894
VFXRenderer:
serializedVersion: 1
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6154284915429400602}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_RayTracingMode: 0
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_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

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f2a37509f5f2e4d4e86cdaf12f99c6c4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,67 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-6061037298009385930
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: M_TowerDrop
m_Shader: {fileID: -6465566751694194690, guid: 5a8ebb05602fadb48a72f94a08654006, 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: {}
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- 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:
- _DecalMeshBiasType: 0
- _DecalMeshDepthBias: 0
- _DecalMeshViewBias: 0
- _DrawOrder: 0
- _LineWidth: 0.02
- _Progress: 0
- _QueueControl: 0
- _QueueOffset: 0
- _SpinSpeed: 2
m_Colors:
- _BeamColor: {r: 8, g: 0, b: 0, a: 1}
- _ReticleColor: {r: 8, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f794f3140d09f724d924caaf96359b81
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,60 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-6403437066739920421
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: M_TowerDrop_Beam
m_Shader: {fileID: -6465566751694194690, guid: 3a2790546855e2246ae4341f5b791133, 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: {}
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- 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:
- _FlowSpeed: 5
- _QueueControl: 0
- _QueueOffset: 0
m_Colors:
- _BeamColor: {r: 8, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 12fa78231d5bf3a4f90e4624b9a6a15f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 5a8ebb05602fadb48a72f94a08654006
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
useAsTemplate: 0
exposeTemplateAsShader: 0
template:
name:
category:
description:
icon: {instanceID: 0}
thumbnail: {instanceID: 0}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3a2790546855e2246ae4341f5b791133
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
useAsTemplate: 0
exposeTemplateAsShader: 0
template:
name:
category:
description:
icon: {instanceID: 0}
thumbnail: {instanceID: 0}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 142a41eb3c31cc3479182408de1b3ffe
VisualEffectImporter:
externalObjects: {}
serializedVersion: 2
template:
name:
category:
description:
icon: {instanceID: 0}
thumbnail: {instanceID: 0}
useAsTemplate: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -17,15 +17,17 @@ MonoBehaviour:
ground enemies only. ground enemies only.
FootprintSize: {x: 2, y: 2} FootprintSize: {x: 2, y: 2}
GoldCost: 50 GoldCost: 50
BuildTime: 0.5 BuildTime: 1
TowerPrefab: {fileID: 6482414459531823157, guid: 85ad5cd50543454891b343720f3048d6, type: 3} TowerPrefab: {fileID: 6482414459531823157, guid: 85ad5cd50543454891b343720f3048d6, type: 3}
ConstructionPhases: {fileID: 0}
Icon: {fileID: 21300000, guid: 1423e4bda9704c3b826b0eb847c29c1c, type: 3}
DamageType: 0 DamageType: 0
TargetPriority: 0 TargetPriority: 0
TargetType: 1 TargetType: 1
GroundedOnly: 1 GroundedOnly: 1
Damage: 25 Damage: 25
Range: 16 Range: 16
FireRate: 0.8 AttacksPerSecond: 0
SplashRadius: 3 SplashRadius: 3
ChainCount: 0 ChainCount: 0
ChainRange: 0 ChainRange: 0
@ -35,4 +37,3 @@ MonoBehaviour:
ProjectilePrefab: {fileID: 2664719039363295382, guid: dc2e4a4108e03874a8b2dab88dcc8fba, type: 3} ProjectilePrefab: {fileID: 2664719039363295382, guid: dc2e4a4108e03874a8b2dab88dcc8fba, type: 3}
ProjectileSpeed: 10 ProjectileSpeed: 10
UpgradePaths: [] UpgradePaths: []
Icon: {fileID: 21300000, guid: 1423e4bda9704c3b826b0eb847c29c1c, type: 3}

View file

@ -17,7 +17,7 @@ MonoBehaviour:
Rapid, low per-hit damage; targets ground and air. Rapid, low per-hit damage; targets ground and air.
FootprintSize: {x: 2, y: 2} FootprintSize: {x: 2, y: 2}
GoldCost: 40 GoldCost: 40
BuildTime: 0.5 BuildTime: 2
TowerPrefab: {fileID: 6482414459531823157, guid: 5a9e31f20d023e44dbd1c6d7dcdf4f71, type: 3} TowerPrefab: {fileID: 6482414459531823157, guid: 5a9e31f20d023e44dbd1c6d7dcdf4f71, type: 3}
ConstructionPhases: {fileID: 0} ConstructionPhases: {fileID: 0}
Icon: {fileID: 0} Icon: {fileID: 0}
@ -27,7 +27,7 @@ MonoBehaviour:
GroundedOnly: 0 GroundedOnly: 0
Damage: 5 Damage: 5
Range: 10 Range: 10
FireRate: 2 AttacksPerSecond: 0
SplashRadius: 0 SplashRadius: 0
ChainCount: 0 ChainCount: 0
ChainRange: 0 ChainRange: 0

View file

@ -299,6 +299,7 @@ MonoBehaviour:
constructingMaterial: {fileID: 2100000, guid: 88f1dd7b174716645953857b38fb6948, type: 2} constructingMaterial: {fileID: 2100000, guid: 88f1dd7b174716645953857b38fb6948, type: 2}
pausedMaterial: {fileID: 0} pausedMaterial: {fileID: 0}
defaultPhaseSet: {fileID: 11400000, guid: ed951755c09d6d0479b4fd924b6915da, type: 2} defaultPhaseSet: {fileID: 11400000, guid: ed951755c09d6d0479b4fd924b6915da, type: 2}
dropReticlePrefab: {fileID: 4110617398237858862, guid: f2a37509f5f2e4d4e86cdaf12f99c6c4, type: 3}
stageCount: 4 stageCount: 4
queuedYScale: 0.15 queuedYScale: 0.15
--- !u!65 &6259437393614329336 --- !u!65 &6259437393614329336

View file

@ -3,6 +3,7 @@ using Unity.Netcode;
using UnityEngine; using UnityEngine;
using TD.Core; using TD.Core;
using TD.Towers; using TD.Towers;
using TD.VFX;
namespace TD.Gameplay namespace TD.Gameplay
{ {
@ -69,6 +70,13 @@ namespace TD.Gameplay
"Leave empty to fall back to the legacy cube Y-scale growth below.")] "Leave empty to fall back to the legacy cube Y-scale growth below.")]
[SerializeField] private ConstructionPhaseSet defaultPhaseSet; [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 " +
"progress each frame so it shrinks as the tower builds, then destroyed with " +
"this visual at completion/cancel. Leave empty to build with no reticle.")]
[SerializeField] private TowerDropReticle dropReticlePrefab;
[Header("Construction stages (cube fallback)")] [Header("Construction stages (cube fallback)")]
[Tooltip("FALLBACK ONLY (no phase set assigned): number of discrete growth stages " + [Tooltip("FALLBACK ONLY (no phase set assigned): number of discrete growth stages " +
"while constructing. 4 = 1/4 → 2/4 → 3/4 → 4/4 height.")] "while constructing. 4 = 1/4 → 2/4 → 3/4 → 4/4 height.")]
@ -247,6 +255,10 @@ namespace TD.Gameplay
private int activePhaseIndex = -1; private int activePhaseIndex = -1;
private bool usePhases; 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;
// ----- Lifecycle -------------------------------------------------- // ----- Lifecycle --------------------------------------------------
/// <summary> /// <summary>
@ -299,6 +311,15 @@ namespace TD.Gameplay
// cube). Depends on towerTypeId, which is replicated by now on every peer. // cube). Depends on towerTypeId, which is replicated by now on every peer.
ResolvePhaseSet(); 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)
{
dropReticleInstance = Instantiate(dropReticlePrefab, transform);
dropReticleInstance.transform.localPosition = Vector3.zero;
dropReticleInstance.transform.localRotation = Quaternion.identity;
}
// Subscribe to value changes so visual updates are reactive. // Subscribe to value changes so visual updates are reactive.
currentStage.OnValueChanged += HandleStageChanged; currentStage.OnValueChanged += HandleStageChanged;
@ -353,6 +374,13 @@ namespace TD.Gameplay
private void Update() private void Update()
{ {
// 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.
if (dropReticleInstance != null)
dropReticleInstance.SetProgress(ComputeProgressNormalized());
// While constructing, advance the visual based on server time. Runs on every // While constructing, advance the visual based on server time. Runs on every
// peer so visuals stay synchronized. Paused does NOT update — the visual is // peer so visuals stay synchronized. Paused does NOT update — the visual is
// frozen at the pause point. // frozen at the pause point.

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ba7743153560abe4c8b69fb6e86ec013
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,96 @@
// Assets/_Project/Scripts/VFX/TowerDropReticle.cs
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace TD.VFX
{
/// <summary>
/// Local visual for a tower-drop targeting reticle — the ground decal, the vertical
/// energy beam, and the rising motes, bundled under one root. It is spawned as a child
/// of a <c>BuildSiteVisual</c>, which feeds it construction progress via
/// <see cref="SetProgress"/> each frame. The decal (and optionally the beam) shrink/fade
/// as progress climbs toward 1 through the shader's <c>_Progress</c> property.
/// </summary>
/// <remarks>
/// <para>Pure visualization — no networking. It runs on every peer because the owning
/// <c>BuildSiteVisual</c> spawns on every peer, and it reads the build site's already-
/// replicated progress. It is destroyed automatically when the build site despawns at
/// construction-complete or cancel (it's a child of that NetworkObject).</para>
///
/// <para><b>Per-instance materials.</b> Several towers can build at once, so each reticle
/// needs its own material — a shared material would make every reticle share one
/// <c>_Progress</c> value and shrink in lockstep. The decal's material is cloned here;
/// beam renderers use <see cref="Renderer.material"/>, which auto-instantiates.</para>
/// </remarks>
public class TowerDropReticle : MonoBehaviour
{
[Tooltip("Ground decal projector. Its material's _Progress drives the reticle shrink/fade. " +
"Auto-found in children if left empty.")]
[SerializeField] private DecalProjector decal;
[Tooltip("Optional extra renderers (e.g. the beam) whose material also exposes _Progress " +
"so they fade with construction. Renderers without the property are skipped.")]
[SerializeField] private Renderer[] progressRenderers;
[Tooltip("Shader float property that drives the shrink: 0 = full size, 1 = complete/gone.")]
[SerializeField] private string progressProperty = "_Progress";
private int progressId;
private Material decalMaterialInstance;
private Material[] rendererMaterialInstances;
private void Awake()
{
progressId = Shader.PropertyToID(progressProperty);
if (decal == null) decal = GetComponentInChildren<DecalProjector>();
// Clone the decal material so this reticle animates independently of any other
// build site sharing the same source material asset.
if (decal != null && decal.material != null)
{
decalMaterialInstance = new Material(decal.material);
decal.material = decalMaterialInstance;
}
// Renderer.material returns a per-renderer instance, so these are already unique.
if (progressRenderers != null && progressRenderers.Length > 0)
{
rendererMaterialInstances = new Material[progressRenderers.Length];
for (int i = 0; i < progressRenderers.Length; i++)
if (progressRenderers[i] != null)
rendererMaterialInstances[i] = progressRenderers[i].material;
}
}
/// <summary>
/// Feed normalized construction progress. 0 = build just started (reticle full size);
/// 1 = complete (reticle shrunk away). Safe to call every frame on any peer.
/// </summary>
public void SetProgress(float t01)
{
t01 = Mathf.Clamp01(t01);
if (decalMaterialInstance != null)
decalMaterialInstance.SetFloat(progressId, t01);
if (rendererMaterialInstances != null)
{
for (int i = 0; i < rendererMaterialInstances.Length; i++)
{
var mat = rendererMaterialInstances[i];
if (mat != null && mat.HasProperty(progressId))
mat.SetFloat(progressId, t01);
}
}
}
private void OnDestroy()
{
// The cloned decal material is ours to free. Renderer material instances are
// owned by their renderers and cleaned up when those GameObjects are destroyed.
if (decalMaterialInstance != null)
Destroy(decalMaterialInstance);
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: baac389882e721248bb426ee40fbf74f

View file

@ -20,6 +20,7 @@
"com.unity.toolchain.linux-x86_64-linux": "1.1.0", "com.unity.toolchain.linux-x86_64-linux": "1.1.0",
"com.unity.toolchain.win-x86_64-linux": "1.0.2", "com.unity.toolchain.win-x86_64-linux": "1.0.2",
"com.unity.ugui": "2.0.0", "com.unity.ugui": "2.0.0",
"com.unity.visualeffectgraph": "17.4.0",
"com.unity.modules.accessibility": "1.0.0", "com.unity.modules.accessibility": "1.0.0",
"com.unity.modules.adaptiveperformance": "1.0.0", "com.unity.modules.adaptiveperformance": "1.0.0",
"com.unity.modules.ai": "1.0.0", "com.unity.modules.ai": "1.0.0",

View file

@ -441,6 +441,15 @@
"com.unity.modules.imgui": "1.0.0" "com.unity.modules.imgui": "1.0.0"
} }
}, },
"com.unity.visualeffectgraph": {
"version": "17.4.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.shadergraph": "17.4.0",
"com.unity.render-pipelines.core": "17.4.0"
}
},
"com.unity.modules.accessibility": { "com.unity.modules.accessibility": {
"version": "1.0.0", "version": "1.0.0",
"depth": 0, "depth": 0,

View file

@ -109,23 +109,43 @@
{ {
"type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.LastSize.Cube", "key": "ShapeBuilder.LastSize.Cube",
"value": "{\"m_Value\":{\"x\":5.5,\"y\":3.0,\"z\":-2.5}}" "value": "{\"m_Value\":{\"x\":-0.8617095947265625,\"y\":1.0079753398895264,\"z\":3.049813747406006}}"
},
{
"type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.LastSize.Stairs",
"value": "{\"m_Value\":{\"x\":-2.007598876953125,\"y\":2.0233278274536135,\"z\":2.0208892822265627}}"
}, },
{ {
"type": "UnityEngine.Quaternion, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "type": "UnityEngine.Quaternion, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.LastRotation.Cube", "key": "ShapeBuilder.LastRotation.Cube",
"value": "{\"m_Value\":{\"x\":0.0,\"y\":0.0,\"z\":0.0,\"w\":1.0}}" "value": "{\"m_Value\":{\"x\":0.0,\"y\":0.0,\"z\":0.0,\"w\":1.0}}"
}, },
{
"type": "UnityEngine.Quaternion, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.LastRotation.Stairs",
"value": "{\"m_Value\":{\"x\":0.0,\"y\":0.0,\"z\":0.0,\"w\":1.0}}"
},
{ {
"type": "UnityEngine.ProBuilder.PivotLocation, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "type": "UnityEngine.ProBuilder.PivotLocation, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.PivotLocation.Cube", "key": "ShapeBuilder.PivotLocation.Cube",
"value": "{\"m_Value\":0}" "value": "{\"m_Value\":0}"
}, },
{
"type": "UnityEngine.ProBuilder.PivotLocation, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.PivotLocation.Stairs",
"value": "{\"m_Value\":0}"
},
{ {
"type": "UnityEngine.ProBuilder.Shapes.Shape, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "type": "UnityEngine.ProBuilder.Shapes.Shape, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.Cube", "key": "ShapeBuilder.Cube",
"value": "{}" "value": "{}"
}, },
{
"type": "UnityEngine.ProBuilder.Shapes.Shape, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "ShapeBuilder.Stairs",
"value": "{}"
},
{ {
"type": "UnityEngine.ProBuilder.SelectMode, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "type": "UnityEngine.ProBuilder.SelectMode, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "s_SelectMode", "key": "s_SelectMode",

View file

@ -3,10 +3,18 @@
--- !u!937362698 &1 --- !u!937362698 &1
VFXManager: VFXManager:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_IndirectShader: {fileID: 0} m_IndirectShader: {fileID: 7200000, guid: 84a17cfa13e40ae4082ef42714f0a81c, type: 3}
m_CopyBufferShader: {fileID: 0} m_CopyBufferShader: {fileID: 7200000, guid: 23c51f21a3503f6428b527b01f8a2f4e, type: 3}
m_SortShader: {fileID: 0} m_PrefixSumShader: {fileID: 7200000, guid: 783e0fdc1a277f54bb851fd2ceab1e7f, type: 3}
m_StripUpdateShader: {fileID: 0} m_SortShader: {fileID: 7200000, guid: ea257ca3cfb12a642a5025e612af6b2a, type: 3}
m_StripUpdateShader: {fileID: 7200000, guid: 8fa6c4009fe2a4d4486c62736fc30ad8, type: 3}
m_EmptyShader: {fileID: 4800000, guid: 33a2079f6a2db4c4eb2e44b33f4ddf6b, type: 3}
m_RenderPipeSettingsPath: m_RenderPipeSettingsPath:
m_FixedTimeStep: 0.016666668 m_FixedTimeStep: 0.016666668
m_MaxDeltaTime: 0.05 m_MaxDeltaTime: 0.05
m_MaxScrubTime: 30
m_MaxCapacity: 100000000
m_CompiledVersion: 7
m_RuntimeVersion: 39
m_RuntimeResources: {fileID: 11400000, guid: bc10b42afe3813544bffd38ae2cd893d, type: 2}
m_BatchEmptyLifetime: 300