feat: Procedural staircase

This commit is contained in:
Alexandre Coirier
2026-06-01 16:16:41 +02:00
parent ef0f7e03c5
commit 3718b3b298
8 changed files with 3260 additions and 1908 deletions
+36 -15
View File
@@ -22,7 +22,7 @@ public class SpiralStaircase : MonoBehaviour
public class State
{
public bool PlayerInside;
public int Turns;
public int Quarters;
public float TotalAngle;
[Range(0, 1)] public float Progression;
[Range(0, 1)] public float TotalProgression;
@@ -33,6 +33,9 @@ public class SpiralStaircase : MonoBehaviour
{
public UniversalRendererData RendererData;
public GameObject Stairs;
public MeshFilter StairSource;
public GameObject WallTop;
public GameObject WallMiddle;
public DoorsPair[] Doors;
public GameObject[] Inside;
public GameObject[] Outside;
@@ -41,10 +44,11 @@ public class SpiralStaircase : MonoBehaviour
[System.Serializable]
public class Settings
{
public float Offset = -12.25f;
public float StartAngle = 450;
public float EndAngle = 720;
public float AdditionalTopAngle = 360;
//public float Offset = -12.25f;
//public float StartAngle = 450;
//public float EndAngle = 720;
[Tooltip("Must be pair")]
[Min(7)] public int HalfTurns = 7;
}
[System.Serializable]
@@ -72,12 +76,29 @@ public class SpiralStaircase : MonoBehaviour
private List<IEnumerator> _doorsCoroutine;
private float _entryAngle = 0f;
private float _stairHeight;
private float _startAngle;
private float _endAngle;
void Awake()
{
_doorsCoroutine = new List<IEnumerator>();
for (int i = 0; i < _references.Doors.Length; i++)
_doorsCoroutine.Add(null);
_stairHeight = 1.75f;// _references.StairSource.mesh.bounds.size.y;
_startAngle = 180 * 2.5f;
_endAngle = Mathf.Max(_startAngle + 180, (_settings.HalfTurns - 2.5f) * 180);
for (int i = 1; i < _settings.HalfTurns; i++)
{
GameObject obj = Instantiate(_references.StairSource.gameObject, _references.StairSource.transform.parent);
obj.transform.localPosition = _references.StairSource.transform.localPosition + Vector3.up * _stairHeight * i;
obj.transform.localRotation = _references.StairSource.transform.localRotation * Quaternion.Euler(0, i * -180, 0);
}
_references.WallTop.transform.localPosition = Vector3.up * _settings.HalfTurns * _stairHeight;
_references.WallMiddle.transform.localScale = new Vector3(1, _settings.HalfTurns - 3, 1);
}
void Start()
@@ -169,7 +190,7 @@ public class SpiralStaircase : MonoBehaviour
{
_state.Progression = 0;
_state.PlayerInside = true;
_state.Turns = (int)_settings.EndAngle / 90;
_state.Quarters = (int)_endAngle / 90;
Count();
ManageInside();
}
@@ -178,7 +199,7 @@ public class SpiralStaircase : MonoBehaviour
{
_state.Progression = 1;
_state.PlayerInside = true;
_state.Turns = 0;
_state.Quarters = 0;
Count();
ManageInside();
}
@@ -188,25 +209,25 @@ public class SpiralStaircase : MonoBehaviour
if (!OctoPlayer.Instance) return;
Vector2[] steps = new Vector2[4] { Vector2.up, Vector2.left, Vector2.down, Vector2.right };
Vector2 nextStep = steps[_state.Turns % steps.Length];
Vector2 nextStep = steps[_state.Quarters % 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);
_state.TotalAngle = Mathf.Max(0, _state.Turns * 90 + quarterAngle);
_state.TotalAngle = Mathf.Max(0, _state.Quarters * 90 + quarterAngle);
if (quarterAngle > 90 && quarterAngle < 100)
{
_state.Turns++;
_state.Quarters++;
}
else if (quarterAngle < 0 && _state.Turns > 0)
else if (quarterAngle < 0 && _state.Quarters > 0)
{
_state.Turns--;
_state.Quarters--;
}
float progression = Mathf.Clamp01(Mathf.InverseLerp(_settings.StartAngle, _settings.EndAngle, _state.TotalAngle));
float progression = Mathf.Clamp01(Mathf.InverseLerp(_startAngle, _endAngle, _state.TotalAngle));
if (progression >= .5f && _state.Progression < .5f)
{
@@ -220,7 +241,7 @@ public class SpiralStaircase : MonoBehaviour
_state.Progression = progression;
_state.TotalProgression = Mathf.Clamp01(
Mathf.InverseLerp(_entryAngle, _settings.EndAngle + _settings.AdditionalTopAngle, _state.TotalAngle)
Mathf.InverseLerp(_entryAngle, _endAngle + _settings.HalfTurns * 180, _state.TotalAngle)
);
foreach (var trigger in _events.HallucinationTriggers)
@@ -236,7 +257,7 @@ public class SpiralStaircase : MonoBehaviour
}
}
_references.Stairs.transform.localPosition = new Vector3(0, _state.Progression * _settings.Offset, 0);
_references.Stairs.transform.localPosition = new Vector3(0, _state.Progression * _settings.HalfTurns * -_stairHeight, 0);
}
private void ManageInside()