카테고리 없음

0813 유니티(8번출구 순환구조)

버스창문 2025. 8. 13. 18:01

8번출구라는 게임은 거꾸로 돌아가도 뒤부터 시작하는게 아닌 정상적으로 앞에서부터 시작하게 된다.

이상이 생겨 뒤로 돌아갔든, 이상이 없어 앞으로 그대로 갔든 반드시 이 방향으로 시작하게 된다.

이 구조를 만들어본다.

 

 

_____________________________________________________________________

1. 입장 방향 감지

BoxCollider는 내가 들어온 방향은 감지해주지 않는다.

즉 그냥 TriggerExit를 쓰면 내가 들어가다가 나갔을 경우에 로직이 꼬이게된다.

 

이를 해결하기 위해 Trigger를 2개를 깐다

public class TriggerCube : MonoBehaviour
{
    //통과해서 밖으로 나간걸 체크해야한다
    //그대로 뒤로 돌아간건 체크되면 안된다

    public bool Check { get; private set; }
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            this.Check = true;
        }

    }
    private void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            this.Check = false;
        }
    }

}

만약 내가 왼쪽으로 입장한다면, 왼쪽의 트리거가 true가 될거고 오른쪽은 false일것이다.

그대로 쭉 가면 둘다 true가 됐다가,

왼쪽이 먼저 false가 됐다가 오른쪽이 false가 되야한다.

 

만약 오른쪽이 true조차 되지않았거나,

둘다 true가 됐는데 오른쪽이 먼저 false가 됐다면, 갔다가 나온것이다.

    IEnumerator CheckRoutine()
    {
        while (true)
        {
            while (!cubes[0].Check && !cubes[1].Check)
            {
                yield return null; // 둘 중 하나가 활성화 될때까지 대기
            }
            var triggerCube = cubes.Find(c => c.Check); // Check가 true인 TriggerCube 찾기
            var targetCube = cubes.Find(c => !c.Check); // Check가 false인 TriggerCube 찾기
            Debug.Log("입장방향 체크 완료");
            while (triggerCube.Check && !targetCube.Check)
            {
                yield return null; // Check가 false가 되거나, targer도 true가 될 동안 대기
            }
            if (targetCube.Check)
            {
                while (targetCube.Check)
                {
                    yield return null; // targetCube가 true인 동안 대기
                }
                if (!triggerCube.Check)
                {
                    Debug.Log("통과했음");
                    // 이후에 들어갈 필드 셋팅 로직
                }
                else
                {
                    Debug.Log("도로 나갔음1");
                }
            }
            else
            {
                Debug.Log("도로 나갔음2");
            }
        }
    }

코루틴을 이용해 해당 상황을 표현한다.

정확히 반대쪽으로 나갔을때만 통과했음 로그가 뜨게 된다.

Turnel쪽에 위의 TriggerCube와 함께, 다음 맵이 셋팅될 위치, 다음 터널이 셋팅될 위치를 각각 잡는다

왼쪽으로 통과해서 나갔을 경우 저 아래쪽에 깔려야하고,

오른쪽으로 통과해서 나갔을 경우 저 위쪽에 깔려야한다.

 

즉 이 시점에서 어느 방향으로 통과했는가에 대한 idx값을 받아야할 필요가 생긴다

    IEnumerator CheckRoutine()
    {
        while (true)
        {
            while (!cubes[0].Check && !cubes[1].Check)
            {
                yield return null; // 둘 중 하나가 활성화 될때까지 대기
            }
            var triggerCube = cubes.Find(c => c.Check); // Check가 true인 TriggerCube 찾기
            var targetCube = cubes.Find(c => !c.Check); // Check가 false인 TriggerCube 찾기
            Debug.Log("입장방향 체크 완료");
            //나간 방향에 대한 idx값 받기
            int idx = cubes.IndexOf(targetCube);
            Debug.Log(idx);
            while (triggerCube.Check && !targetCube.Check)
            {
                yield return null; // Check가 false가 되거나, targer도 true가 될 동안 대기
            }
            if (targetCube.Check)
            {
                while (targetCube.Check)
                {
                    yield return null; // targetCube가 true인 동안 대기
                }
                if (!triggerCube.Check)
                {
                    Debug.Log("통과했음");
                    // 필드 셋팅 부분
                }
                else
                {
                    Debug.Log("도로 나갔음1");
                }
            }
            else
            {
                Debug.Log("도로 나갔음2");
            }
        }
    }

해당 idx를 활용할 수 있는 구조체를 만들고, 셋팅한다.

 

 

[System.Serializable]
public struct MapPos
{
    public Transform fieldPos;
    public Transform turnelPos;
}

이때, idx값은 정확하게 들어가야한다.

위쪽 부분에 맞춘건 오른쪽 TriggerCube의 idx값과 같아야하고, 아래쪽 부분에 맞춘건 왼쪽 TriggerCube의 idx값과 같아야한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public struct MapPos
{
    public Transform fieldPos;
    public Transform turnelPos;
}
public class TriggerTurnel : MonoBehaviour
{
    List<TriggerCube> cubes = new List<TriggerCube>();

    public MapPos[] mapPoses = new MapPos[2];

    public GameObject field;
    public GameObject turnel;

    private void Start()
    {
        this.GetComponentsInChildren<TriggerCube>(cubes);
        StartCoroutine(CheckRoutine());
    }
    IEnumerator CheckRoutine()
    {
        while (true)
        {
            while (!cubes[0].Check && !cubes[1].Check)
            {
                yield return null; // 둘 중 하나가 활성화 될때까지 대기
            }
            var triggerCube = cubes.Find(c => c.Check); // Check가 true인 TriggerCube 찾기
            var targetCube = cubes.Find(c => !c.Check); // Check가 false인 TriggerCube 찾기
            Debug.Log("입장방향 체크 완료");
            int idx = cubes.IndexOf(targetCube);
            Debug.Log(idx);
            while (triggerCube.Check && !targetCube.Check)
            {
                yield return null; // Check가 false가 되거나, targer도 true가 될 동안 대기
            }
            if (targetCube.Check)
            {
                while (targetCube.Check)
                {
                    yield return null; // targetCube가 true인 동안 대기
                }
                if (!triggerCube.Check)
                {
                    Debug.Log("통과했음");
                    this.field.transform.position = mapPoses[idx].fieldPos.transform.position;
                    this.turnel.transform.position = mapPoses[idx].turnelPos.transform.position;
                    this.field.transform.rotation = mapPoses[idx].fieldPos.transform.rotation;
                    this.turnel.transform.rotation = mapPoses[idx].turnelPos.transform.rotation;
                }
                else
                {
                    Debug.Log("도로 나갔음1");
                }
            }
            else
            {
                Debug.Log("도로 나갔음2");
            }
        }
    }
}

통과한 경우에만 위치값을 idx값에 맞춰 셋팅한다.

 

이렇게하면 8번출구식 구조가 완성된다.

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.