Add tower Sell action with refund + coin VFX/SFX
Owner-validated sell RPC refunds SellRefundPercent of invested gold (Wall refunds 100% while un-upgraded), despawns the tower, and broadcasts a coin-burst VFX + rustle SFX. Refunds do not count as per-wave income. Investment/upgrade tracking added as the seam for the future upgrade system. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2429efbf6a
commit
9be31b1645
7 changed files with 361 additions and 12 deletions
101
Assets/_Project/Scripts/VFX/CoinBurstVfx.cs
Normal file
101
Assets/_Project/Scripts/VFX/CoinBurstVfx.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// Assets/_Project/Scripts/VFX/CoinBurstVfx.cs
|
||||
using UnityEngine;
|
||||
|
||||
namespace TD.VFX
|
||||
{
|
||||
/// <summary>
|
||||
/// Self-contained, code-configured gold-coin burst used as the zero-art placeholder for the
|
||||
/// tower-sell effect. Configures its own <see cref="ParticleSystem"/> for a short radial
|
||||
/// spray of gold specks thrown up in random arcs under gravity, then destroys itself.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Instantiated at runtime by <see cref="SellEffectSpawner"/> when no authored VFX prefab is
|
||||
/// assigned. It can also be dropped on a prefab in the editor and tuned. Replace with an
|
||||
/// authored particle / VFX-graph prefab (assigned on the spawner) when art is ready — nothing
|
||||
/// else needs to change.
|
||||
/// </remarks>
|
||||
[RequireComponent(typeof(ParticleSystem))]
|
||||
public class CoinBurstVfx : MonoBehaviour
|
||||
{
|
||||
[Tooltip("How many coin specks to throw.")]
|
||||
[SerializeField] private int coinCount = 14;
|
||||
|
||||
[Tooltip("Longest a speck lives (seconds). The whole effect self-destructs shortly after.")]
|
||||
[SerializeField] private float lifetime = 0.6f;
|
||||
|
||||
[Tooltip("Gold tint applied to the specks.")]
|
||||
[SerializeField] private Color coinColor = new Color(1f, 0.84f, 0.2f, 1f);
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
var ps = GetComponent<ParticleSystem>();
|
||||
if (ps == null) ps = gameObject.AddComponent<ParticleSystem>();
|
||||
Configure(ps);
|
||||
}
|
||||
|
||||
private void Configure(ParticleSystem ps)
|
||||
{
|
||||
// Reconfiguring modules requires the system to be stopped first.
|
||||
ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
|
||||
|
||||
var main = ps.main;
|
||||
main.duration = 0.1f;
|
||||
main.loop = false;
|
||||
main.playOnAwake = false;
|
||||
main.startLifetime = new ParticleSystem.MinMaxCurve(lifetime * 0.6f, lifetime);
|
||||
main.startSpeed = new ParticleSystem.MinMaxCurve(2.5f, 5f);
|
||||
main.startSize = new ParticleSystem.MinMaxCurve(0.07f, 0.16f);
|
||||
main.startRotation = new ParticleSystem.MinMaxCurve(0f, Mathf.PI * 2f);
|
||||
main.startColor = coinColor;
|
||||
main.gravityModifier = 2.5f; // arc up then fall back down quickly
|
||||
main.simulationSpace = ParticleSystemSimulationSpace.World;
|
||||
main.maxParticles = 64;
|
||||
main.stopAction = ParticleSystemStopAction.None;
|
||||
|
||||
var emission = ps.emission;
|
||||
emission.enabled = true;
|
||||
emission.rateOverTime = 0f; // burst only, no continuous stream
|
||||
emission.SetBursts(new[] { new ParticleSystem.Burst(0f, (short)coinCount) });
|
||||
|
||||
// Hemisphere pointing up → specks spray outward and upward in random directions.
|
||||
var shape = ps.shape;
|
||||
shape.enabled = true;
|
||||
shape.shapeType = ParticleSystemShapeType.Hemisphere;
|
||||
shape.radius = 0.12f;
|
||||
|
||||
// Fade the specks out over the back half of their life so they "decay quickly".
|
||||
var col = ps.colorOverLifetime;
|
||||
col.enabled = true;
|
||||
var grad = new Gradient();
|
||||
grad.SetKeys(
|
||||
new[] { new GradientColorKey(coinColor, 0f), new GradientColorKey(coinColor, 1f) },
|
||||
new[]
|
||||
{
|
||||
new GradientAlphaKey(1f, 0f),
|
||||
new GradientAlphaKey(1f, 0.55f),
|
||||
new GradientAlphaKey(0f, 1f),
|
||||
});
|
||||
col.color = new ParticleSystem.MinMaxGradient(grad);
|
||||
|
||||
// Give the specks a visible, transparent-capable material even with no assigned art.
|
||||
var renderer = GetComponent<ParticleSystemRenderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
renderer.renderMode = ParticleSystemRenderMode.Billboard;
|
||||
if (renderer.sharedMaterial == null)
|
||||
{
|
||||
Shader shader = Shader.Find("Universal Render Pipeline/Particles/Unlit")
|
||||
?? Shader.Find("Sprites/Default")
|
||||
?? Shader.Find("Legacy Shaders/Particles/Alpha Blended Premultiply");
|
||||
if (shader != null)
|
||||
renderer.material = new Material(shader) { color = coinColor };
|
||||
}
|
||||
}
|
||||
|
||||
ps.Play();
|
||||
|
||||
// Tear down after the last speck has died (plus a small margin).
|
||||
Destroy(gameObject, lifetime + 0.25f);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue