본문 바로가기

취미로 하는 게임코딩_gameCodingAsHobby/유니티unity로 게임 만들기

유니티21_게임 제작 과정 05_충돌 설정

적 소멸

 

앞 글에 이어서 Enemy가 총알을 맞고 health값이 0 이 되면 소멸(죽음)하도록 만들어 본다.

 

 

17번~20번줄

적이 데미지(손상)을 입으면 health값이 감소한 후 if 조건문을 만들어서 0 이하가 될 때 실행할 코드를 만든다.

health값이 0보다 작거나 같으면 Die( )메서드를 실행하도록 한다.

*Die : 죽다

 

Die( )메서드가 없기 때문에 30번줄에 메서드를 만든다.

 

30번~33번줄

반환값이 없는 void 타입의 Die메서드가 호출되면 앞에서 총알을 없앨 때 사용했던 Destroy( ) 메서드를 사용한다.

여기서 gameObject는 현재 스크립트의 클래스의 Enemy 객체가 된다.

this는 이전 글 '상속'에서 설명했다.

this를 생략해도 된다.

 

스크립트를 저장한 후 실행해서 health 값이 0 이 되었을 때 사라지는 지 확인한다.

 

Ship 손상

 

플레이어의 Ship도 Enemy와 같은 방식으로 손상을 입도록 코드를 작성한다.

Ship 스크립트를 새로 만들어서 게임오브젝트 Ship에 연결한다.

 

 

Enemy 스크립트와 비슷한 내용이다.

 

23번줄

충돌이 생기면 health값 10 감소하고 상대방 게임오브젝트를 파괴한다.

 

스크립트를 저장한 후 컴퍼넌트로 추가하고, 충돌 처리를 위한 Circle Collider 2D 컴퍼넌트도 추가한다.

 

실행하면 어떤 문제가 생기는가?

총알이 발사되지 않는다. 정확히 말하면 발사하자 마자 파괴(destroy)된다.

짐작하겠지만 Ship에 충돌을 처리하는 Collider 컴퍼넌트를 장착하고, 코드에서 충돌이 일어나면 상대방 게임오브젝트를 파괴하라는 코드를 만들었기 때문이다.

 

문제 해결

 

이 문제를 해결하려면 충돌이 일어났을 때 상대가 어떤 오브젝트인지 알아내야 한다.

유니티에서는 Tag (태그) 기능이 있다.

Tag가 '꼬리표'라는 뜻이므로 Tag에 이름을 붙이면 자신이 어떤 게임오브젝트인지 알려주는 역할을 한다.

위 Ship오브젝트의 경우 현재 Untagged(꼬리표 없음)으로 설정되어 있다.

 

 

Ship에 태그를 붙인다.

Add Tag(태그 추가)를 클릭한다.

 

+버튼을 누른다.

 

Ship을 입력하고 Save(저장) 버튼을 누른다.

 

Hierarchy창에서 다시 Ship오브젝트를 선택한 후 Inspector창 Tag에서 Ship을 선택한다.

 

추가로 Bullet Prefab에 Bullet 태그를, Enemy에는 Enemy 태그를 추가한다.

Bullet태그의 경우는 Prefabs폴더에 있는 Bullet을 더블클릭한 후 Bullet 태그를 만들어 추가한다.

 

 

Tag 확인

 

각 게임오브젝트에 Tag(태그)를 달아준 후에 코드에서 태그를 확인할 때는 CompareTag( ) 메서드를 사용한다.

*compare : 비교하다

 

스크립트 Ship에서 OnCollisionEnter2D( ) 메서드 코드에 다음과 같은 내용으로 수정한다.

 

'만약 게임오브젝트 태그 문자열이 Enemy라면, health값을 10 감소하고 상대방 게임오브젝트를 파괴한다.'

 

Ship.cs 스크립트를 위와 같이 수정하면 충돌했을 때 Tag를 비교해서 "Enemy"라는 태그를 달고 있는 게임오브젝트일 때만 TakeDamage 메서드와 Destroy 메서드가 실행된다.

 

스크립트 Enemy에서는 태그가 Bullet일 때만 OnCollisionEnter2D메서드가 실행 되도록 수정하자.

 

스크립트를 저장한 후 실행해서 Bullet이 제대로 발사되는 지 확인한다.

 

health 변수 캡슐화

앞에서 배운 캡슐화를 Enemy스크립트로 연습 해본다.

 

health변수값은 변경되거나 접근이 자유로우면 안되는 변수이므로 private으로 설정해서 보호하는 것이 좋다.

위 코드에서 변수 health는 접근제한자가 붙어있지 않다.

이렇게 접근제한자를 붙이지 않고 생략한 경우, 변수(필드)는 같은 클래스 안에서만 접근 가능한 private으로 자동 설정된다고 했다.

 

만약 private으로 접근 제한 상태를 유지한 채 health 값에 접근하게 하려면 property(프라퍼티, 속성)이라는 접근자를 이용한다고 캡슐화에서 배웠다. 이 프라퍼티를 필드 health에 적용해보자.

 

 

9~13번줄

이와같이 프라퍼티를 만들어 놓으면 다른 곳에서 health필드에 접근해서 get접근자로 값을 읽거나 set접근자로 값을 변경할 수 있다. 여기서는 값을 변경하면 안되므로 set메서드를 삭제한다.

 

이제 private으로 설정된 필드health는 프라퍼티(속성)를 통해서 값을 읽을 수만 있다.

 

TakeDamage 오버로드

위에서 작성했던 TakeDamage( )메서드로 다형성의 오버로드(overload)를 어떻게 활용하는 지 알아본다.

 

이 메서드는 int타입의 값을 매개변수로 받아서 필드health값에서 뺀 후 다시 health에 저장하고 만약 0보다 작아지면 Die메서드를 실행한다.

 

그런데 추가로 정수가 아닌 '비율(ratio)'로 health값을 줄이는 메서드가 필요하다면 오버로드를 이용하여 다음과 같이 코드를 작성할 수 있다.

 

 

이렇게 하면 TakeDamage( )메서드가 호출되었을 때 인수가 정수값 또는 실수값(소수)이냐에 따라 자동으로 해당 메서드가 실행된다.

(int)(health * ratio)는 health값에 비율을 곱한 후 int(정수)로 명시적 타입 변환을 나타낸다.

 

 

끝.

Wraven...