Ruya Games

4 - Collider2D와 RigidBody2D로 충돌 처리하기 본문

게임 개발 일지/블록 아케이드 게임

4 - Collider2D와 RigidBody2D로 충돌 처리하기

SadEvil 2023. 12. 1. 01:49

이제 구현해야 할 내용은 아래와 같습니다.

플레이어의 블록이 이동했을때 이동한 지점 아래의 블록 색상과 플레이어 블록의 색상이 같다면,
아래의 블록을 제거하고 블레이어 블록은 떨어진다.

 

그리고 현재 블록들의 기본 상태는 매 프레임마다 일정 값만큼 위로 올라가고 있고, transform.Translate로 구현되어 있습니다.

그렇다면 동작은

 

  1. 플레이어 블록을 이동시킨다.
  2. 플레이어 블록의 이동이 끝났을때 아래 블록의 색상값을 확인한다.
  3. 색상값이 일치한다면 아래 블록을 제거한다.
  4. 일시적으로 transform.Translate의 동작을 멈추고, 플레이어 블록을 아래로 떨어지도록 한다.
  5. 플레이어 블록의 아랫면이 다른 블록과 닿으면 다시 다른 블록처럼 위로 상승하도록 한다.

이 순서로 동작해야 합니다.

 

1번은 구현했으니, 2번부터 구현해보겠습니다.

 


2. 플레이어 블록의 이동이 끝났을때 아래 블록의 색상값을 확인한다.

1번을 구현할때, 애니메이션이 종료되면 블록의 현재 x축 위치를 저장하는 인덱스값이 변경되도록 구현했는데요.

그 함수에 블록의 색상값을 서로 비교하는 조건문을 추가합니다.

public void SetBlockPosition(int index) {
  currentBlockPosition = index;
  //여기서 두 블록의 색상을 비교합니다.
  if(blocks[index].blockColor == playableBlock.currentBlockColor) {
    playableBlock.GravityOn();
    Destroy(blocks[index].gameObject);
  }
}

두 블록의 색상값이 같다면 3,4번 동작을 구현한 함수를 실행시킵니다.

 

3. 색상값이 일치한다면 아래 블록을 제거한다.

간단히 Destroy(blocks[index].gameObject) 로 제거하면 됩니다.

애니메이션을 추가하고싶다면 DoTween을 사용해서 애니메이션을 재생시킨뒤, OnComplete()로 Destroy()를 호출하면 됩니다.

(나중에 오브젝트 풀링을 사용해서 해당 내용을 추가 구현할 예정입니다.)

 

4. 일시적으로 transform.Translate의 동작을 멈추고, 플레이어 블록을 아래로 떨어지도록 한다.

이 프로젝트에서는 GravityOn()이라는 함수에서 해당 동작을 구현했습니다.

private void Update() {
  if(rising) transform.Translate(0,GeneralBlockSetting.BlockSpeed,0);
}

public void GravityOn() {
  rising = false;
  rigidBody.bodyType = RigidbodyType2D.Dynamic;
}

Update함수의 Translate에 조건문을 추가하여 rising 값에 따라 동작 여부를 제어합니다.

GravityOn()함수는 rising 변수를 false로 설정하고, 플레이어 블록의 rigidBody타입을 Dynamic으로 변경합니다.

rigidBody의 타입은 세 종류입니다.

 

  • Dynamic : 힘, 중력, 충돌 등 외부 물리적 요인의 영향을 받습니다.
  • Kinematic : 중력이나 충돌에 의한 영향을 받지 않으며 스크립트나 애니메이션에 의해 움직임이 결정됩니다.
  • Static : 움직이지 않는 개체에 사용. 중력이나 다른 힘의 영향을 받지 않으며, 다른 움직이는 개체와의 충돌만을 감지합니다. 물리 엔진의 제어에 영향을 받지 않습니다(질량이 무한하여 움직일 수 없는 오브젝트처럼 작동합니다).

따라서, Dynamic으로 bodyType을 변경해서 일시적으로 중력의 영향을 받도록 합니다.

 

5. 플레이어 블록의 아랫면이 다른 블록과 닿으면 다시 다른 블록처럼 위로 상승하도록 한다.

아래의 블록과의 충돌은 BoxCollider를 사용합니다.

private void OnTriggerEnter2D(Collider2D col) {
  if (col.CompareTag($"Block")) ReturnToRising(col.transform.localPosition);
}

private void ReturnToRising(Vector3 resetPosition) {
  rigidBody.bodyType = RigidbodyType2D.Static;
  transform.localPosition = new Vector3(resetPosition.x, resetPosition.y+GeneralBlockSetting.BlockSize, resetPosition.z);
  rising = true;
}

충돌한 collider를 CompareTag를 통해 블록 오브젝트인지 확인하고, 맞다면 ReturnToRising()함수를 실행시킵니다.

 

ReturnToRising함수는 플레이어 블록의 rigidBody타입을 다시 Static으로 변경합니다.

그렇게되면 블록 오브젝트가 갖고있던 속도값은 모두 적용되지 않고 그자리에 멈추게 됩니다.

그리고 블록의 position을 충돌한 블록의 바로 위로 세팅해준 뒤, rising을 true로 설정하게 되면 블록은 다시 위로 올라가게 됩니다.

 

 

아래는 최종 구현 결과입니다.