Adding VFX package, cleaning up texture on terrain slightly, and adding new build FX asset for orbital drop visuals.
This commit is contained in:
parent
2fbee5fd99
commit
28b0e2cdf2
24 changed files with 15522 additions and 10 deletions
|
|
@ -3,6 +3,7 @@ using Unity.Netcode;
|
|||
using UnityEngine;
|
||||
using TD.Core;
|
||||
using TD.Towers;
|
||||
using TD.VFX;
|
||||
|
||||
namespace TD.Gameplay
|
||||
{
|
||||
|
|
@ -69,6 +70,13 @@ namespace TD.Gameplay
|
|||
"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 " +
|
||||
"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)")]
|
||||
[Tooltip("FALLBACK ONLY (no phase set assigned): number of discrete growth stages " +
|
||||
"while constructing. 4 = 1/4 → 2/4 → 3/4 → 4/4 height.")]
|
||||
|
|
@ -247,6 +255,10 @@ namespace TD.Gameplay
|
|||
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;
|
||||
|
||||
// ----- Lifecycle --------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -299,6 +311,15 @@ namespace TD.Gameplay
|
|||
// 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)
|
||||
{
|
||||
dropReticleInstance = Instantiate(dropReticlePrefab, transform);
|
||||
dropReticleInstance.transform.localPosition = Vector3.zero;
|
||||
dropReticleInstance.transform.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
// Subscribe to value changes so visual updates are reactive.
|
||||
currentStage.OnValueChanged += HandleStageChanged;
|
||||
|
||||
|
|
@ -353,6 +374,13 @@ namespace TD.Gameplay
|
|||
|
||||
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
|
||||
// peer so visuals stay synchronized. Paused does NOT update — the visual is
|
||||
// frozen at the pause point.
|
||||
|
|
|
|||
8
Assets/_Project/Scripts/VFX.meta
Normal file
8
Assets/_Project/Scripts/VFX.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ba7743153560abe4c8b69fb6e86ec013
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
96
Assets/_Project/Scripts/VFX/TowerDropReticle.cs
Normal file
96
Assets/_Project/Scripts/VFX/TowerDropReticle.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/_Project/Scripts/VFX/TowerDropReticle.cs.meta
Normal file
2
Assets/_Project/Scripts/VFX/TowerDropReticle.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: baac389882e721248bb426ee40fbf74f
|
||||
Loading…
Add table
Add a link
Reference in a new issue