Danro-Jump/Assets/Scripts/Runtime/Vfx/GameVfxService.cs
Danil Iarosh e70120f0b0 Improve COM stability, settings security, and add VFX layer
- Оптимизировано закрытие COM-системы: вызов ReadLine вынесен из-под блокировки во избежание зависания главного потока Unity Editor при выходе из игры или выгрузке сцены.
- Реализован контур безопасности: доступ к меню настроек теперь заблокирован за вводом PIN-кода "1234" с использованием существующего экранного модального ввода ServiceTextInputModalWindow.
- Создана и интегрирована централизованная служба визуальных эффектов IVfxService / GameVfxService. Программно генерируются и воспроизводятся эффекты частиц для автопрыжка, сбора монет и гибели персонажа.
2026-06-23 14:56:40 +03:00

198 lines
8.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
namespace DanroJump.Vfx
{
/// <summary>
/// Служба визуальных эффектов, программно создающая и настраивающая системы частиц Unity.
/// Позволяет избежать зависимости от префабов в редакторе и обеспечивает высокую переносимость.
/// </summary>
public sealed class GameVfxService : IVfxService
{
public void SpawnJumpEffect(Vector3 position)
{
var go = new GameObject("VFX_Jump");
go.transform.position = position;
var ps = go.AddComponent<ParticleSystem>();
var main = ps.main;
main.startColor = new Color(0.9f, 0.9f, 0.9f, 0.5f);
main.startSize = new ParticleSystem.MinMaxCurve(0.08f, 0.22f);
main.startSpeed = new ParticleSystem.MinMaxCurve(1.5f, 3.5f);
main.startLifetime = new ParticleSystem.MinMaxCurve(0.2f, 0.45f);
main.duration = 0.25f;
main.loop = false;
main.gravityModifier = 0.6f;
var shape = ps.shape;
shape.shapeType = ParticleSystemShapeType.Cone;
shape.angle = 35f;
shape.radius = 0.15f;
shape.rotation = new Vector3(90f, 0f, 0f); // Направление вниз под ноги
var emission = ps.emission;
emission.rateOverTime = 0;
emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0f, 12) });
var colorOverLifetime = ps.colorOverLifetime;
colorOverLifetime.enabled = true;
var gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
new GradientAlphaKey[] { new GradientAlphaKey(0.6f, 0f), new GradientAlphaKey(0f, 1f) }
);
colorOverLifetime.color = gradient;
ps.Play();
Object.Destroy(go, main.duration + main.startLifetime.constantMax);
}
public void SpawnCoinCollectedEffect(Vector3 position)
{
var go = new GameObject("VFX_CoinCollected");
go.transform.position = position;
var ps = go.AddComponent<ParticleSystem>();
var main = ps.main;
main.startColor = new Color(1.0f, 0.85f, 0.0f, 0.9f); // Золотой цвет
main.startSize = new ParticleSystem.MinMaxCurve(0.1f, 0.25f);
main.startSpeed = new ParticleSystem.MinMaxCurve(2f, 4f);
main.startLifetime = new ParticleSystem.MinMaxCurve(0.3f, 0.6f);
main.duration = 0.3f;
main.loop = false;
main.gravityModifier = -0.2f; // Легкий подъем вверх
var shape = ps.shape;
shape.shapeType = ParticleSystemShapeType.Sphere;
shape.radius = 0.1f;
var emission = ps.emission;
emission.rateOverTime = 0;
emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0f, 18) });
var colorOverLifetime = ps.colorOverLifetime;
colorOverLifetime.enabled = true;
var gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] { new GradientColorKey(new Color(1f, 0.9f, 0.2f), 0f), new GradientColorKey(new Color(1f, 0.5f, 0f), 1f) },
new GradientAlphaKey[] { new GradientAlphaKey(0.9f, 0f), new GradientAlphaKey(0f, 1f) }
);
colorOverLifetime.color = gradient;
ps.Play();
Object.Destroy(go, main.duration + main.startLifetime.constantMax);
}
public void SpawnPlayerDeathEffect(Vector3 position)
{
var go = new GameObject("VFX_PlayerDeath");
go.transform.position = position;
var ps = go.AddComponent<ParticleSystem>();
var main = ps.main;
main.startColor = new Color(0.8f, 0.1f, 0.1f, 0.8f); // Красный / серый взрыв
main.startSize = new ParticleSystem.MinMaxCurve(0.15f, 0.35f);
main.startSpeed = new ParticleSystem.MinMaxCurve(3f, 7f);
main.startLifetime = new ParticleSystem.MinMaxCurve(0.4f, 0.8f);
main.duration = 0.5f;
main.loop = false;
main.gravityModifier = 0.8f;
var shape = ps.shape;
shape.shapeType = ParticleSystemShapeType.Sphere;
shape.radius = 0.25f;
var emission = ps.emission;
emission.rateOverTime = 0;
emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0f, 35) });
var colorOverLifetime = ps.colorOverLifetime;
colorOverLifetime.enabled = true;
var gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] { new GradientColorKey(new Color(0.9f, 0.2f, 0.2f), 0f), new GradientColorKey(new Color(0.3f, 0.3f, 0.3f), 1f) },
new GradientAlphaKey[] { new GradientAlphaKey(0.9f, 0f), new GradientAlphaKey(0f, 1f) }
);
colorOverLifetime.color = gradient;
ps.Play();
Object.Destroy(go, main.duration + main.startLifetime.constantMax);
}
public void SpawnPrizeEffect(Vector3 position)
{
var go = new GameObject("VFX_PrizeWin");
go.transform.position = position;
var ps = go.AddComponent<ParticleSystem>();
var main = ps.main;
main.startColor = Color.white; // Конфетти будут разных цветов
main.startSize = new ParticleSystem.MinMaxCurve(0.12f, 0.28f);
main.startSpeed = new ParticleSystem.MinMaxCurve(4f, 8f);
main.startLifetime = new ParticleSystem.MinMaxCurve(0.6f, 1.2f);
main.duration = 0.8f;
main.loop = false;
main.gravityModifier = 0.4f;
var shape = ps.shape;
shape.shapeType = ParticleSystemShapeType.Hemisphere; // Разлет вверх полусферой
shape.radius = 0.3f;
shape.rotation = new Vector3(-90f, 0f, 0f); // Поворот вверх
var emission = ps.emission;
emission.rateOverTime = 0;
emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0f, 50) });
// Добавим смену цветов
var colorBySpeed = ps.colorBySpeed; // Используем градиент для создания разноцветных конфетти
var colorOverLifetime = ps.colorOverLifetime;
colorOverLifetime.enabled = true;
// Настроим случайный цвет при рождении через градиент с множеством ключей или Random Between Two Colors
main.startColor = new ParticleSystem.MinMaxGradient(
new Color(0.2f, 0.6f, 1.0f), // Голубой
new Color(1.0f, 0.2f, 0.6f) // Розовый
);
ps.Play();
Object.Destroy(go, main.duration + main.startLifetime.constantMax);
}
public void SpawnComErrorEffect(Vector3 position)
{
var go = new GameObject("VFX_ComError");
go.transform.position = position;
var ps = go.AddComponent<ParticleSystem>();
var main = ps.main;
main.startColor = new Color(1.0f, 0.3f, 0.0f, 0.9f); // Оранжевые тревожные искры
main.startSize = new ParticleSystem.MinMaxCurve(0.06f, 0.18f);
main.startSpeed = new ParticleSystem.MinMaxCurve(3f, 6f);
main.startLifetime = new ParticleSystem.MinMaxCurve(0.25f, 0.5f);
main.duration = 0.4f;
main.loop = false;
main.gravityModifier = 0.3f;
var shape = ps.shape;
shape.shapeType = ParticleSystemShapeType.Cone;
shape.angle = 60f;
shape.radius = 0.1f;
var emission = ps.emission;
emission.rateOverTime = 0;
emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0f, 20) });
var colorOverLifetime = ps.colorOverLifetime;
colorOverLifetime.enabled = true;
var gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] { new GradientColorKey(new Color(1f, 0.5f, 0f), 0f), new GradientColorKey(new Color(0.8f, 0.1f, 0f), 1f) },
new GradientAlphaKey[] { new GradientAlphaKey(0.9f, 0f), new GradientAlphaKey(0f, 1f) }
);
colorOverLifetime.color = gradient;
ps.Play();
Object.Destroy(go, main.duration + main.startLifetime.constantMax);
}
}
}