Files
Travel_Run/Assets/Scripts/FinishGate.cs
T
2026-07-06 17:34:13 +09:00

330 lines
12 KiB
C#

using TMPro;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public enum FinishGateStyle {
None,
AirportDeparture,
JapanTorii,
ChinaPaifang,
AmericaLiberty
}
public class FinishGate : MonoBehaviour {
private const string ForegroundSortingLayer = "Foreground";
private const float DespawnX = -18f;
private const float RuntimeSpritePixelsPerUnit = 256f;
private static Sprite blockSprite;
private bool cleared = false;
public void Setup(FinishGateStyle style) {
cleared = false;
ScrollingObject scrollingObject = GetComponent<ScrollingObject>();
if(scrollingObject == null)
{
scrollingObject = gameObject.AddComponent<ScrollingObject>();
}
scrollingObject.speed = 10f;
BoxCollider2D trigger = GetComponent<BoxCollider2D>();
if(trigger == null)
{
trigger = gameObject.AddComponent<BoxCollider2D>();
}
ConfigureTrigger(trigger);
BuildGate(style);
}
private void Update() {
if(transform.position.x < DespawnX)
{
Destroy(gameObject);
}
}
private void OnTriggerEnter2D(Collider2D other) {
if(cleared || !other.CompareTag("Player") || !GameFlowManager.IsGameplayActive)
{
return;
}
cleared = true;
if(GameManager.instance != null)
{
GameManager.instance.CompleteCurrentStageFromFinishGate();
}
}
private void BuildGate(FinishGateStyle style) {
ClearChildren();
if(TryBuildSpriteGate(style))
{
return;
}
switch(style)
{
case FinishGateStyle.JapanTorii:
BuildJapanTorii();
break;
case FinishGateStyle.ChinaPaifang:
BuildChinaPaifang();
break;
case FinishGateStyle.AmericaLiberty:
BuildAmericaLibertyFallback();
break;
case FinishGateStyle.AirportDeparture:
default:
BuildAirportDepartureGate();
break;
}
}
private void ConfigureTrigger(BoxCollider2D trigger) {
trigger.isTrigger = true;
trigger.offset = new Vector2(0f, 1.75f);
trigger.size = new Vector2(2.2f, 4.2f);
}
private bool TryBuildSpriteGate(FinishGateStyle style) {
string resourcePath = GetSpriteResourcePath(style);
if(string.IsNullOrEmpty(resourcePath))
{
return false;
}
Sprite sprite = LoadGateSprite(resourcePath);
if(sprite == null)
{
return false;
}
GameObject spriteObject = new GameObject("Finish Gate Sprite");
spriteObject.transform.SetParent(transform, false);
SpriteRenderer spriteRenderer = spriteObject.AddComponent<SpriteRenderer>();
spriteRenderer.sprite = sprite;
spriteRenderer.sortingLayerName = ForegroundSortingLayer;
spriteRenderer.sortingOrder = 6;
float targetHeight = GetSpriteGateHeight(style);
float spriteHeight = Mathf.Max(0.01f, sprite.bounds.size.y);
float scale = targetHeight / spriteHeight;
spriteObject.transform.localScale = new Vector3(scale, scale, 1f);
spriteObject.transform.localPosition = new Vector3(0f, targetHeight * 0.5f - GetSpriteGateBottomInset(style), 0f);
return true;
}
private Sprite LoadGateSprite(string resourcePath) {
Sprite sprite = Resources.Load<Sprite>(resourcePath);
if(sprite != null)
{
return sprite;
}
Sprite[] sprites = Resources.LoadAll<Sprite>(resourcePath);
if(sprites != null && sprites.Length > 0 && sprites[0] != null)
{
return sprites[0];
}
Texture2D texture = Resources.Load<Texture2D>(resourcePath);
if(texture != null)
{
return CreateRuntimeSprite(texture);
}
#if UNITY_EDITOR
string assetPath = "Assets/Resources/" + resourcePath + ".png";
sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
if(sprite != null)
{
return sprite;
}
texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
if(texture != null)
{
return CreateRuntimeSprite(texture);
}
#endif
return null;
}
private Sprite CreateRuntimeSprite(Texture2D texture) {
return Sprite.Create(
texture,
new Rect(0f, 0f, texture.width, texture.height),
new Vector2(0.5f, 0.5f),
RuntimeSpritePixelsPerUnit);
}
private string GetSpriteResourcePath(FinishGateStyle style) {
switch(style)
{
case FinishGateStyle.AirportDeparture:
return "FinishGate_Tutorial_Incheon";
case FinishGateStyle.JapanTorii:
return "FinishGate_Japan_Torii";
case FinishGateStyle.ChinaPaifang:
return "FinishGate_China_Paifang";
case FinishGateStyle.AmericaLiberty:
return "FinishGate_America_Liberty";
default:
return "";
}
}
private float GetSpriteGateHeight(FinishGateStyle style) {
switch(style)
{
case FinishGateStyle.ChinaPaifang:
return 4.65f;
case FinishGateStyle.AmericaLiberty:
return 4.45f;
default:
return 4.35f;
}
}
private float GetSpriteGateBottomInset(FinishGateStyle style) {
switch(style)
{
case FinishGateStyle.JapanTorii:
return 0.36f;
default:
return 0f;
}
}
private void BuildAirportDepartureGate() {
Color navy = new Color(0.05f, 0.2f, 0.34f, 1f);
Color blue = new Color(0.08f, 0.42f, 0.67f, 1f);
Color cyan = new Color(0.18f, 0.83f, 0.95f, 1f);
Color yellow = new Color(1f, 0.78f, 0.22f, 1f);
Color glass = new Color(0.6f, 0.9f, 1f, 0.55f);
CreateBlock("Airport Left Pillar", new Vector2(-1.15f, 1.45f), new Vector2(0.22f, 3.1f), navy, 3);
CreateBlock("Airport Right Pillar", new Vector2(1.15f, 1.45f), new Vector2(0.22f, 3.1f), navy, 3);
CreateBlock("Airport Top Sign", new Vector2(0f, 3.05f), new Vector2(2.75f, 0.64f), blue, 4);
CreateBlock("Airport Sign Highlight", new Vector2(0f, 3.35f), new Vector2(2.75f, 0.08f), cyan, 5);
CreateBlock("Airport Gate Floor", new Vector2(0f, -0.04f), new Vector2(2.9f, 0.12f), yellow, 4);
CreateBlock("Airport Glass Left", new Vector2(-0.62f, 1.35f), new Vector2(0.16f, 2.2f), glass, 2);
CreateBlock("Airport Glass Right", new Vector2(0.62f, 1.35f), new Vector2(0.16f, 2.2f), glass, 2);
CreateBlock("Airport Clear Light", new Vector2(0f, 2.55f), new Vector2(0.26f, 0.14f), yellow, 5);
CreateWorldText("DEPARTURE", new Vector2(0f, 3.07f), 0.34f, Color.white, 6);
}
private void BuildJapanTorii() {
Color red = new Color(0.86f, 0.08f, 0.05f, 1f);
Color darkRed = new Color(0.48f, 0.02f, 0.02f, 1f);
Color black = new Color(0.08f, 0.04f, 0.03f, 1f);
Color gold = new Color(1f, 0.76f, 0.28f, 1f);
CreateBlock("Torii Left Pillar", new Vector2(-1.18f, 1.35f), new Vector2(0.28f, 2.9f), red, 4);
CreateBlock("Torii Right Pillar", new Vector2(1.18f, 1.35f), new Vector2(0.28f, 2.9f), red, 4);
CreateBlock("Torii Left Base", new Vector2(-1.18f, -0.14f), new Vector2(0.48f, 0.22f), black, 3);
CreateBlock("Torii Right Base", new Vector2(1.18f, -0.14f), new Vector2(0.48f, 0.22f), black, 3);
CreateBlock("Torii Lower Beam", new Vector2(0f, 2.55f), new Vector2(2.75f, 0.24f), darkRed, 5);
CreateBlock("Torii Main Beam", new Vector2(0f, 3.05f), new Vector2(3.35f, 0.32f), red, 6);
CreateBlock("Torii Top Cap", new Vector2(0f, 3.31f), new Vector2(3.75f, 0.16f), black, 7);
CreateBlock("Torii Center Plaque", new Vector2(0f, 2.82f), new Vector2(0.36f, 0.5f), gold, 7);
}
private void BuildChinaPaifang() {
Color red = new Color(0.74f, 0.05f, 0.04f, 1f);
Color gold = new Color(1f, 0.72f, 0.18f, 1f);
Color roof = new Color(0.12f, 0.3f, 0.22f, 1f);
Color dark = new Color(0.24f, 0.04f, 0.03f, 1f);
CreateBlock("Paifang Left Pillar", new Vector2(-1.25f, 1.28f), new Vector2(0.28f, 2.8f), red, 4);
CreateBlock("Paifang Right Pillar", new Vector2(1.25f, 1.28f), new Vector2(0.28f, 2.8f), red, 4);
CreateBlock("Paifang Center Pillar Left", new Vector2(-0.42f, 1.48f), new Vector2(0.18f, 2.2f), dark, 3);
CreateBlock("Paifang Center Pillar Right", new Vector2(0.42f, 1.48f), new Vector2(0.18f, 2.2f), dark, 3);
CreateBlock("Paifang Sign", new Vector2(0f, 2.65f), new Vector2(2.45f, 0.46f), gold, 5);
CreateBlock("Paifang Roof", new Vector2(0f, 3.18f), new Vector2(3.25f, 0.26f), roof, 6);
CreateBlock("Paifang Roof Cap", new Vector2(0f, 3.42f), new Vector2(2.35f, 0.2f), roof, 7);
CreateBlock("Paifang Lantern Left", new Vector2(-0.78f, 2.18f), new Vector2(0.26f, 0.34f), red, 7);
CreateBlock("Paifang Lantern Right", new Vector2(0.78f, 2.18f), new Vector2(0.26f, 0.34f), red, 7);
}
private void BuildAmericaLibertyFallback() {
Color metal = new Color(0.48f, 0.56f, 0.58f, 1f);
Color green = new Color(0.03f, 0.38f, 0.22f, 1f);
Color yellow = new Color(1f, 0.8f, 0.18f, 1f);
Color white = Color.white;
CreateBlock("Road Sign Left Pole", new Vector2(-1.3f, 1.35f), new Vector2(0.18f, 3.0f), metal, 3);
CreateBlock("Road Sign Right Pole", new Vector2(1.3f, 1.35f), new Vector2(0.18f, 3.0f), metal, 3);
CreateBlock("Road Sign Panel", new Vector2(0f, 2.65f), new Vector2(3.05f, 0.9f), green, 5);
CreateBlock("Road Sign Stripe", new Vector2(0f, 2.25f), new Vector2(2.75f, 0.08f), white, 6);
CreateBlock("Road Sign Arrow", new Vector2(0f, 2.72f), new Vector2(0.5f, 0.16f), yellow, 7);
CreateWorldText("ARRIVAL", new Vector2(0f, 2.88f), 0.36f, white, 8);
}
private SpriteRenderer CreateBlock(string objectName, Vector2 localPosition, Vector2 size, Color color, int sortingOrder) {
GameObject block = new GameObject(objectName);
block.transform.SetParent(transform, false);
block.transform.localPosition = new Vector3(localPosition.x, localPosition.y, 0f);
block.transform.localScale = new Vector3(size.x, size.y, 1f);
SpriteRenderer renderer = block.AddComponent<SpriteRenderer>();
renderer.sprite = GetBlockSprite();
renderer.color = color;
renderer.sortingLayerName = ForegroundSortingLayer;
renderer.sortingOrder = sortingOrder;
return renderer;
}
private TextMeshPro CreateWorldText(string text, Vector2 localPosition, float fontSize, Color color, int sortingOrder) {
GameObject textObject = new GameObject("Gate Text " + text);
textObject.transform.SetParent(transform, false);
textObject.transform.localPosition = new Vector3(localPosition.x, localPosition.y, -0.05f);
TextMeshPro textMesh = textObject.AddComponent<TextMeshPro>();
textMesh.text = text;
textMesh.fontSize = fontSize;
textMesh.alignment = TextAlignmentOptions.Center;
textMesh.color = color;
textMesh.textWrappingMode = TextWrappingModes.NoWrap;
textMesh.rectTransform.sizeDelta = new Vector2(3f, 0.55f);
textMesh.renderer.sortingLayerName = ForegroundSortingLayer;
textMesh.renderer.sortingOrder = sortingOrder;
return textMesh;
}
private static Sprite GetBlockSprite() {
if(blockSprite != null)
{
return blockSprite;
}
Texture2D texture = new Texture2D(1, 1);
texture.SetPixel(0, 0, Color.white);
texture.Apply();
texture.wrapMode = TextureWrapMode.Clamp;
texture.filterMode = FilterMode.Point;
blockSprite = Sprite.Create(texture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 1f);
blockSprite.name = "Runtime Finish Gate Block";
return blockSprite;
}
private void ClearChildren() {
for(int i = transform.childCount - 1; i >= 0; i--)
{
Destroy(transform.GetChild(i).gameObject);
}
}
}