324 lines
9.9 KiB
C#
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;
|
|
}
|
|
} |