Files
JuegoSim/Assets/_Project/Scripts/Code/VirtualPlatform/CanvasVirtualPlatformManager.cs
T
2026-07-21 08:56:10 +03:00

324 lines
9.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
public enum PlaneAxis
{
XZ = 0, // Horizontal plane (Y = 0)
XY = 1, // Front plane (Z = 0)
YZ = 2 // Side plane (X = 0)
}
[System.Serializable]
public class VirtualPlane
{
public PlaneAxis planeAxis;
public GameObject canvasGrid; // The Canvas with grid visual
[HideInInspector]
public GameObject colliderObject; // The collider (generated dynamically)
}
public class CanvasVirtualPlatformManager : MonoBehaviour
{
private static CanvasVirtualPlatformManager instance;
[Header("Plane Configurations")]
[SerializeField] private VirtualPlane[] virtualPlanes;
[Header("Collider Settings")]
[SerializeField] private float colliderThickness = 0.1f;
[SerializeField] private string colliderLayer = "World";
[Header("Settings")]
[SerializeField] private PlaneAxis currentPlane = PlaneAxis.XZ;
[SerializeField] private bool platformVisible = true;
private void Awake()
{
if (instance == null) instance = this;
else Destroy(this.gameObject);
}
public static CanvasVirtualPlatformManager getInstance() => instance;
private void Start()
{
GenerateColliders();
UpdatePlaneVisibility();
}
/// <summary>
/// Generate colliders for all planes based on their canvas sizes
/// </summary>
private void GenerateColliders()
{
foreach (var plane in virtualPlanes)
{
if (plane.canvasGrid == null) continue;
// Get the canvas component
Canvas canvas = plane.canvasGrid.GetComponent<Canvas>();
if (canvas == null) continue;
RectTransform rectTransform = canvas.GetComponent<RectTransform>();
if (rectTransform == null) continue;
// Create collider object
if (plane.colliderObject != null)
{
Destroy(plane.colliderObject);
}
plane.colliderObject = new GameObject($"Collider_{plane.planeAxis}");
plane.colliderObject.transform.SetParent(transform);
// Match canvas position
plane.colliderObject.transform.position = plane.canvasGrid.transform.position;
// Set rotation based on plane axis (not canvas rotation)
plane.colliderObject.transform.rotation = GetColliderRotation(plane.planeAxis);
// Add box collider
BoxCollider boxCollider = plane.colliderObject.AddComponent<BoxCollider>();
// Calculate collider size based on canvas size and scale
float width = rectTransform.rect.width * canvas.transform.localScale.x;
float height = rectTransform.rect.height * canvas.transform.localScale.y;
// All colliders use the same size format (width, thickness, height)
// Rotation handles the orientation
boxCollider.size = new Vector3(width, colliderThickness, height);
// Set layer
int layer = LayerMask.NameToLayer(colliderLayer);
if (layer != -1)
{
plane.colliderObject.layer = layer;
}
else
{
Debug.LogWarning($"Layer '{colliderLayer}' not found. Using default layer.");
}
Debug.Log($"Generated collider for {plane.planeAxis}: Size = {new Vector3(width, colliderThickness, height)}, Rotation = {GetColliderRotation(plane.planeAxis).eulerAngles}");
}
}
/// <summary>
/// Get the rotation for the collider based on plane axis
/// </summary>
private Quaternion GetColliderRotation(PlaneAxis axis)
{
switch (axis)
{
case PlaneAxis.XZ: // Horizontal plane (rotate to lay flat)
return Quaternion.Euler(0, 0, 0);
case PlaneAxis.XY: // Front plane (vertical, facing forward)
return Quaternion.Euler(90, 0, 0);
case PlaneAxis.YZ: // Side plane (vertical, facing sideways)
return Quaternion.Euler(0, 0, 90);
default:
return Quaternion.identity;
}
}
/// <summary>
/// Regenerate colliders (useful if canvas size changes at runtime)
/// </summary>
public void RegenerateColliders()
{
GenerateColliders();
UpdatePlaneVisibility();
}
/// <summary>
/// Switch to a different plane axis
/// </summary>
public void SwitchToPlane(PlaneAxis plane)
{
currentPlane = plane;
UpdatePlaneVisibility();
}
/// <summary>
/// Toggle platform visibility (canvas and collider)
/// </summary>
public void TogglePlatformVisibility(bool visible)
{
platformVisible = visible;
UpdatePlaneVisibility();
}
private void UpdatePlaneVisibility()
{
foreach (var plane in virtualPlanes)
{
bool isActive = (plane.planeAxis == currentPlane) && platformVisible;
if (plane.canvasGrid != null)
{
plane.canvasGrid.SetActive(isActive);
}
if (plane.colliderObject != null)
{
plane.colliderObject.SetActive(isActive);
}
}
}
/// <summary>
/// Toggle only the canvas grid visibility, keep colliders active
/// </summary>
public void ToggleGridVisibility(bool visible)
{
foreach (var plane in virtualPlanes)
{
if (plane.planeAxis == currentPlane && plane.canvasGrid != null)
{
plane.canvasGrid.SetActive(visible && platformVisible);
}
}
}
/// <summary>
/// Get the current active plane
/// </summary>
public PlaneAxis GetCurrentPlane() => currentPlane;
/// <summary>
/// Check if platform is currently visible
/// </summary>
public bool IsPlatformVisible() => platformVisible;
/// <summary>
/// Get the current active plane's collider object
/// </summary>
public GameObject GetCurrentCollider()
{
foreach (var plane in virtualPlanes)
{
if (plane.planeAxis == currentPlane)
{
return plane.colliderObject;
}
}
return null;
}
/// <summary>
/// Get the current active plane's canvas
/// </summary>
public GameObject GetCurrentCanvas()
{
foreach (var plane in virtualPlanes)
{
if (plane.planeAxis == currentPlane)
{
return plane.canvasGrid;
}
}
return null;
}
/// <summary>
/// Set the canvas size for a specific plane and regenerate its collider
/// </summary>
public void SetCanvasSize(PlaneAxis planeAxis, float width, float height)
{
foreach (var plane in virtualPlanes)
{
if (plane.planeAxis == planeAxis && plane.canvasGrid != null)
{
Canvas canvas = plane.canvasGrid.GetComponent<Canvas>();
RectTransform rectTransform = canvas.GetComponent<RectTransform>();
if (rectTransform != null)
{
rectTransform.sizeDelta = new Vector2(width, height);
// Regenerate only this plane's collider
RegenerateSingleCollider(plane);
}
break;
}
}
}
/// <summary>
/// Set the canvas size for the current active plane
/// </summary>
public void SetCurrentCanvasSize(float width, float height)
{
SetCanvasSize(currentPlane, width, height);
}
/// <summary>
/// Regenerate collider for a single plane
/// </summary>
private void RegenerateSingleCollider(VirtualPlane plane)
{
if (plane.canvasGrid == null) return;
Canvas canvas = plane.canvasGrid.GetComponent<Canvas>();
if (canvas == null) return;
RectTransform rectTransform = canvas.GetComponent<RectTransform>();
if (rectTransform == null) return;
// Destroy old collider if exists
if (plane.colliderObject != null)
{
Destroy(plane.colliderObject);
}
// Create new collider
plane.colliderObject = new GameObject($"Collider_{plane.planeAxis}");
plane.colliderObject.transform.SetParent(transform);
// Match canvas position
plane.colliderObject.transform.position = plane.canvasGrid.transform.position;
// Set rotation based on plane axis (not canvas rotation)
plane.colliderObject.transform.rotation = GetColliderRotation(plane.planeAxis);
BoxCollider boxCollider = plane.colliderObject.AddComponent<BoxCollider>();
float width = rectTransform.rect.width * canvas.transform.localScale.x;
float height = rectTransform.rect.height * canvas.transform.localScale.y;
// All colliders use the same size format (width, thickness, height)
// Rotation handles the orientation
boxCollider.size = new Vector3(width, colliderThickness, height);
int layer = LayerMask.NameToLayer(colliderLayer);
if (layer != -1)
{
plane.colliderObject.layer = layer;
}
// Update visibility based on current state
plane.colliderObject.SetActive((plane.planeAxis == currentPlane) && platformVisible);
Debug.Log($"Regenerated collider for {plane.planeAxis}: Size = {new Vector3(width, colliderThickness, height)}, Rotation = {GetColliderRotation(plane.planeAxis).eulerAngles}");
}
/// <summary>
/// Get the current canvas size
/// </summary>
public Vector2 GetCurrentCanvasSize()
{
GameObject canvas = GetCurrentCanvas();
if (canvas != null)
{
RectTransform rectTransform = canvas.GetComponent<RectTransform>();
if (rectTransform != null)
{
return rectTransform.sizeDelta;
}
}
return Vector2.zero;
}
}