유니티 총알 Destroy - yuniti chong-al Destroy

GameObject 동적으로 삭제 하기

유니티에서 게임실행중에 GameObject 를 제거해야 할때가 있다.

예를 들면 총알이 몬스터에 맞았을 경우 총알을 제거해 줘야 한다. 

또 몬스터의 HP가 0보다 작아지면 몬스터 또한 제거해 줘야 한다.

Destroy (Object obj, t : float time= 0.0F)  함수를 이용하면 쉽게 제거할 수 있다.

obj 는 삭제할 대상 오브젝트 이며, time 은 Destroy 함수 호출후 몇초후에 삭제할지 결정한다.

코드

// 게임 오브젝트를 제거한다.

Destroy (gameObject);

// 게임오브젝트로부터 현재 스크립트를 제거 한다.

Destroy (this);

// 게임오브젝트로부터 강체를 제거합니다.

Destroy (rigidbody);

// 오브젝트 로드 후 5초 안에 게임오브젝트를 죽입니다.Kills the game object in 5 seconds after loading the object

Destroy (gameObject, 5);

// 사용자가 Ctrl키를 누를때, 스크립트를 제거 할것입니다. 

// 게임오브젝트의 FooScript라는 이름의

function Update () {

    if (Input.GetButton ("Fire1") && GetComponent (FooScript))

        Destroy (GetComponent (FooScript));

}

참고

http://www.devkorea.co.kr/reference/Documentation/ScriptReference/Object.Destroy.html

유니티 destroy vs 유니티 SetActive(false).

유니티 게임 오브젝트를 제거 삭제할때 어떻게 해야할까?

유니티 총알 Destroy - yuniti chong-al Destroy

1. 만약 게임 오브젝트가 재사용 되지 않는다면 삭제해야한다.

Destroy(gameObject);

2. 만약 게임 오브젝트가 재사용되면 삭제하지 않고 비활성화 시킨다.

gameObject.SetActive(false);

가장 좋은예로 투사체(총알), 특수 효과(FX)는 매우 자주 계속 반복되서 사용되므로

미리 만들어놓고 List에 넣어서 ON/OFF를 반복하며 꺼내쓰는 기법인 오브젝트 풀링을 사용하면 좋다.

왜냐하면 게임 오브젝트를 생성(Instantiate)하고 삭제(Destroy)하는 작업은 약간 고사양이며

잦은 생성과 삭제로 GC가 불려 프레임 감소를 일으킬 수 있기 때문이다.

반면 사용수가 적고 한번 사용후 게임 플레이와 전혀 관계 없어지는 물체.

좋은 예로 플레이어에게 사망한 적 유닛, 사용하지 않아서 꺼버린 장식물등이 있다.

이런것들은 되도록 [파괴] Destroy(게임 오브젝트); 를 써서 아예 씬에서 삭제해주면 씬에 오랫동안 머문다고 가정했을때의 퍼포먼스를 향상시키고 메모리 RAM 쪽에 부담을 줄여줄 수 있다.

단, 주의해야할 점은 Destroy 할시 레퍼런스들이 null이 되므로 != null 조건문을 꼼꼼하게 많이 써줘야한다.

유니티 총알 Destroy - yuniti chong-al Destroy

1. 총알 만들기 스크립트

유니티 총알 Destroy - yuniti chong-al Destroy

GameController.cs파일안에 총알을 복제하는 스크립트가 담겨 있던 Start( ) 함수 아래에 새로운 함수를 하나 만든다. 총알을 만드는 일을 할 MakeBullet( ) 함수이다.

유니티 총알 Destroy - yuniti chong-al Destroy

3편에서 작성했던 Start( ) 안에 들어있는 모든 스크립트를 MakeBullet( )함수 안으로 옴긴다. 결과적으로 이제 Start( ) 안에는 아무런 내용이 없는 상태가 된다.

유니티 총알 Destroy - yuniti chong-al Destroy

이제 총알을 생성려면 MakeBullet( )을 호출하여야 하고, 앱이 시작하자마자 총알을 바로 생성하려면 Start( )안에 MakeBullet( )을 작성하여 호출하면 된다.

스크립트 파일을 처음 생성하면 기본으로 들어있던 Start( )나 Update( )처럼 클래스 안에서는 언제든 원하는 함수를 만들어 사용할 수 있으며, 클래스내의 어떤 함수 안에서도 새로 만든 함수를 호출하여 작동시킬 수 있다. 마찬가지로 처음부터 있던 Start( )나 Update( )등은 필요없으면 지워도 된다.

유니티 총알 Destroy - yuniti chong-al Destroy

이 과정을 따라오는 동안 모든 스크립트 문장에 일정한 들여쓰기가 있는 것을 보았을 것이다. 이는 함수의 시작과 끝이 어디인지, 함수 안에서 어떤 깊이에 작성된 스크립트인지 알아보기 쉽게 하기 위한 것으로, 잘 보면 묶음이 되는 중괄호의 시작이 되는 문장과 끝나는 중괄호의 들여쓰는 위치가 동일한 공통점이 있다. 다행히도 비주얼 스튜디오같은 에디터들에선 묶음 단위로 시작과 끝 영역을 세로 줄로 은은하게 연결하여 나타내어 도움을 주기도 한다.

유니티 총알 Destroy - yuniti chong-al Destroy

유니티는 C# 스크립트의 내용을 실행할 때 위에서부터 한줄 한줄 실행한다. 하나의 함수내에 있는 스크립트는 당연히 위에서 부터 한줄 한줄 실행이 되겠지만, 클래스 내의 여러 함수들은 위에서부터 하나씩 실행되는 것이 아니라, 호출되는 순서로 실행이 된다. 이해를 돕기 위해 간단한 실험을 해보자.

위에는 Start( )와 PrintA( ) 두 개의 함수가 있다. 당연히 Start( )가 실행될 것이고, 첫 줄에 PrintA( )를 호출한다. 이제 다음실행 순서는 B를 출력하는 것일까. A를 출력하는 것일까.

유니티 총알 Destroy - yuniti chong-al Destroy

유니티를 실행하여 결과를 보면 A, C, B의 순서로 출력된다. Start( )에서 PrintA( )를 호출하면, PrintA( )안에 담겨있는 스크립트가 모두 실행되고나서야 Start( )의 다음줄로 넘어가 실행시키는 것을 알 수 있다. 이 순서를 잘 기억하여 추후 복잡한 스크립트의 오류를 방지하자.

유니티 총알 Destroy - yuniti chong-al Destroy

스크립트 파일을 처음 생성했을 때 이미 작성되어 있던 Start( )함수의 바로 윗줄에 회색 문장이 쓰여있다. 문장의 맨 앞에 있는 2개의 슬래시는 그 뒤의 한 줄 전체를 주석으로 만든다. 이렇게 주석으로 만들어진 문장은 유니티에서 실행을 하지 않는, 무시하는 문장이 된다. 위에처럼 MakeBullet( )앞에 슬래시를 두 개 넣어 주석으로 만들면 이제 더이상 총알은 생성되지 않을 것이다.

아무튼 위의 Start( )에 MakeBullet( )함수를 적었으면 실행을 하여 총알이 잘 생성되는지 확인한다.

2. 총알 반복하여 만들기

유니티 총알 Destroy - yuniti chong-al Destroy

InvokeRepeating(호출할 함수 이름 문자열, 지연시간, 반복시간)은 반복적으로 함수를 호출 해준다. 지금까지 함수 호출을 할 때에는 함수명 + 소괄호를 이용해 왔는데, InvokeRepeating( )을 이용해 반복적으로 함수를 호출할 때에는 함수명을 문자열로 전달해야한다. 위와같이 MakeBullet을 큰 따옴표로 감싸 문자열로 전달하고, 그 뒤에는 InvokeRepeating을 호출하고 얼마나 있다가 MakeBullet을 호출할지의 지연시간을 그리고 마지막에는 반복적으로 호출하는 시간 간격을 초단위의 수치로 전달한다.

숫자를 바꿔 실행해보면서 어떻게 작동되는지 이해해보자.

유니티 총알 Destroy - yuniti chong-al Destroy

3. 총알 소멸

유니티 총알 Destroy - yuniti chong-al Destroy

총알이 1초마다 만들어지고 있으므로, 100초 뒤엔 100개가 1,000초 뒤엔 1,000개의 총알이 서로 다른 방향으로 무한히 날아가게 된다. Hierarchy에 bullet(Clone)의 개수가 계속 늘어나는 것이 보이는데, 이대로라면 총알이 많아질 수록 CPU는 연산할 것이 많아져 갈수록 느려진다. 물론 뭐 100개쯤 되었다고 못해먹을 만큼 느려지는 것이 아니겠지만, 불필요한 연산을 줄이려면 화면을 벗어나 쓸모가 없어진 총알 게임오브젝트는 삭제해야 한다.

Destroy(제거할 게임오브젝트, 지연시간) 함수는 게임오브젝트를 제거한다. bullet프리팹에 콤포넌트로 사용되고 있는 Bullet.cs의 Start( ) 맨 마지막 줄에 Destroy( ) 함수를 추가한다. 소괄호 안에 전달하는 내용은 파괴할 게임오브젝트와 Destroy( )가 호출된 때부터 제거할 때까지 대기하는 시간이다. 파괴할 게임오브젝트로 소문자로 시작하는 gameObject를 전달하는데, 이미 한 번 언급했던대로 이 스크립트가 콤포넌트로 사용되고 있는 게임오브젝트를 의미한다.

따라서 총알이 생성되고 Start( )함수가 실행되면, 위치를 정해주는 각 변수에 값을 대입한 후 5초 후에 사라지도록 예약하는 셈이다.

유니티 총알 Destroy - yuniti chong-al Destroy

실행해보면 hierarchy에 등록되는 bullet(Clone)이 제한적임을 확인할 수 있다. 생성된 총알은 5초동안 날아가다 소멸하므로 5초 뒤부터는 같은 수의 총알이 유지된다. 5초의 시간동안 화면밖으로 총알이 벗어나지 못하고 소멸되는 것도 보인다. 화면안에서 이유없이 총알이 사라지지 않도록 시간은 적절하게 조절하자.

4. 미리해보기

1. 더 빠르고 느린 총알들이 한 화면에 날아가도록 만들어보자.
2. 스크립트 내용 사이사이에 코드의 내용을 설명하는 주석을 넣어보자.

이 시리즈가 도움이 되셨다면 구독과 공감 부탁드립니다.이 시리즈가 계속 될 수 있는 힘이 됩니다.


InvokeRepeating( ) : docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.html
Destroy( ) : docs.unity3d.com/ScriptReference/Object.Destroy.html 

유니티 강좌 5 - 총알 피하기 5/9. 버튼 이벤트와 Canvas

아래 내용은 4편에서 이어집니다. 1편 : boxwitch.tistory.com/180 4편 : boxwitch.tistory.com/184 Button 오브젝트와 Canvas 플레이어를 이동시킬 조이스틱은 아날로그 스틱형태로 만들기엔 내용이 아직 복잡..

boxwitch.tistory.com

유니티 총알 Destroy - yuniti chong-al Destroy