UniRun UI, GameManager, PlatformSpawner 추가

이정현
∙∙조회 1

20261021 UniRun UI, GameManager, PlatformSpawner 추가

Awake

GameObject가 Instantiate된 프레임에 실행되는것이 Awake이고 바로 다음 프레임에 실행되는 것이 Start이다. Start와 Update는 Component Script가 비활성화 되어있으면 실행이 안된다. 하지만 Awake는 Script가 비활성화 되어있어도 GameObject가 생성되면 실행된다.(GameObject 자체가 비활성화 되어있으면 실행되지 않는다.) 그러므로 생성자에 가까운것은 사실 Start가 아니라 Awake다. GameObject 자신한테 붙어있는 Component는 Awake에서, 다른 GameObject에 붙어있는것을 찾아오는것은 Start에서 찾아오는 것이 좋다. 생성되는 타이밍과 호출되는 타이밍이 어긋날 수 있기때문이다.

VS Code 빠른이동 참고

Ctrl + p를 눌러 검색창을 열고 원하는 Script명을 입력하면 빠르게 다른 Script로 이동할 수 있다.

Stretch

TMP(TextMeshPro)의 Rect Transform -> Anchors Preset의 Stretch기능은 부모를 기준으로 Anchors를 잡는 기능이다. 좌우 Stretch의 경우 기존의 Pos X와 Width가 Left와 Right로 변경되며 Left는 부모의 좌측 넓이로부터의 Offset값을 설정하고 Right는 부모의 우측 넓이로 부터의 Offset값을 설정하는것이다.

  • 양수로 입력하면 해당 값 만큼 거리를 벌려준다.

저번과 다른 방식의 SceneLoad

csharp
// Scene을 다시 Loading하는 예시
private void Update()
{
    if(isGameOver && Input.GetKeyDown(KeyCode.Space))
    {
        Scene scene = SceneManager.GetActiveScene();
        SceneManager.LoadScene(scene.name);
    }
}

OnEnable, OnDisable

OnEnable, OnDisable은 해당 GameObject와 Script가 활성/비활성화 될때 실행된다. 단 Script와 GameObject가 함께 활성화가 되어야 OnEnable이 실행되며 GameObject가 활성화 된 상태로 Script가 비활성화 되거나 Script가 활성화 된 상태로 GameObject가 비활성화 되어야 OnDisable이 한번 발생한다. Script의 활성/비활성과 GameObject의 활성/비활성이 따로 관리되기 때문에 만약 Script가 비활성화인 상태로 GameObject만 활성화 할 경우 Script는 여전히 비활성화 상태이기 때문에 OnEnable이 실행되지 않는다.

확률로 장애물 생성

미리 여러개의 Platform을 생성해놓고 생성한 Platform을 돌려쓰는 방식을 사용한다. 생성 후 일정 범위 혹은 시간이 지나면 해당 Platform을 비활성화 후 별도의 생성위치를 설정하여 해당 위치에서 다시 활성화 하는것을 반복하여 재사용 한다. 별도의 생성위치는 빈 GameObject로 위치를 만들어 놓은 후 시간의 범위를 설정해서 해당 범위 안에서 Platform을 Random한 시간으로 생성한다. 또한 각 Platform의 장애물을 미리 배치해놓고 Platform의 장애물들을 일정 확률로 활성/비활성화 하여 다양한 형태의 장애물을 설정할 수 있다.

csharp
// Random하게 Platform에 있는 장애물(obstacles)을 활성화 시키는 예시
// 할당 부분은 스킵
public GameObject[] obstacles;
public float obstaclesRatio = 0.3f;//확률설정.
private void OnEnable()
{
    stepped = false;

    foreach(var obstacle in obstacles)
    {
        // Random.Value는 Random.Range(0f, 1f);와 같다. 0.0f~1.0f 사이의 값을 반환한다.
        // 0.0f~1.0f까지의 Random한 값이 0.3f 보다 낮을 확률은 30%정도 된다.
        obstacle.SetActive(Random.value < obstaclesRatio);
    }
}

기존상태에서 볼 수 있는 버그와 수정방법

기존 상태에서는 Player가 Platform과 충돌만 하면 Jump횟수가 초기화 되기 때문에 Player가 밑으로 떨어지는 상태에서 Platform의 하단 혹은 옆면에 부딛혀도 Jump횟수가 초기화 된다. 이를 방지하기 위해 Platform의 상단에 충돌 했을 때만 Jump 횟수를 초기화 하기 위해서 법선을 사용한다.

3D에서의 Normalize(법선)

법선이란 Normal Vector가 면에 수직하는 값을 말한다. 3D에서 Mesh에 그림자를 생성하는 원리가 Normal Vector를 이용하는 것이다. Texture Map과 똑같은 크기의 Pixel Data에 Normal Vector값을 넣어놓은것이 NormalMap이다. Normal Vector를 이용해서 Collider의 윗면과 충돌 했을 때만 Jump횟수를 초기화 하도록 Jump횟수 초기화 조건에 추가해 주면 된다. collision에는 부딛힌 면에 대한 정보도 있다. 그 중 Normal Vector가 있으며 충돌체의 윗면과 비교해야 하기 때문에 Y값으로 비교한다.

csharp
// collision에서 Normal값 가져오는 방법 예시
private void OnCollisionEnter2D(Collision2D collision)
{
    // contacts는 충돌한 두 물체 사이의 접촉 지점 배열이다. [0]은 첫 번째 접촉 지점을 기리킨다.
    if(collision.collider.tag == "Platform" &&
        collision.contacts[0].normal.y > 0.7f)
    {
        jumpCount = 0;
        animator.SetBool("Grounded", true);
    }
}

모서리는 Normal Vector가 조금 기울었기 때문에 수직만 검사하는 1f이 아니라 좀더 범위를 넓게해서 확인하는 것이 필요하다. 0.7은 약 45도 각도(1.0/루트2, 1.0/루트2)의 좌표값을 구해서 나온값이다.