140 lines
5.7 KiB
C#
140 lines
5.7 KiB
C#
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// Токсичная лужа ядовитой слизи босса, оставшаяся после попадания плевка.
|
||
/// Наносит периодический урон игроку при нахождении в зоне поражения и шипит.
|
||
/// </summary>
|
||
public class AcidPool : MonoBehaviour
|
||
{
|
||
public float damagePerSecond = 5f;
|
||
public float lifetime = 4.5f;
|
||
public float radius = 0.85f;
|
||
|
||
private float timer = 0f;
|
||
private PlayerHealth playerInPool = null;
|
||
private Light poolLight;
|
||
private System.Collections.Generic.List<Transform> visualSplatterPieces = new System.Collections.Generic.List<Transform>();
|
||
|
||
public static AcidPool Create(Vector3 position, float poolLifetime = 4.5f, float poolRadius = 0.85f)
|
||
{
|
||
GameObject go = new GameObject("Acid_Saliva_Splatter");
|
||
go.transform.position = position;
|
||
|
||
AcidPool pool = go.AddComponent<AcidPool>();
|
||
pool.lifetime = poolLifetime;
|
||
pool.radius = poolRadius;
|
||
return pool;
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
// Сферический триггер для обнаружения игрока
|
||
SphereCollider sc = gameObject.AddComponent<SphereCollider>();
|
||
sc.isTrigger = true;
|
||
sc.radius = radius;
|
||
|
||
// Кислотно-зеленый токсичный материал слюны: влажный, глянцевый
|
||
Material salivaMat = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"));
|
||
salivaMat.color = new Color(0.28f, 0.9f, 0.18f, 0.75f);
|
||
salivaMat.EnableKeyword("_EMISSION");
|
||
salivaMat.SetColor("_EmissionColor", new Color(0.15f, 0.7f, 0.1f) * 1.1f);
|
||
if (salivaMat.HasProperty("_Smoothness")) salivaMat.SetFloat("_Smoothness", 0.95f);
|
||
|
||
// 1. Центральное влажное пятно слюны (ультратонкое, как реальный след жидкости)
|
||
GameObject mainPuddle = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
mainPuddle.name = "Saliva_Center";
|
||
mainPuddle.transform.SetParent(transform, false);
|
||
mainPuddle.transform.localPosition = new Vector3(0f, 0.005f, 0f);
|
||
mainPuddle.transform.localScale = new Vector3(radius * 0.9f, 0.002f, radius * 0.9f);
|
||
Destroy(mainPuddle.GetComponent<Collider>());
|
||
mainPuddle.GetComponent<Renderer>().material = salivaMat;
|
||
visualSplatterPieces.Add(mainPuddle.transform);
|
||
|
||
// 2. Мелкие органические капли-брызги вокруг центра (клякса превращается в естественный всплеск слюны)
|
||
Vector2[] splashOffsets = new Vector2[]
|
||
{
|
||
new Vector2(0.42f, 0.25f),
|
||
new Vector2(-0.38f, 0.32f),
|
||
new Vector2(0.15f, -0.45f),
|
||
new Vector2(-0.42f, -0.22f),
|
||
new Vector2(0.50f, -0.18f)
|
||
};
|
||
|
||
for (int i = 0; i < splashOffsets.Length; i++)
|
||
{
|
||
GameObject splash = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
splash.name = $"Saliva_Droplet_{i + 1}";
|
||
splash.transform.SetParent(transform, false);
|
||
splash.transform.localPosition = new Vector3(splashOffsets[i].x * radius, 0.005f, splashOffsets[i].y * radius);
|
||
float dropScale = Random.Range(0.14f, 0.24f) * radius;
|
||
splash.transform.localScale = new Vector3(dropScale, 0.002f, dropScale * Random.Range(0.85f, 1.35f));
|
||
Destroy(splash.GetComponent<Collider>());
|
||
splash.GetComponent<Renderer>().material = salivaMat;
|
||
visualSplatterPieces.Add(splash.transform);
|
||
}
|
||
|
||
// 3. Мягкий биолюминесцентный свет пятна
|
||
GameObject lightObj = new GameObject("AcidLight");
|
||
lightObj.transform.SetParent(transform, false);
|
||
lightObj.transform.localPosition = new Vector3(0f, 0.15f, 0f);
|
||
poolLight = lightObj.AddComponent<Light>();
|
||
poolLight.type = LightType.Point;
|
||
poolLight.color = new Color(0.3f, 1.0f, 0.2f);
|
||
poolLight.intensity = 0.75f;
|
||
poolLight.range = 1.8f;
|
||
|
||
// Звук шипения кислоты
|
||
GameAudioSynthesizer.PlayAcidHiss();
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
timer += Time.deltaTime;
|
||
|
||
// Нанесение периодического урона игроку в луже
|
||
if (playerInPool != null)
|
||
{
|
||
playerInPool.TakeDamage(damagePerSecond * Time.deltaTime);
|
||
}
|
||
|
||
// Плавное испарение слюны в конце жизни
|
||
float remaining = lifetime - timer;
|
||
if (remaining <= 1.0f)
|
||
{
|
||
float scaleRatio = Mathf.Clamp01(remaining);
|
||
foreach (var piece in visualSplatterPieces)
|
||
{
|
||
if (piece != null)
|
||
{
|
||
piece.localScale = new Vector3(piece.localScale.x * scaleRatio, 0.002f, piece.localScale.z * scaleRatio);
|
||
}
|
||
}
|
||
if (poolLight != null) poolLight.intensity = 0.75f * scaleRatio;
|
||
}
|
||
|
||
if (timer >= lifetime)
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
}
|
||
|
||
private void OnTriggerEnter(Collider other)
|
||
{
|
||
if (other.CompareTag("Player") || other.GetComponentInParent<PlayerMovement>() != null)
|
||
{
|
||
playerInPool = other.GetComponentInParent<PlayerHealth>();
|
||
}
|
||
}
|
||
|
||
private void OnTriggerExit(Collider other)
|
||
{
|
||
if (other.CompareTag("Player") || other.GetComponentInParent<PlayerMovement>() != null)
|
||
{
|
||
if (playerInPool == other.GetComponentInParent<PlayerHealth>())
|
||
{
|
||
playerInPool = null;
|
||
}
|
||
}
|
||
}
|
||
}
|