Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Добавлен `ScoreSystem` — singleton-компонент, отслеживающий монеты, убитых врагов и экологические очки; финальный счёт вычисляется по формуле `Score = E × (P + 45C + 90K + 10K²) − 0.5T` с раздельными множителями для победы и проигрыша. - Добавлен `EnvironmentalCollectibleBase` — абстрактный базовый класс для подбираемых экологических объектов: срабатывает по триггеру, поддерживает пулинг, при подборе регистрирует очки в `ScoreSystem`. - Добавлен `LeafCollectible` — листик с синусоидальным горизонтальным дрейфом, вращением и детекцией земли. - Добавлен `BatCollectible` — летучая мышь с синусоидальным вертикальным движением, ограниченным горизонтальным блужданием и случайными сменами направления; переворачивает спрайт по X при смене направления. - Добавлен `EnvironmentalPool` — простой объектный пул по prefab-ключу с прогревом (`Warmup`) и возвратом объектов. - Добавлен `EnvironmentalCollectibleSpawner` — взвешенный случайный спаунер, поддерживающий фиксированное количество активных объектов; поддерживает лимиты по типу, принудительный выбор одного prefab и область спауна через `BoxCollider2D` или ручной `Bounds`. - В `CoinCollectible.TryPickup` добавлен вызов `ScoreSystem.Instance?.RegisterCoinCollected()`. - В `EnemyController.Die` добавлен guard через флаг `_isDead` для предотвращения повторного срабатывания; добавлен вызов `ScoreSystem.Instance?.RegisterEnemyKilled()`. - В `GameManager` добавлен вызов `ScoreSystem.Instance?.ResetStats()` при старте новой игры и при потере жизни.
123 lines
3.4 KiB
C#
123 lines
3.4 KiB
C#
using System;
|
|
using RR.Game2D.Behaviour;
|
|
using UnityEngine;
|
|
|
|
namespace RR.Common.Entities.Props
|
|
{
|
|
[RequireComponent(typeof(Collider2D))]
|
|
public abstract class EnvironmentalCollectibleBase : MonoBehaviour
|
|
{
|
|
[SerializeField] private int points = 1;
|
|
[SerializeField] private string playerTag = "Player";
|
|
[SerializeField] private bool usePooling = true;
|
|
|
|
private bool _collected;
|
|
private int _defaultPoints;
|
|
private Collider2D _trigger;
|
|
private EnvironmentalPool _ownerPool;
|
|
private GameObject _originPrefab;
|
|
private Vector3 _spawnPosition;
|
|
|
|
public event Action<EnvironmentalCollectibleBase> Collected;
|
|
|
|
public int Points => points;
|
|
public Vector3 SpawnPosition => _spawnPosition;
|
|
public bool UsesPooling => usePooling;
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
_defaultPoints = Mathf.Max(0, points);
|
|
_trigger = GetComponent<Collider2D>();
|
|
ValidateTrigger();
|
|
}
|
|
|
|
protected virtual void Update()
|
|
{
|
|
TickBehaviour(Time.deltaTime);
|
|
}
|
|
|
|
protected virtual void OnValidate()
|
|
{
|
|
if (points < 0) points = 0;
|
|
_defaultPoints = points;
|
|
ValidateTrigger();
|
|
}
|
|
|
|
private void OnTriggerEnter2D(Collider2D other)
|
|
{
|
|
// Unity 2D trigger callbacks usually require at least one of the colliding objects to have a Rigidbody2D.
|
|
if (_collected || other == null) return;
|
|
if (!other.CompareTag(playerTag)) return;
|
|
|
|
Collect(other.transform);
|
|
}
|
|
|
|
public void InitializeForSpawn(
|
|
EnvironmentalPool ownerPool,
|
|
GameObject originPrefab,
|
|
Vector3 spawnPosition,
|
|
int? pointsOverride)
|
|
{
|
|
_ownerPool = ownerPool;
|
|
_originPrefab = originPrefab;
|
|
_spawnPosition = spawnPosition;
|
|
points = pointsOverride.HasValue ? Mathf.Max(0, pointsOverride.Value) : _defaultPoints;
|
|
|
|
ResetStateForReuse();
|
|
}
|
|
|
|
public void ResetStateForReuse()
|
|
{
|
|
_collected = false;
|
|
_spawnPosition = transform.position;
|
|
OnSpawned();
|
|
}
|
|
|
|
protected void Collect(Transform collector)
|
|
{
|
|
if (_collected) return;
|
|
|
|
_collected = true;
|
|
OnCollected();
|
|
|
|
if (points > 0)
|
|
ScoreSystem.Instance?.RegisterEnvironmentalPoints(points);
|
|
|
|
Collected?.Invoke(this);
|
|
|
|
if (usePooling && _ownerPool != null && _originPrefab != null)
|
|
{
|
|
_ownerPool.Return(_originPrefab, gameObject);
|
|
return;
|
|
}
|
|
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
protected virtual void OnSpawned()
|
|
{
|
|
}
|
|
|
|
protected virtual void OnCollected()
|
|
{
|
|
}
|
|
|
|
protected abstract void TickBehaviour(float dt);
|
|
|
|
private void ValidateTrigger()
|
|
{
|
|
if (_trigger == null)
|
|
_trigger = GetComponent<Collider2D>();
|
|
|
|
if (_trigger == null)
|
|
{
|
|
Debug.LogError($"[{nameof(EnvironmentalCollectibleBase)}] Missing Collider2D on {name}.", this);
|
|
return;
|
|
}
|
|
|
|
if (!_trigger.isTrigger)
|
|
Debug.LogError($"[{nameof(EnvironmentalCollectibleBase)}] Collider2D on {name} must have isTrigger enabled.", this);
|
|
}
|
|
}
|
|
}
|