밝으면 죽는 대미지 블록을 만듭니다. 새로운 게임오브젝트를 만들어 "Dead" Tag를 붙여주면 됩니다.

  • 대미지 블록의 외관은 바늘
  • 양 옆에서 접축하면 대미지 없이 충돌
  • 위에서 접촉시만 대미지 (게임오버)

 

바늘 대미지 블록 만들기

대미지 블록을 위한 바늘 이미지는 에셋인 needle을 씬뷰나 하이라키고 드래그 드롭으로 추가합니다.

Sprite Render컴포넌트의 Order in Layer값을 2로 합니다.

인스펙터 뷰에서 Add Component>Physics 2D를 선택한 후 Box Collider 2D를 두개 어태치해 양옆으로 벽처럼 배치합니다.  플레이어의 진행을 벽처럼 막을 목적이므로 isTrigger는 체크하지 않습니다.(체크하면 통과해버립니다.)

하이라키뷰에서 needle의 자식으로 Create Empty한후 이름을 DeadZone으로 하고 BoxCollider 2D를 추가하고 isTrigger를 체크합니다. 범위는 가운데쪽으로 해서 위에서 떨어지는 접촉을 감지합니다.

needle 을 Prefab폴더로 끌어다 prefab으로 만듭니다.

 

낙하하는 대미지 블록 만들기

images폴더에서 block1x1을 씬뷰에 끌어다 이름을 GimmickBlock으로 변경합니다. Sprite Renderer컴포넌트의 Order in Layuers는 2로 변경, Layer값은 Ground로 해서 캐릭터가 올라탈수 있도록 합니다.

Box Collider 2D를 추가하고 아래쪽을 살짝 올려줍니다.

지면과의 접촉은 CircleCollider2D를 추가합니다. 지면과의 마찰을 줄여 매끄럽게 이동하기 위해서입니다.   플레이어가 밀수 있게 Rigidbody2D를 추가하고 넘어지지 않게 Freeze Rotation Z를 체크하고 25로 설정합니다.

떨어지다가 플레이어와의 접촉을 담당할 새로운 빈오브젝트를 만들어 이름을 DeadZone으로 바꾸고 GimmickBlock의 자식으로 만들고 Tag를 Dead로 설정합니다.  Box Collider 2D를 추가하고 위치를 아래로 약간 내리고 IsTrigger를 체크해서 플레이어의 검출을 담당합니다.

장애물 블록과 식별을 용이하게 하기 위해 컬러아이콘을 붙입니다. 인스펙터뷰 맨위좌측을 눌러보면 아이콘을 선택할 수 있습니다. 부탁후 씬쀼에서 이름을 확인할 수 있습니다. 게임중에는 표시되지 않습니다.

공중에 배치하면 낙하하고 플레이어와 충돌하면 게임 오버가 되면 지면에 배치하면 플레이어가 밀어서 움직일 수 있고 올라탈수 있는 블록이 완성되었습니다.

 

대미지 블록을 낙하시키는 스크립트 만들기

GimmickBlock에 다음 기능을 추가하는 스크립트를 추가해봅니다.

플레이어가 일정 거리 안에 들어가면 떨어진다.

낙하 후에는 점점 사라진다.(변수로 시간을 정의할 수 있음)

GimmickBlock.cs의 코드 입니다.

변수 : 낙하와 페이드아웃 시간을 정의하고 있습니다.

public float length = 0.0f;     // 자동 낙하 탐지 거리
public bool isDelete = false;   // 낙하 후 제거할지 여부

bool isFell = false;            // 낙하 플래그
float fadeTime = 0.5f;          // 페이드 아웃 시간

Start()  : 게임 시작시 낙하할 블록을 Static으로 만들어 못 움직이게 만듭니다.

void Start() {
    // Rigidbody2D 물리연동 정지
    Rigidbody2D rbody = GetComponent<Rigidbody2D>();
    rbody.bodyType = RigidbodyType2D.Static;
}

Update() : 플레이어와의 거리를 계산해서 bodyType을 Dynamic으로 바꿔 떨어지게 만듭니다.

블록이 바닥에 떨어져 있는 상태라면 faceTiem을 카운트다운하면서 서서히 투명도를 바꿔줍니다. 0이 되면 제거합니다.

void Update(){
        GameObject player = GameObject.FindGameObjectWithTag("Player"); // 플레이어 찾기
        if (player != null) {
            // 플레이어와의 거리 계산
            float d = Vector2.Distance(transform.position, player.transform.position);
            if (length >= d) {
                Rigidbody2D rbody = GetComponent<Rigidbody2D>();
                if (rbody.bodyType == RigidbodyType2D.Static) {
                    // Rigidbody2D물리 연동 시작
                    rbody.bodyType = RigidbodyType2D.Dynamic;
                }
            }
        }
        if (isFell){
            // 낙하
            // 투명도를 변경해여 페이드 아웃 효과
            fadeTime -= Time.deltaTime; // 이전 프레이과의 차이만큼 시간 차감
            Color col = GetComponent<SpriteRenderer>().color;   // 컬러 값 가져오기
            col.a = fadeTime;   // 투명도 변경
            GetComponent<SpriteRenderer>().color = col; // 컬러 값을 재설정
            if (fadeTime <= 0.0f){            
                Destroy(gameObject); // 0보다 작으면(투명)제거
            }
        }
    }

OnCollisionEnter2D() 충돌은 바닥과 생기므로 오브젝트 검사는 하지 않습니다. 바닥에 떨어지면 isFell이 true로 바꿔줍니다.

void OnCollisionEnter2D(Collision2D collision) {
    if (isDelete){
        isFell = true; // 낙하 플래그 true
    }
}

스크립트를 GimmickBlock에 어태치하고 Lengh를 2정도로 해줍니다. 플레이어와 블록의 거리가 2이하이면 떨어지게 만들어 줍니다. isDelete도 체크해줘 땅에 떨어지면 사라지게도 해봅니다. 이걸 안하면 화면이 스크롤 되면서 블록이 왼쪽에 부디치면 어색하게 밀립니다.

블록이 2이상 높이 배치되어 있을 경우 블록이 떨어지지 않습니다. 거리d를 x만 계산해서 높이가 높아도 x축으로 다가가면  떨어지게 만들어 봤습니다. 이건 게임의 상황에 따라 적절히 조절해보시면 됩니다.

float d = Mathf.Abs( transform.position.x- player.transform.position.x);

완성된 GimmickBlock을 프리팹으로 만들어 씬에 몇개더 배치해 봅니다. 

+ Recent posts