From 430e66bfbf34ab99d39cef3f1c229305c6291602 Mon Sep 17 00:00:00 2001 From: Ben Calegari Date: Tue, 23 Jun 2026 21:02:40 -0700 Subject: [PATCH 1/3] Replace square with cone for Basic Arrow Tower. --- ...BasicTower.asset => BasicArrowTower.asset} | 8 +- ....asset.meta => BasicArrowTower.asset.meta} | 0 ...r_Basic.prefab => Tower_BasicArrow.prefab} | 20 ++- ...efab.meta => Tower_BasicArrow.prefab.meta} | 0 Assets/_Project/Scripts/Visuals.meta | 8 ++ Assets/_Project/Scripts/Visuals/ConeMesh.cs | 126 ++++++++++++++++++ .../_Project/Scripts/Visuals/ConeMesh.cs.meta | 11 ++ 7 files changed, 167 insertions(+), 6 deletions(-) rename Assets/_Project/Definitions/Towers/{BasicTower.asset => BasicArrowTower.asset} (84%) rename Assets/_Project/Definitions/Towers/{BasicTower.asset.meta => BasicArrowTower.asset.meta} (100%) rename Assets/_Project/Prefabs/Towers/{Tower_Basic.prefab => Tower_BasicArrow.prefab} (94%) rename Assets/_Project/Prefabs/Towers/{Tower_Basic.prefab.meta => Tower_BasicArrow.prefab.meta} (100%) create mode 100644 Assets/_Project/Scripts/Visuals.meta create mode 100644 Assets/_Project/Scripts/Visuals/ConeMesh.cs create mode 100644 Assets/_Project/Scripts/Visuals/ConeMesh.cs.meta diff --git a/Assets/_Project/Definitions/Towers/BasicTower.asset b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset similarity index 84% rename from Assets/_Project/Definitions/Towers/BasicTower.asset rename to Assets/_Project/Definitions/Towers/BasicArrowTower.asset index e32563a..5f00eaf 100644 --- a/Assets/_Project/Definitions/Towers/BasicTower.asset +++ b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset @@ -10,11 +10,11 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 7b353a757b6e6774d97e6fb8ba138fcc, type: 3} - m_Name: BasicTower + m_Name: BasicArrowTower m_EditorClassIdentifier: Assembly-CSharp::TD.Towers.TowerDefinition - DisplayName: Basic Arrow - Description: Targets ground and air. Fires single-target arrows. The bread and butter - of any maze. + DisplayName: Basic Arrow Tower + Description: Single-target tower that fires arrows at ground and air enemies. The + backbone of any maze. FootprintSize: {x: 2, y: 2} GoldCost: 25 BuildTime: 0.5 diff --git a/Assets/_Project/Definitions/Towers/BasicTower.asset.meta b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset.meta similarity index 100% rename from Assets/_Project/Definitions/Towers/BasicTower.asset.meta rename to Assets/_Project/Definitions/Towers/BasicArrowTower.asset.meta diff --git a/Assets/_Project/Prefabs/Towers/Tower_Basic.prefab b/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab similarity index 94% rename from Assets/_Project/Prefabs/Towers/Tower_Basic.prefab rename to Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab index 42defa0..1e6b505 100644 --- a/Assets/_Project/Prefabs/Towers/Tower_Basic.prefab +++ b/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab @@ -69,8 +69,9 @@ GameObject: - component: {fileID: 9137031893466587143} - component: {fileID: 805962841523123163} - component: {fileID: 8853488620519990682} + - component: {fileID: 5360241685303413177} m_Layer: 0 - m_Name: Tower_Basic + m_Name: Tower_BasicArrow m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -100,7 +101,7 @@ MeshFilter: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6482414459531823157} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} + m_Mesh: {fileID: 0} --- !u!23 &4028055828417179692 MeshRenderer: m_ObjectHideFlags: 0 @@ -241,6 +242,21 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerRangeIndicator rangeProjector: {fileID: 8255517343120954594} projectionDepth: 50 +--- !u!114 &5360241685303413177 +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: 93bc533262394e1e8b122bbfad89391a, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TD.Visuals.ConeMesh + sides: 16 + radius: 0.5 + height: 1 --- !u!1 &7580197837852108944 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/_Project/Prefabs/Towers/Tower_Basic.prefab.meta b/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab.meta similarity index 100% rename from Assets/_Project/Prefabs/Towers/Tower_Basic.prefab.meta rename to Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab.meta diff --git a/Assets/_Project/Scripts/Visuals.meta b/Assets/_Project/Scripts/Visuals.meta new file mode 100644 index 0000000..367f7c2 --- /dev/null +++ b/Assets/_Project/Scripts/Visuals.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 16f3da2efd0d4431888e3f04056646c2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Scripts/Visuals/ConeMesh.cs b/Assets/_Project/Scripts/Visuals/ConeMesh.cs new file mode 100644 index 0000000..d1790a5 --- /dev/null +++ b/Assets/_Project/Scripts/Visuals/ConeMesh.cs @@ -0,0 +1,126 @@ +// Assets/_Project/Scripts/Visuals/ConeMesh.cs +using UnityEngine; + +namespace TD.Visuals +{ + /// + /// Procedurally generates a cone mesh and assigns it to the GameObject's + /// . Unity ships no built-in cone primitive, so this + /// fills that gap for tower visuals (e.g. the Basic Arrow Tower). + /// + /// + /// Visual only. No networking, no collision — the mesh is purely cosmetic. + /// The existing MeshRenderer + material (and any owner/paint tinting via + /// TowerInstance.tintedRenderers) keep working unchanged. + /// + /// Pivot. The cone is centred on the local origin: its base ring sits at + /// y = -height/2 and its apex at y = +height/2, matching the vertical + /// extents of a unit cube so it sits on a build tile the same way the old cube did. + /// + /// Edit-time. [ExecuteAlways] rebuilds the mesh in the editor so the + /// cone is visible without entering play mode. The generated mesh is flagged + /// HideFlags.DontSave so it is never written out as a project asset. + /// + [ExecuteAlways] + [RequireComponent(typeof(MeshFilter))] + public class ConeMesh : MonoBehaviour + { + [Tooltip("Number of radial segments around the base. Higher = smoother circle.")] + [Range(3, 64)] + [SerializeField] private int sides = 16; + + [Tooltip("Radius of the cone's base in local units.")] + [Min(0.001f)] + [SerializeField] private float radius = 0.5f; + + [Tooltip("Height of the cone from base to apex in local units.")] + [Min(0.001f)] + [SerializeField] private float height = 1f; + + private Mesh mesh; + + private void OnEnable() => Rebuild(); + + private void OnValidate() + { + // OnValidate can fire before OnEnable in the editor; guard the component. + if (isActiveAndEnabled) Rebuild(); + } + + private void OnDisable() + { + // Clean up the generated mesh so it doesn't linger when the object is destroyed. + if (mesh != null) + { + if (Application.isPlaying) Destroy(mesh); + else DestroyImmediate(mesh); + mesh = null; + } + } + + private void Rebuild() + { + var filter = GetComponent(); + if (filter == null) return; + + if (mesh == null) + { + mesh = new Mesh { name = "ProceduralCone", hideFlags = HideFlags.DontSave }; + } + + BuildCone(mesh); + filter.sharedMesh = mesh; + } + + private void BuildCone(Mesh target) + { + target.Clear(); + + float halfHeight = height * 0.5f; + + // Vertex layout: + // [0 .. sides-1] base ring + // [sides] apex + // [sides + 1] base centre (for the bottom cap) + int baseRingStart = 0; + int apexIndex = sides; + int baseCentreIndex = sides + 1; + + var vertices = new Vector3[sides + 2]; + for (int i = 0; i < sides; i++) + { + float angle = (i / (float)sides) * Mathf.PI * 2f; + vertices[baseRingStart + i] = new Vector3( + Mathf.Cos(angle) * radius, + -halfHeight, + Mathf.Sin(angle) * radius); + } + vertices[apexIndex] = new Vector3(0f, halfHeight, 0f); + vertices[baseCentreIndex] = new Vector3(0f, -halfHeight, 0f); + + // Side faces (base ring -> apex) + base cap (fan from centre). + // Wind both so they face outward / downward respectively. + var triangles = new int[sides * 3 * 2]; + int t = 0; + for (int i = 0; i < sides; i++) + { + int next = (i + 1) % sides; + + // Side triangle, outward-facing. + triangles[t++] = baseRingStart + i; + triangles[t++] = apexIndex; + triangles[t++] = baseRingStart + next; + + // Base cap triangle, downward-facing. + triangles[t++] = baseCentreIndex; + triangles[t++] = baseRingStart + next; + triangles[t++] = baseRingStart + i; + } + + target.vertices = vertices; + target.triangles = triangles; + target.RecalculateNormals(); + target.RecalculateBounds(); + } + } +} diff --git a/Assets/_Project/Scripts/Visuals/ConeMesh.cs.meta b/Assets/_Project/Scripts/Visuals/ConeMesh.cs.meta new file mode 100644 index 0000000..2db0b9d --- /dev/null +++ b/Assets/_Project/Scripts/Visuals/ConeMesh.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93bc533262394e1e8b122bbfad89391a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 4f57499e40ded0f3ae49b41aeafa0ad7d7fc5724 Mon Sep 17 00:00:00 2001 From: Ben Calegari Date: Tue, 23 Jun 2026 22:57:15 -0700 Subject: [PATCH 2/3] Seige tower --- Assets/DefaultNetworkPrefabs.asset | 5 + Assets/_Project/Art/Sprites/Towers.meta | 8 + Assets/_Project/Art/Sprites/Towers/arrow.png | 3 + .../Art/Sprites/Towers/arrow.png.meta | 101 ++++++ Assets/_Project/Art/Sprites/Towers/siege.png | 3 + .../Art/Sprites/Towers/siege.png.meta | 101 ++++++ .../Definitions/Towers/BasicArrowTower.asset | 1 + .../Definitions/Towers/SiegeCannonTower.asset | 38 +++ .../Towers/SiegeCannonTower.asset.meta | 8 + .../Prefabs/Towers/Tower_SiegeCannon.prefab | 304 ++++++++++++++++++ .../Towers/Tower_SiegeCannon.prefab.meta | 7 + Assets/_Project/Scenes/Levels/9Player.unity | 186 +++++------ Assets/_Project/Scenes/Levels/Main.unity | 2 + Assets/_Project/Scripts/Editor/Towers.meta | 8 + .../Editor/Towers/TowerIconGenerator.cs | 190 +++++++++++ .../Editor/Towers/TowerIconGenerator.cs.meta | 11 + .../Scripts/Towers/TowerDefinition.cs | 5 + Assets/_Project/Scripts/UI/HUDController.cs | 9 + 18 files changed, 898 insertions(+), 92 deletions(-) create mode 100644 Assets/_Project/Art/Sprites/Towers.meta create mode 100644 Assets/_Project/Art/Sprites/Towers/arrow.png create mode 100644 Assets/_Project/Art/Sprites/Towers/arrow.png.meta create mode 100644 Assets/_Project/Art/Sprites/Towers/siege.png create mode 100644 Assets/_Project/Art/Sprites/Towers/siege.png.meta create mode 100644 Assets/_Project/Definitions/Towers/SiegeCannonTower.asset create mode 100644 Assets/_Project/Definitions/Towers/SiegeCannonTower.asset.meta create mode 100644 Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab create mode 100644 Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab.meta create mode 100644 Assets/_Project/Scripts/Editor/Towers.meta create mode 100644 Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs create mode 100644 Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs.meta diff --git a/Assets/DefaultNetworkPrefabs.asset b/Assets/DefaultNetworkPrefabs.asset index b3cf2c0..8f1b198 100644 --- a/Assets/DefaultNetworkPrefabs.asset +++ b/Assets/DefaultNetworkPrefabs.asset @@ -24,6 +24,11 @@ MonoBehaviour: SourcePrefabToOverride: {fileID: 0} SourceHashToOverride: 0 OverridingTargetPrefab: {fileID: 0} + - Override: 0 + Prefab: {fileID: 6482414459531823157, guid: 85ad5cd50543454891b343720f3048d6, type: 3} + SourcePrefabToOverride: {fileID: 0} + SourceHashToOverride: 0 + OverridingTargetPrefab: {fileID: 0} - Override: 0 Prefab: {fileID: 116861493430507844, guid: 3398cc5831880954487717577f61b6d7, type: 3} SourcePrefabToOverride: {fileID: 0} diff --git a/Assets/_Project/Art/Sprites/Towers.meta b/Assets/_Project/Art/Sprites/Towers.meta new file mode 100644 index 0000000..31e40d5 --- /dev/null +++ b/Assets/_Project/Art/Sprites/Towers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf1fa78cd62d44dd9882bb2d76bf1443 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Art/Sprites/Towers/arrow.png b/Assets/_Project/Art/Sprites/Towers/arrow.png new file mode 100644 index 0000000..7237b49 --- /dev/null +++ b/Assets/_Project/Art/Sprites/Towers/arrow.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28be0634e691ce222fab744a01eccf421e84e5eda3d42af2039b5e6e2abc65b5 +size 18755 diff --git a/Assets/_Project/Art/Sprites/Towers/arrow.png.meta b/Assets/_Project/Art/Sprites/Towers/arrow.png.meta new file mode 100644 index 0000000..b6332c9 --- /dev/null +++ b/Assets/_Project/Art/Sprites/Towers/arrow.png.meta @@ -0,0 +1,101 @@ +fileFormatVersion: 2 +guid: afe216737d1b46e783889299bda1c252 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Art/Sprites/Towers/siege.png b/Assets/_Project/Art/Sprites/Towers/siege.png new file mode 100644 index 0000000..8ac6b6e --- /dev/null +++ b/Assets/_Project/Art/Sprites/Towers/siege.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2e3748739d63be5f5e35d4efacae24923f9a9551563f5263a5b05b62b9c7d00 +size 62603 diff --git a/Assets/_Project/Art/Sprites/Towers/siege.png.meta b/Assets/_Project/Art/Sprites/Towers/siege.png.meta new file mode 100644 index 0000000..797abf3 --- /dev/null +++ b/Assets/_Project/Art/Sprites/Towers/siege.png.meta @@ -0,0 +1,101 @@ +fileFormatVersion: 2 +guid: 1423e4bda9704c3b826b0eb847c29c1c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 7d2e9f1c4a6b3d850800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Definitions/Towers/BasicArrowTower.asset b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset index 5f00eaf..7709fe3 100644 --- a/Assets/_Project/Definitions/Towers/BasicArrowTower.asset +++ b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset @@ -35,3 +35,4 @@ MonoBehaviour: ProjectilePrefab: {fileID: 2664719039363295382, guid: dc2e4a4108e03874a8b2dab88dcc8fba, type: 3} ProjectileSpeed: 15 UpgradePaths: [] + Icon: {fileID: 21300000, guid: afe216737d1b46e783889299bda1c252, type: 3} diff --git a/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset b/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset new file mode 100644 index 0000000..54d91dd --- /dev/null +++ b/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset @@ -0,0 +1,38 @@ +%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: 7b353a757b6e6774d97e6fb8ba138fcc, type: 3} + m_Name: SiegeCannonTower + m_EditorClassIdentifier: Assembly-CSharp::TD.Towers.TowerDefinition + DisplayName: Siege Cannon Tower + Description: Lobs a ballistic shell that deals splash damage where it lands. Targets + ground enemies only. + FootprintSize: {x: 2, y: 2} + GoldCost: 50 + BuildTime: 0.5 + TowerPrefab: {fileID: 6482414459531823157, guid: 85ad5cd50543454891b343720f3048d6, type: 3} + DamageType: 0 + TargetPriority: 0 + TargetType: 1 + GroundedOnly: 1 + Damage: 25 + Range: 16 + FireRate: 0.8 + SplashRadius: 3 + ChainCount: 0 + ChainRange: 0 + SlowFactor: 0 + DotDamagePerSecond: 0 + EffectDuration: 0 + ProjectilePrefab: {fileID: 2664719039363295382, guid: dc2e4a4108e03874a8b2dab88dcc8fba, type: 3} + ProjectileSpeed: 10 + UpgradePaths: [] + Icon: {fileID: 21300000, guid: 1423e4bda9704c3b826b0eb847c29c1c, type: 3} diff --git a/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset.meta b/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset.meta new file mode 100644 index 0000000..72fa85b --- /dev/null +++ b/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 04219895bbea4fb9a94fd62fef35bf2a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab b/Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab new file mode 100644 index 0000000..1c6e32f --- /dev/null +++ b/Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab @@ -0,0 +1,304 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &39352475684176306 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5753294230586596248} + - component: {fileID: 5360241685303413176} + m_Layer: 8 + m_Name: SelectionVolume + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5753294230586596248 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 39352475684176306} + 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: 1283036264165444500} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &5360241685303413176 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 39352475684176306} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + 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 &6482414459531823157 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1283036264165444500} + - component: {fileID: 6869333096494165105} + - component: {fileID: 4028055828417179692} + - component: {fileID: 5594214090440991794} + - component: {fileID: 7630870068340451557} + - component: {fileID: 9137031893466587143} + - component: {fileID: 805962841523123163} + - component: {fileID: 8853488620519990682} + m_Layer: 0 + m_Name: Tower_SiegeCannon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1283036264165444500 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6482414459531823157} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 2, y: 0.5, z: 2} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 5753294230586596248} + - {fileID: 7547850274173754846} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &6869333096494165105 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6482414459531823157} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4028055828417179692 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6482414459531823157} + 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 &5594214090440991794 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6482414459531823157} + 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!114 &7630870068340451557 +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: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject + GlobalObjectIdHash: 3344551122 + InScenePlacedSourceGlobalObjectIdHash: 0 + DeferredDespawnTick: 0 + Ownership: 1 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 0 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 + SyncOwnerTransformWhenParented: 1 + AllowOwnerToParent: 0 +--- !u!114 &9137031893466587143 +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: fb111fc88b3d6a340a3abde5a1502af3, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.TowerInstance + ShowTopMostFoldoutHeaderGroup: 1 + tintedRenderers: + - {fileID: 4028055828417179692} +--- !u!114 &805962841523123163 +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: 7eb6cce6cd96b23478b7d2173cebf74d, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerCombat + ShowTopMostFoldoutHeaderGroup: 1 + enemyLayerMask: + serializedVersion: 2 + m_Bits: 1024 +--- !u!114 &8853488620519990682 +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: c0edb0c5206ca454bbd7c300c6cc7574, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerRangeIndicator + rangeProjector: {fileID: 8255517343120954594} + projectionDepth: 50 +--- !u!1 &7580197837852108944 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7547850274173754846} + - component: {fileID: 8255517343120954594} + m_Layer: 0 + m_Name: RangeIndicator + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7547850274173754846 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7580197837852108944} + 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: 1283036264165444500} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8255517343120954594 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7580197837852108944} + 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: f99227cbde481ce47a2527e6bca709d2, 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: 1, y: 1, z: 1} + m_FadeFactor: 1 + m_VisibleInScene: 1 + version: 1 + m_DecalLayerMask: 1 diff --git a/Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab.meta b/Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab.meta new file mode 100644 index 0000000..fe27c56 --- /dev/null +++ b/Assets/_Project/Prefabs/Towers/Tower_SiegeCannon.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 85ad5cd50543454891b343720f3048d6 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Scenes/Levels/9Player.unity b/Assets/_Project/Scenes/Levels/9Player.unity index 9e21cf2..b0eec47 100644 --- a/Assets/_Project/Scenes/Levels/9Player.unity +++ b/Assets/_Project/Scenes/Levels/9Player.unity @@ -632,8 +632,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -1371,8 +1371,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -2379,8 +2379,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -2983,8 +2983,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -3161,8 +3161,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -4477,8 +4477,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -6479,8 +6479,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -6657,8 +6657,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -6905,8 +6905,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -7795,8 +7795,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -7973,8 +7973,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -8541,8 +8541,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -9075,8 +9075,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -9679,8 +9679,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -10247,8 +10247,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -11137,8 +11137,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -11315,8 +11315,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -12205,8 +12205,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -13489,8 +13489,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -13805,8 +13805,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -13983,8 +13983,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -14514,8 +14514,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -15124,8 +15124,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -15892,8 +15892,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -16172,8 +16172,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -16706,8 +16706,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -17308,8 +17308,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -17486,8 +17486,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -17799,8 +17799,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -18061,8 +18061,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -18307,8 +18307,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -19657,8 +19657,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -19774,6 +19774,7 @@ MonoBehaviour: - {fileID: 11400000, guid: 0f693e29ca953e1439e10cb8f12e4b30, type: 2} - {fileID: 11400000, guid: c4a1f7e92b6d8a4e3f0c9b1d6e5a2f80, type: 2} - {fileID: 11400000, guid: d5b2e8fa3c7e9b5f4a1d0c2e7f6b3a91, type: 2} + - {fileID: 11400000, guid: 04219895bbea4fb9a94fd62fef35bf2a, type: 2} startingDeck: - {fileID: 11400000, guid: d5b2e8fa3c7e9b5f4a1d0c2e7f6b3a91, type: 2} - {fileID: 11400000, guid: 0f693e29ca953e1439e10cb8f12e4b30, type: 2} @@ -19909,6 +19910,7 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.TowerRegistry definitions: - {fileID: 11400000, guid: 0f693e29ca953e1439e10cb8f12e4b30, type: 2} + - {fileID: 11400000, guid: 04219895bbea4fb9a94fd62fef35bf2a, type: 2} --- !u!1 &1547583984 GameObject: m_ObjectHideFlags: 0 @@ -20625,8 +20627,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -21229,8 +21231,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -21407,8 +21409,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -21941,8 +21943,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -22475,8 +22477,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -23123,8 +23125,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -25020,8 +25022,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -25554,8 +25556,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -26181,8 +26183,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -27139,8 +27141,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -27387,8 +27389,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -27565,8 +27567,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -27743,8 +27745,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 @@ -28347,8 +28349,8 @@ Mesh: m_CookingOptions: 30 m_BakedConvexCollisionMesh: m_BakedTriangleCollisionMesh: - 'm_MeshMetrics[0]': 1 - 'm_MeshMetrics[1]': 1 + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 m_MeshOptimizationFlags: 1 m_StreamData: serializedVersion: 2 diff --git a/Assets/_Project/Scenes/Levels/Main.unity b/Assets/_Project/Scenes/Levels/Main.unity index 9c9afa2..ccfea25 100644 --- a/Assets/_Project/Scenes/Levels/Main.unity +++ b/Assets/_Project/Scenes/Levels/Main.unity @@ -1842,6 +1842,7 @@ MonoBehaviour: towerDefinitions: - {fileID: 0} - {fileID: 11400000, guid: 0f693e29ca953e1439e10cb8f12e4b30, type: 2} + - {fileID: 11400000, guid: 04219895bbea4fb9a94fd62fef35bf2a, type: 2} --- !u!4 &1507514109 Transform: m_ObjectHideFlags: 0 @@ -1903,6 +1904,7 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.TowerRegistry definitions: - {fileID: 11400000, guid: 0f693e29ca953e1439e10cb8f12e4b30, type: 2} + - {fileID: 11400000, guid: 04219895bbea4fb9a94fd62fef35bf2a, type: 2} --- !u!1 &1597884408 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/_Project/Scripts/Editor/Towers.meta b/Assets/_Project/Scripts/Editor/Towers.meta new file mode 100644 index 0000000..a821b80 --- /dev/null +++ b/Assets/_Project/Scripts/Editor/Towers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2bef66c4dde743cc87f8272b863c12d4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs b/Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs new file mode 100644 index 0000000..15ceab8 --- /dev/null +++ b/Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs @@ -0,0 +1,190 @@ +// Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; +using TD.Towers; + +namespace TD.Towers.Editor +{ + /// + /// Editor utility that renders each 's prefab to a square + /// thumbnail PNG and assigns it back to the definition's Icon field, so the HUD + /// build menu shows "how the building looks when built" on each tower tile. + /// + /// + /// Run via TD > Generate Tower Icons. Uses + /// (synchronous, controllable) rather than the async AssetPreview API so the whole + /// pass completes within the menu callback. Generated PNGs are written to + /// Assets/_Project/Art/Sprites/Towers/, imported as Sprites, and wired onto the + /// matching asset. Re-running regenerates and overwrites in place. + /// + public static class TowerIconGenerator + { + private const string OutputFolder = "Assets/_Project/Art/Sprites/Towers"; + private const int IconSize = 128; + + [MenuItem("TD/Generate Tower Icons")] + public static void GenerateAll() + { + EnsureFolder(OutputFolder); + + string[] guids = AssetDatabase.FindAssets("t:TowerDefinition"); + if (guids.Length == 0) + { + Debug.LogWarning("[TowerIconGenerator] No TowerDefinition assets found."); + return; + } + + int generated = 0; + try + { + foreach (string guid in guids) + { + string defPath = AssetDatabase.GUIDToAssetPath(guid); + var def = AssetDatabase.LoadAssetAtPath(defPath); + if (def == null || def.TowerPrefab == null) + { + Debug.LogWarning($"[TowerIconGenerator] Skipping '{defPath}' — " + + "missing TowerDefinition or TowerPrefab."); + continue; + } + + Texture2D icon = RenderPrefabIcon(def.TowerPrefab); + if (icon == null) continue; + + string pngPath = $"{OutputFolder}/{def.name}.png"; + File.WriteAllBytes(pngPath, icon.EncodeToPNG()); + Object.DestroyImmediate(icon); + + AssetDatabase.ImportAsset(pngPath, ImportAssetOptions.ForceSynchronousImport); + ConfigureAsSprite(pngPath); + + var sprite = AssetDatabase.LoadAssetAtPath(pngPath); + AssignIcon(def, sprite); + generated++; + } + } + finally + { + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + Debug.Log($"[TowerIconGenerator] Generated {generated} tower icon(s) into {OutputFolder}."); + } + + // ----- Rendering -------------------------------------------------- + + private static Texture2D RenderPrefabIcon(GameObject prefab) + { + var pru = new PreviewRenderUtility(); + GameObject instance = null; + try + { + instance = Object.Instantiate(prefab); + instance.hideFlags = HideFlags.HideAndDontSave; + pru.AddSingleGO(instance); + + if (!TryGetWorldBounds(instance, out Bounds bounds)) + { + Debug.LogWarning($"[TowerIconGenerator] '{prefab.name}' has no renderers to capture."); + return null; + } + + // 3/4 view framed to the prefab's combined bounds. + const float fov = 30f; + float radius = Mathf.Max(bounds.extents.magnitude, 0.01f); + float distance = radius / Mathf.Sin(Mathf.Deg2Rad * fov * 0.5f) * 1.15f; + Quaternion dir = Quaternion.Euler(20f, 135f, 0f); + + var cam = pru.camera; + cam.fieldOfView = fov; + cam.transform.rotation = dir; + cam.transform.position = bounds.center - dir * Vector3.forward * distance; + cam.nearClipPlane = 0.01f; + cam.farClipPlane = distance * 4f; + cam.clearFlags = CameraClearFlags.SolidColor; + cam.backgroundColor = new Color(0f, 0f, 0f, 0f); // transparent + + pru.lights[0].intensity = 1.2f; + pru.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0f); + pru.lights[1].intensity = 0.6f; + pru.ambientColor = new Color(0.35f, 0.35f, 0.35f, 1f); + + var rect = new Rect(0, 0, IconSize, IconSize); + pru.BeginPreview(rect, GUIStyle.none); + pru.camera.Render(); + Texture rendered = pru.EndPreview(); + + var result = new Texture2D(IconSize, IconSize, TextureFormat.RGBA32, false); + RenderTexture prev = RenderTexture.active; + RenderTexture.active = rendered as RenderTexture; + result.ReadPixels(rect, 0, 0); + result.Apply(); + RenderTexture.active = prev; + return result; + } + finally + { + if (instance != null) Object.DestroyImmediate(instance); + pru.Cleanup(); + } + } + + private static bool TryGetWorldBounds(GameObject go, out Bounds bounds) + { + var renderers = go.GetComponentsInChildren(); + bounds = default; + bool any = false; + foreach (var r in renderers) + { + // Skip projector/decal-style renderers that don't represent the tower body. + if (r is MeshRenderer || r is SkinnedMeshRenderer) + { + if (!any) { bounds = r.bounds; any = true; } + else { bounds.Encapsulate(r.bounds); } + } + } + return any; + } + + // ----- Asset wiring ----------------------------------------------- + + private static void ConfigureAsSprite(string pngPath) + { + var importer = AssetImporter.GetAtPath(pngPath) as TextureImporter; + if (importer == null) return; + + importer.textureType = TextureImporterType.Sprite; + importer.spriteImportMode = SpriteImportMode.Single; + importer.alphaIsTransparency = true; + importer.mipmapEnabled = false; + importer.SaveAndReimport(); + } + + private static void AssignIcon(TowerDefinition def, Sprite sprite) + { + if (sprite == null) return; + var so = new SerializedObject(def); + so.FindProperty("Icon").objectReferenceValue = sprite; + so.ApplyModifiedPropertiesWithoutUndo(); + EditorUtility.SetDirty(def); + } + + private static void EnsureFolder(string assetFolder) + { + if (AssetDatabase.IsValidFolder(assetFolder)) return; + + string[] parts = assetFolder.Split('/'); + string current = parts[0]; // "Assets" + for (int i = 1; i < parts.Length; i++) + { + string next = $"{current}/{parts[i]}"; + if (!AssetDatabase.IsValidFolder(next)) + AssetDatabase.CreateFolder(current, parts[i]); + current = next; + } + } + } +} diff --git a/Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs.meta b/Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs.meta new file mode 100644 index 0000000..01731bf --- /dev/null +++ b/Assets/_Project/Scripts/Editor/Towers/TowerIconGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de83f68d5958449185d2a0c8199c41ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Scripts/Towers/TowerDefinition.cs b/Assets/_Project/Scripts/Towers/TowerDefinition.cs index a106ebf..8d80828 100644 --- a/Assets/_Project/Scripts/Towers/TowerDefinition.cs +++ b/Assets/_Project/Scripts/Towers/TowerDefinition.cs @@ -68,6 +68,11 @@ namespace TD.Towers "replace with a real mesh when art is available.")] public GameObject TowerPrefab; + [Tooltip("Icon shown on this tower's tile in the HUD build menu. Auto-generated from " + + "the TowerPrefab by the 'TD/Generate Tower Icons' menu item, or assign a " + + "Sprite manually. Null falls back to the grey placeholder icon.")] + public Sprite Icon; + // ------------------------------------------------------------------- // Combat // ------------------------------------------------------------------- diff --git a/Assets/_Project/Scripts/UI/HUDController.cs b/Assets/_Project/Scripts/UI/HUDController.cs index ccef8f0..28b4558 100644 --- a/Assets/_Project/Scripts/UI/HUDController.cs +++ b/Assets/_Project/Scripts/UI/HUDController.cs @@ -858,6 +858,15 @@ namespace TD.UI Debug.LogWarning("[HUDController] No TowerPlacementController assigned."); }); + // Show the tower's thumbnail on the icon placeholder. Falls back to the grey + // placeholder square when no Icon is assigned (see CreatePaintButton for the pattern). + if (def.Icon != null) + { + var icon = btn.Q(null, "cmd-icon-placeholder"); + if (icon != null) + icon.style.backgroundImage = new StyleBackground(def.Icon); + } + btn.RegisterCallback(_ => ShowTooltip(def)); btn.RegisterCallback(_ => ClearTooltip()); return btn; From c5c02ecc7ecd43b70543e9ff38347dd7899a0911 Mon Sep 17 00:00:00 2001 From: Ben Calegari Date: Tue, 23 Jun 2026 23:11:48 -0700 Subject: [PATCH 3/3] Fix cone make it look nice --- Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab | 7 ++++--- Assets/_Project/Scripts/Visuals/ConeMesh.cs | 8 +++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab b/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab index 1e6b505..72ae323 100644 --- a/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab +++ b/Assets/_Project/Prefabs/Towers/Tower_BasicArrow.prefab @@ -254,9 +254,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 93bc533262394e1e8b122bbfad89391a, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::TD.Visuals.ConeMesh - sides: 16 - radius: 0.5 - height: 1 + sides: 4 + radius: 0.7071068 + height: 1.5 + angularOffsetDegrees: 45 --- !u!1 &7580197837852108944 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/_Project/Scripts/Visuals/ConeMesh.cs b/Assets/_Project/Scripts/Visuals/ConeMesh.cs index d1790a5..7b0f322 100644 --- a/Assets/_Project/Scripts/Visuals/ConeMesh.cs +++ b/Assets/_Project/Scripts/Visuals/ConeMesh.cs @@ -37,6 +37,11 @@ namespace TD.Visuals [Min(0.001f)] [SerializeField] private float height = 1f; + [Tooltip("Rotation of the base ring around the vertical axis, in degrees. With a low " + + "side count this makes a pyramid; e.g. sides = 4 with a 45° offset and " + + "radius 0.7071 yields a square-based pyramid whose faces align to the X/Z axes.")] + [SerializeField] private float angularOffsetDegrees = 0f; + private Mesh mesh; private void OnEnable() => Rebuild(); @@ -89,7 +94,8 @@ namespace TD.Visuals var vertices = new Vector3[sides + 2]; for (int i = 0; i < sides; i++) { - float angle = (i / (float)sides) * Mathf.PI * 2f; + float angle = (i / (float)sides) * Mathf.PI * 2f + + angularOffsetDegrees * Mathf.Deg2Rad; vertices[baseRingStart + i] = new Vector3( Mathf.Cos(angle) * radius, -halfHeight,