Files
Ipseity-Demo/Assets/_Content/Scripts/SpiralStaircase.cs
T

123 lines
3.2 KiB
C#

using OctoCore.Components;
using UnityEngine;
using UnityEngine.Rendering.Universal;
public class SpiralStaircase : MonoBehaviour
{
[System.Serializable]
public class References
{
public UniversalRendererData RendererData;
public GameObject Stairs;
public GameObject[] Inside;
public GameObject[] Outside;
}
[System.Serializable]
public class Settings
{
public float Offset = -12.25f;
public float StartAngle = 450;
public float EndAngle = 720;
}
[SerializeField] private References _references;
[SerializeField] private Settings _settings;
private bool _playerInside;
[SerializeField] private int _turns;
[SerializeField] private float _totalAngle;
[SerializeField] private float _progression;
void Start()
{
ManageInside();
}
void OnDisable()
{
_playerInside = false;
ManageInside();
}
void Update()
{
if (_playerInside)
Count();
}
void OnTriggerEnter(Collider col)
{
if (OctoPlayer.Instance && OctoPlayer.Instance.gameObject == col.gameObject)
{
if (!_playerInside)
{
_playerInside = true;
ManageInside();
}
}
}
void OnTriggerExit(Collider col)
{
if (OctoPlayer.Instance && OctoPlayer.Instance.gameObject == col.gameObject)
{
if (_playerInside)
{
_playerInside = false;
ManageInside();
}
}
}
private void Count()
{
if (!OctoPlayer.Instance) return;
Vector2[] steps = new Vector2[4] { Vector2.up, Vector2.left, Vector2.down, Vector2.right };
Vector2 nextStep = steps[_turns % steps.Length];
Vector3 relativePos3D = transform.InverseTransformPoint(OctoPlayer.Instance.transform.position);
Vector2 relativePos2D = new Vector2(relativePos3D.x, relativePos3D.z);
float quarterAngle = Vector2.Angle(nextStep, relativePos2D) * Mathf.Sign(Vector3.Cross(nextStep, relativePos2D).z);
_totalAngle = Mathf.Max(0, _turns * 90 + quarterAngle);
if (quarterAngle > 90 && quarterAngle < 100)
{
_turns++;
}
else if (quarterAngle < 0 && _turns > 0)
{
_turns--;
}
_progression = Mathf.Clamp01(Mathf.InverseLerp(_settings.StartAngle, _settings.EndAngle, _totalAngle));
_references.Stairs.transform.localPosition = new Vector3(0, _progression * _settings.Offset, 0);
}
private void ManageInside()
{
foreach (GameObject obj in _references.Inside) obj.SetActive(_playerInside);
foreach (GameObject obj in _references.Outside) obj.SetActive(!_playerInside);
Shader.SetGlobalFloat("_MaskEnabled", _playerInside ? 0 : 1);
foreach (var feature in _references.RendererData.rendererFeatures)
{
// Stencil Mask
// VisibleThroughMask
// HiddenThroughMask
if (feature.name == "HiddenThroughMask")
{
feature.SetActive(!_playerInside);
break;
}
}
}
}