[Unity] Flappy Plane 개발-2

Connected Brain·2025년 2월 14일
post-thumbnail

Flappy Plane 만들기

모티프 : Flappy Bird

필요한 요소 정리

1. 사용할 Sprite 자르기
2. 비행기 조작

3. 장애물 배치
4. 장애물 및 배경 루프

3. 장애물 배치

public float highPosY = 1f;
public float lowPosY = -1f;

public float holeSizeMin = 1f;
public float holeSizeMax = 3f;

public Transform topObject;
public Transform bottomObject;

public float widthPadding = 4f;
  • 장애물을 생성하기 위한 변수이다. 위에서부터 장애물이 생성될 y 값의 범위, 두 장애물 사이 빈 공간의 너비의 최댓값과 최솟값, 위에 있는 장애물과 아래 있는 장애물, 마지막으로 장애물과 장애물 사이의 너비이다.
public Vector3 SetRandomPlace(Vector3 lastPosition, int obstacleCount)
{
    float holeSize = Random.Range(holeSizeMin, holeSizeMax);
    float halfHoleSize = holeSize / 2;

    topObject.localPosition = new Vector3(0, halfHoleSize);
    bottomObject.localPosition = new Vector3(0, -halfHoleSize);

    Vector3 placePosition = lastPosition + new Vector3(widthPadding, 0);
    placePosition.y = Random.Range(lowPosY, highPosY);

    transform.position = placePosition;

    return placePosition;
}
  • 장애물의 무직위 위치를 설정하는 함수이다.
  • 비행기가 통과할 수 있는 틈의 너비를 최댓값과 최솟값 사이의 무작위 값으로 정한다.
  • 해당 너비의 절반이 각각 위와 아래의 장애물의 원점이 될 위치 값이 된다.

(장애물은 각각 위와 아래에 원점(Pivot)이 위치하도록 미리 설정하였다.)

  • 이전 장애물이 있었던 위치에서 widthPadding만큼 떨어져서 장애물이 생성되어야 하므로 이전 위치 값의 x 값에 widthPadding을 더한다.
  • 이후 y 값의 최대, 최소 범위 내에서 무작위 값을 정해 이를 이후 생성될 장애물의 위치 값으로 반환한다.

4. 장애물 및 배경 루프

  • 장애물과 배경이 루프되는 기준은 Player를 따라오는 카메라에 자식 오브젝트인 BgLooper(BackGround Looper)와 충돌했는지를 검사하여 충돌하면 앞으로 이동하도록 한다. 이를 위해 BgLooper에 충돌했다는 것은 전달하지만 물리 계산은 하지 않도록 Rigidbody2D의 모드를 Kinematic으로 설정한다. 그리고 BoxCollider2D의 isTrigger를 true로 한다.
private void OnTriggerEnter2D(Collider2D collision)
{
    Debug.Log("Triggered " + collision.name);
    Obstacle obstacle = collision.GetComponent<Obstacle>();

    if (obstacle)
    {
        obstacleLastPosition = obstacle.SetRandomPlace(obstacleLastPosition, obstacleCount);
    }

}
  • 이후 충돌한 오브젝트에 Obstacle 클래스가 포함되어 있으면 이를 가져와 앞서 만든 SetRandomPlace 함수를 실행해 이미 지나친 장애물을 다시 앞으로 이동시키고 새로운 위치에 옮겨 놓는다.
  • 루프 해야할 것은 장애물뿐만이 아니라 배경도 포함된다. 이를 위해 위와 아래의 Ground 그리고 배경 이미지를 하나의 세트로 만들고, 이 세트에 태그를 "BackGround"를 설정해 아래의 코드를 통해 앞으로 이동하도록 하였다.
if (collision.CompareTag("BackGround"))
{
    BoxCollider2D collider2D = collision.GetComponent<BoxCollider2D>();
    float widthOfObject = collider2D.size.x;
    Vector3 pos = collision.transform.position;

    pos.x += widthOfObject * numBgCount;
    collision.transform.position = pos;
    return;
}
  • 앞에 적절한 위치로 이동시키기 위해 Collider의 사이즈를 가져오고, 이 크기에 백그라운드 세트 개수만큼 곱한 것을 기존 x 값에 더한 위치로 이동하도록 하였다.

Trouble Shooting!

  • 기존에는 다른 방식을 사용하였었다. 두 지면과 배경 이미지에 각각 태그를 할당하고 변경하도록 하였다. 그리고 각각에 isTrigger가 true인 BoxCollier2D를 두어 충돌 처리를 구현하였었다.
float widthOfObject = ((BoxCollider2D)collision).size.x;
Vector3 pos = collision.transform.position;

pos.x += widthOfObject * numBgCount;
collision.transform.position = pos;
return;
  • 충돌한 물체에는 BoxCollider2D가 있을 것이므로 캐스팅을 통해 BoxCollider2D로 형변환 하여 Collider의 사이즈 값을 받아와 이를 통해 계산하도록 하였다.

    InvalidCastException: Specified cast is not valid.
    BgLooper.OnTriggerEnter2D (UnityEngine.Collider2D collision) (at Assets/Scripts/BgLooper.cs:34)

  • 그랬더니 위와 같은 에러 코드가 전시되었다. 이는 지면 오브젝트에 포함된 PolygonCollider2D로 인한 것으로 확인할 수 있었다. PolygonCollider2D는 size 정보를 가지고 있지 않기 때문에 에러가 발생한 것으로 보인다.
  • 이를 해결하기 위해 위의 방식으로 변경하였다. PolygonCollider2D와 직접적으로 충돌 처리를 하지 않도록 하고, 그럼에도 배경 전체가 루프되도록 하기 위해 세트를 만들어 해당 세트가 반복될 수 있도록 하였다.

0개의 댓글