Files
AppleHillsProduction/Assets/Scripts/Minigames/TrashMaze/Objects/RevealableObject.cs
Michal Pikulski 8a65a5d0f6 Stash work
2025-12-08 16:46:50 +01:00

176 lines
5.6 KiB
C#

using Core;
using Minigames.TrashMaze.Core;
using UnityEngine;
namespace Minigames.TrashMaze.Objects
{
/// <summary>
/// Component for objects that need reveal memory (obstacles, booster packs, treasures).
/// Tracks if object has been revealed and updates material properties accordingly.
/// </summary>
[RequireComponent(typeof(SpriteRenderer))]
public class RevealableObject : MonoBehaviour
{
[Header("Textures")]
[SerializeField] private Sprite normalSprite;
[SerializeField] private Sprite outlineSprite;
[Header("Object Type")]
[SerializeField] private bool isBoosterPack = false;
[SerializeField] private bool isExit = false;
private SpriteRenderer _spriteRenderer;
private Material _instanceMaterial;
private bool _hasBeenRevealed = false;
private bool _isCollected = false;
// Material property IDs (cached for performance)
private static readonly int IsRevealedID = Shader.PropertyToID("_IsRevealed");
private static readonly int IsInVisionID = Shader.PropertyToID("_IsInVision");
private void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
// Create instance material so each object has its own properties
if (_spriteRenderer.material != null)
{
_instanceMaterial = new Material(_spriteRenderer.material);
_spriteRenderer.material = _instanceMaterial;
}
else
{
Logging.Error($"[RevealableObject] No material assigned to {gameObject.name}");
}
}
private void Start()
{
// Initialize material properties
if (_instanceMaterial != null)
{
_instanceMaterial.SetFloat(IsRevealedID, 0f);
_instanceMaterial.SetFloat(IsInVisionID, 0f);
// Set textures if provided
if (normalSprite != null)
{
_instanceMaterial.SetTexture("_MainTex", normalSprite.texture);
}
if (outlineSprite != null)
{
_instanceMaterial.SetTexture("_OutlineTex", outlineSprite.texture);
}
}
}
private void Update()
{
if (_isCollected || _instanceMaterial == null) return;
// Calculate distance to player
float distance = Vector2.Distance(transform.position, PulverController.PlayerPosition);
bool isInRadius = distance < PulverController.VisionRadius;
// Update real-time vision flag
_instanceMaterial.SetFloat(IsInVisionID, isInRadius ? 1f : 0f);
// Set revealed flag (once true, stays true)
if (isInRadius && !_hasBeenRevealed)
{
_hasBeenRevealed = true;
_instanceMaterial.SetFloat(IsRevealedID, 1f);
Logging.Debug($"[RevealableObject] {gameObject.name} revealed!");
}
}
private void OnTriggerEnter2D(Collider2D other)
{
// Check if player is interacting
if (other.CompareTag("Player") && _hasBeenRevealed && !_isCollected)
{
HandleInteraction();
}
}
private void HandleInteraction()
{
if (isBoosterPack)
{
CollectBoosterPack();
}
else if (isExit)
{
ActivateExit();
}
}
private void CollectBoosterPack()
{
_isCollected = true;
Logging.Debug($"[RevealableObject] Booster pack collected: {gameObject.name}");
// Notify controller
if (TrashMazeController.Instance != null)
{
TrashMazeController.Instance.OnBoosterPackCollected();
}
// Destroy object
Destroy(gameObject);
}
private void ActivateExit()
{
Logging.Debug($"[RevealableObject] Exit activated: {gameObject.name}");
// Notify controller
if (TrashMazeController.Instance != null)
{
TrashMazeController.Instance.OnExitReached();
}
}
private void OnDestroy()
{
// Clean up instance material
if (_instanceMaterial != null)
{
Destroy(_instanceMaterial);
}
}
/// <summary>
/// Check if object is currently visible to player
/// </summary>
public bool IsVisible()
{
float distance = Vector2.Distance(transform.position, PulverController.PlayerPosition);
return distance < PulverController.VisionRadius;
}
/// <summary>
/// Check if object has been revealed at any point
/// </summary>
public bool HasBeenRevealed()
{
return _hasBeenRevealed;
}
/// <summary>
/// Force reveal the object (for debugging or special cases)
/// </summary>
public void ForceReveal()
{
_hasBeenRevealed = true;
if (_instanceMaterial != null)
{
_instanceMaterial.SetFloat(IsRevealedID, 1f);
}
}
}
}