이 글은 PC 버전 TISTORY에 최적화 되어있습니다.
서론
이 포스트에서는 Cocos Creator의 충돌 시스템을 소개합니다. Creator는 쉽고 간편하게 원형, 사각형, 폴리곤을 이용해 충돌 체크를 할 수 있도록 해줍니다. 어떻게하느냐 바로 Collision 체크가 필요한 Node에 Collider Component를 달아주는 것 입니다. 이런 방법은 유니티의 Rigid Body를 달아 중력 체크, 가속도, 충돌 후 튕김 같은 것을 제공하지는 않습니다. 단지 충돌 체크만을 해줍니다.
1. Collider 컴포넌트2. Collision Group3. Collision Scripting4. 예제5. 예제2
목표
오늘의 목표는 아래 움짤을 완성하는 것입니다.
이를 통해 배우게 될 것들은 다음과 같습니다.
1. Collider 종류2. Collision Component3. Collision Scripting으로 충돌에 대한 콜백 처리
Collider 컴포넌트
(오른쪽 마우스 클릭 후 저장해서 사용하세요)
위의 별을 텍스쳐로 하는 Sprite 를 화면에 만들어줍니다. 그리고 Properties 탭에서 Add Component - Add Collider Component에서 Box Collider, Circle Collider, Polygon Collider를 차례로 붙여줍니다.
먼저 Polygon Collider를 보도록 하죠. node에는 여러 collider를 붙여줄 수 있습니다. 충돌이 일어났을 때 tag 프로퍼티를 통해서 충돌체를 판단할 수 있습니다. editing는 체크할 시 충돌체의 모양을 마음대로 지정할 수 있도록 합니다.
Polygon Collider
Polygon Collider의 점들을 드래그로 옮겨서 다음과 같이 만들어 줍시다. 점이 부족하다면 Points 프로퍼티의 값을 바꿔주면 늘어납니다.
또한 Polygon Collider는 threshold를 지정하고 Regenerate Points를 이용해서 Automatically하게 점을 잡아줍니다. threshold가 낮을 수록 정밀하게 나타냅니다.
<threshold 8일 때>
<threshold 1일 때>
Circle Collider
Circle Collider의 Editing을 체크하면 다음과 같이 Gizmo (Node를 조작할 수 있게 해주는 UI)가 나타납니다. 원 내부를 클릭 후 움직일 수 있습니다. 원의 좌우상하에 4개의 점이 있습니다. 점을 드래그하면 Collider의 지름을 줄이거나 키울 수 있습니다.
Box Collider
이것도 비슷하게 동작하니 자유자재로 움직여보도록 합니다.
Collision Group
위에서 충돌 체크를 할 수 있는 몸체를 Collider Component 만들었습니다. 그 다음 스텝은 어떤 그룹과 충돌체크가 될지 정하는 기능인 Collision Group을 설정하도록 하겠습니다. 이 기능은 매번 모든 Collider들이 충돌 체크를 하지 않고 지정된 Collider들끼리만 충돌체크를 함으로써 성능을 향상시킬 수 있습니다.
Collider들을 카테고리해봅시다. Project - Project Settings... - Group Manager로 가보면 아래와 같이 Group List 파트가 보일 것입니다.
Group Manager 안에서 우리는 새로운 그룹을 추가하거나 이미 있는 그룹의 이름을 바꿀 수 있습니다. Group은 삭제할 수 없으니 신중하게 추가하도록 합시다.
자 이제 우리는 Collider들을 구분한 그룹을 만들었습니다. 플랫폼 액션 게임이라는 가정하에 기본적으로 actor, platform, bullet, item 등이 있을 것입니다. 그럼 우리는 actor와 item, bullet 그리고 platform이 충돌하길 원할거고 actor끼리는 충돌하지 않도록 만들고 싶을 것입니다.
아래의 맵에서 열과 행을 참고하여 충돌할 그룹과 충돌 안할 그룹을 지정할 수 있습니다. 다 셋팅한 후에는 save를 눌러줘야지만 저장이 되니 주의하시길 바랍니다.
체크된대로 서로 충돌할 수 있는 그룹은 다음과 같습니다.
Actor - Item, bullet, platform
Platform - Item, bullet
위에서 add한 그룹을 Collider 노드들에 다음과 같이 적용할 수 있습니다. Node의 group 프로퍼티를 통해 star를 actor 그룹에 platform을 ground 그룹으로 지정합시다. 그렇게 되면 Collision Map에서 Collider 끼리는 충돌체크를 하기로 했으니 별과 흰색 바는 서로 맞닿았을 때 충돌 체크를 할 수 있게 되는겁니다.
Collision Scripting
Cocos Creator는 내장 된 Collision Detection System을 사용하는 간단하고 쉬운 방법을 제공합니다. 추가 된 Collider에 따라 Collision detection를 수행합니다. Collider가 Enabled되면 Collider 구성 요소가 Collision Detection System에 자동으로 추가되고 충돌체크 하기로 한 Collider들이 충돌 한 것을 체크해서 충돌한 쌍에게 각각 정보를 알려줍니다.
NOTE : 동일한 노드에있는 Collider Components 여러개 추가해도 서로 충돌 감지를 하지 않습니다.
Collision Detection System은 다음의 코드로 가져올 수 있습니다.
var manager = cc.director.getCollisionManager();
Collision Detection System는 기본적으로 사용하지 않도록 설정되어 있습니다. 사용하려면 아래와 같이 enabled 프로퍼티를 true로 바꿔줘야 합니다.
manager.enabled = true;
Debug Draw는 기본적으로 사용하지 않도록 설정되어 있으므로 Collider의 범위나 정보를 확인해야하는 경우 enabledDebugDraw 프로퍼티를 true로 설정해주세요.
manager.enabledDebugDraw = true;
Debug Draw를 활성화 하면 아래와 같이 런타임시 Collider의 영역을 볼 수 있습니다 :
Collider Component의 경계 상자를 표시하려 다음과 같이 enabledDrawBoundingBox
프로퍼티를 true로 설정해줍니다.
manager.enabledDrawBoundingBox = true;
결과 :
충돌이 감지되면 Collision Manager는 콜백을 호출합니다. Collider 컴포넌트가 있는 노드에 아래와 같이 스크립팅을 하면 Collider 컴포넌트의 충돌에 대한 콜백이 들어옵니다. 콜백의 종류는 다음과 같이 3가지 종류가 있습니다. (onCollisionEnter, onCollisionStay, onCollisionExit)
/**
* collision이 발견되었을 때 호출됨
* @param {Collider} other 충돌한 Collider
* @param {Collider} self 내 Collider
*/
onCollisionEnter: function (other, self) {
console.log('on collision enter');
// Collider Manager는 world 기준으로 조정된 정보를 world 프로퍼티에 넣어 놓습니다.
var world = self.world;
// 현재 Collider Component aabb 바운딩 박스입니다. (AABB는 아래에서 다룹니다.)
var aabb = world.aabb;
// 가장 최근 Collider Component aabb bounding box (aabb의 바로 전 타임의 aabb입니다.)
var preAabb = world.preAabb;
// world transform
var t = world.transform;
// Circle Collider Component world 프로퍼티
var r = world.radius;
var p = world.position;
// Rect, Polygon Collider Component world 프로퍼티
var ps = world.points;
},
/**
* collision이 호출된 후 그리고 collision이 끝나기 전 까지 매 time마다 collision 결과를 반환함
* @param {Collider} other 충돌한 Collider
* @param {Collider} self 내 Collider
*/
onCollisionStay: function (other, self) {
console.log('on collision stay');
},
/**
* collision이 끝난 후 호출됨
* @param {Collider} other 충돌한 Collider
* @param {Collider} self 내 Collider
*/
onCollisionExit: function (other, self) {
console.log('on collision exit');
}
예제
자 오늘의 목표였던 아래의 프로젝트를 만들어보도록 하겠습니다.
1. 먼저 두 개의 별을 만들어 다음의 코드를 붙여 회전시킵니다.
cc.Class({
extends: cc.Component,
properties: {
moveSpeed: 100,
rotationSpeed: 90
},
update: function (dt) {
this.node.x += dt * this.moveSpeed;
this.node.rotation += dt * this.rotationSpeed;
},
});
2. 두 개의 별에 Collision Component를 3가지 달아줍니다. (Polygon, Circle, Box) 그리고 별이 돌아갈 때 충돌이 될만큼 거리를 조정해줍니다.
3. Collision을 체크해주는 Script를 두 별에 달아줍니다. 충돌이 시작되면 별을 빨갛게 충돌이 끝나면 돌아오도록 코딩해주세요.
cc.Class({
extends: cc.Component,
onLoad: function () {
cc.director.getCollisionManager().enabled = true;
cc.director.getCollisionManager().enabledDebugDraw = true;
this.touchingNumber = 0;
},
onCollisionEnter: function (other) {
this.node.color = cc.Color.RED;
this.touchingNumber ++;
},
onCollisionStay: function (other) {
console.log('on collision stay');
},
onCollisionExit: function () {
this.touchingNumber --;
if (this.touchingNumber === 0) {
this.node.color = cc.Color.WHITE;
}
}
});
4. 각 별의 3가지 Collider를 끄고 켤 수 있는 버튼을 만들고 콜백을 달아줍니다. (이 부분은 어렵지 않으니 여기서 다루지 않겠습니다. 참고)
여기까지 완성하셨으면 움짤과 같은 충돌 체크를 테스트해보실 수 있을 것 입니다.
예제2
이번에는 충돌체를 터치했을 때 충돌체인지를 탐지하는 예제입니다.
터치한 부위가 충돌체인지를 탐지하여 Hit인지 Not Hit인지를 title이라는 라벨에 뿌려줍니다. 터치한 위치와 polligon Collider를 이용하는 방법입니다.
cc.Class({
extends: cc.Component,
properties: {
collider: {
default: null,
type: cc.PolygonCollider
},
title: {
default: null,
type: cc.Label
}
},
onLoad: function () {
cc.director.getCollisionManager().enabled = true;
cc.director.getCollisionManager().enabledDebugDraw = true;
this.title.string = 'normal';
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
onTouchBegan: (touch, event) => {
var touchLoc = touch.getLocation();
/**
* cc.Intersection.pointInPolygon
* 클릭한 지점과 polygon이 서로 간섭하는지 판단하는 함수
* @param point 클릭한 지점의 point
* @param polygon point의 세트 여기서는 poligonCollider의 point들을 넣음
*/
if (cc.Intersection.pointInPolygon(touchLoc, this.collider.world.points)) {
this.title.string = 'Hit';
}
else {
this.title.string = 'Not hit';
}
return true;
},
}, this.node);
}
});
'Frontend > Cocos Creator' 카테고리의 다른 글
[Cocos Creator Particle System] 1. Particle Editor 사용하기 (0) | 2018.02.12 |
---|---|
[Cocos Creator 물리] 3-2. Physics Collider Component (2) | 2018.02.05 |
[Cocos Creator 물리] 3. Physics Manager (0) | 2018.02.01 |
[Cocos Creator] ListView 개념 및 사용 (0) | 2018.01.29 |
[Cocos Creator] Layout 개념 및 사용 예시 (0) | 2018.01.29 |
[Cocos Creator] ScrollView 개념 및 사용 예시 (2) | 2018.01.29 |