Physics - kuimoani/defold GitHub Wiki

Physics

Defold๋Š” 2D ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์œ„ํ•ด Box2D ๋ฌผ๋ฆฌ ์—”์ง„์„ ๊ฐœ๋Ÿ‰ํ•œ ๋ฒ„์ „์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋‰ดํ„ด์˜ ๋ฌผ๋ฆฌ ๋ฒ•์น™์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ข…๋ฅ˜์˜ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๊ฐ„์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”๋‰ด์–ผ์€ ๋ฌผ๋ฆฌ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๊ด€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

Collision objects

์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ๋ฌผ๋ฆฌ ๋™์ž‘์œผ๋กœ ๊ฒŒ์ž„ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ™•์žฅํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋ฌผ๋ฆฌ ์†์„ฑ(๋ฌด๊ฒŒ, ๋ฐ˜๋ฐœ๋ ฅ, ๋งˆ์ฐฐ๋ ฅ ๊ฐ™์€)์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ํ•œ ๊ฐœ ํ˜น์€ ๊ทธ ์ด์ƒ์˜ ๋ชจํ˜•(shape) ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฒจ๋ถ€ํ•ด์„œ ๊ณต๊ฐ„ ํ™•์žฅ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Defold๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ง€์›ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค:

Static objects

์ •์  ๊ฐ์ฒด๋Š” ์Šค์Šค๋กœ ๋ฐ˜์‘ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ๋‹ค๋ฅธ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ถฉ๋Œํ•˜๊ฒŒ ๋˜๋ฉด ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›€์ง์ด์ง€ ์•Š๋Š” ๊ฑด์ถ•๋ฌผ ๊ฐ™์€ ์ง€ํ˜•(๋ฐ”๋‹ฅ, ๋ฒฝ ๋“ฑ๋“ฑ)์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค(์„ฑ๋Šฅ์ƒ ์ด๋“์ž„). ์ •์  ์˜ค๋ธŒ์ ํŠธ๋Š” ์›€์ง์ด๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Dynamic objects

๋ฌผ๋ฆฌ ์—”์ง„์€ ๋ชจ๋“  ์ถฉ๋Œ(collision)์„ ํ•ด๊ฒฐํ•˜๊ณ  ํž˜(forces)์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ˜„์‹ค์ ์œผ๋กœ ์›€์ง์—ฌ์•ผ ํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ์ด ๋™์  ์˜ค๋ธŒ์ ํŠธ์— ํž˜์„ ๊ฐ€ํ•˜๋Š” ๊ฒƒ ๋ฟ์ž…๋‹ˆ๋‹ค.

Kinematic objects

์ด ํƒ€์ž…์€ ๋‹ค๋ฅธ ๋ฌผ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ์™€ ์ถฉ๋Œํ•˜์ง€๋งŒ ์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•˜๋Š” ์ž‘์—…์„ ์ง์ ‘ ์ฒ˜๋ฆฌ(์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜)ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ‚ค๋„ค๋งˆํ‹ฑ ์˜ค๋ธŒ์ ํŠธ๋Š” ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜๋ฉด์„œ ๋ชจ๋“  ๋ฆฌ์•ก์…˜์„ ์ง์ ‘ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

Triggers

ํŠธ๋ฆฌ๊ฑฐ๋Š” ๊ฐ„๋‹จํ•œ ์ถฉ๋Œ์„ ๋“ฑ๋กํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์–ด๋–ค ์˜ค๋ธŒ์ ํŠธ(ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ ๊ฐ™์€)๊ฐ€ ํŠน์ •ํ•œ ์ง€์ ์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ๊ฐ€ ํ•„์š”ํ•œ ๊ฒŒ์ž„๋กœ์ง์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

Editing collision objects

์—๋””ํ„ฐ๋Š” ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๊ฒŒ์ž„ ์˜ค๋ธŒ์ ํŠธ์— ์‰ฝ๊ฒŒ ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.

Physics collision object

์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ํ•˜๋‚˜ ํ˜น์€ ๊ทธ ์ด์ƒ์˜ ๋ฌผ๋ฆฌ ๋ชจํ˜•(physics shapes)์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • Box shapes
  • Sphere shapes
  • Capsule shapes (3D ๋ฌผ๋ฆฌ์—์„œ๋งŒ ๋™์ž‘ํ•จ!)

๋‹น์‹ ์€ ์œ„์˜ ๋ชจํ˜•(shape)์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ณ€ํ˜• ๋„๊ตฌ(transform tool)์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šค์ผ€์ผ, ํšŒ์ „, ํฌ์ง€์…˜์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์†์„ฑ๋“ค์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

Physics properties

"Collision Shape" ์†์„ฑ์€ ์ผ๋ฐ˜ ์›์‹œ ๋ชจํ˜•(primitive shape)์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํƒ€์ผ๋งต์˜ ์ง€ํ˜•(geometry)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๊ฒƒ์€ Tilesource collision shapes ์—์„œ ์‚ดํŽด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Type ์†์„ฑ์€ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ์ข…๋ฅ˜("Dynamic", "Kinematic", "Static", "Trigger")๋ฅผ ์„ค์ •ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. "Dynamic"์œผ๋กœ ์„ค์ •ํ•˜๋ฉด Mass(์งˆ๋Ÿ‰) ์†์„ฑ์„ 0์ด ์•„๋‹Œ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋™์ (Dynamic) ํ˜น์€ ์ •์ (Static) ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์œ„ํ•ด์„œ๋Š” Friction(๋งˆ์ฐฐ๋ ฅ) ๊ณผ Restitution(๋ฐ˜๋ฐœ๋ ฅ) ๊ฐ’์„ ์„ค์ • ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ "Dynamic" ํƒ€์ž…์œผ๋กœ ์„ค์ •ํ•˜๊ณ  mass๋ฅผ 0์ด ์•„๋‹Œ ๊ฐ’์œผ๋กœ ์…‹ํŒ…ํ•˜๋Š” ๊ฒƒ์„ ๊นœ๋นก ํ•œ๋‹ค๋ฉด ์ปดํŒŒ์ผ์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค: "ERROR: GAMESYS: Invalid mass 0.000000 for shape type 0"

Friction

๋งˆ์ฐฐ๋ ฅ์€ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋‹ค๋ฅธ ์˜ค๋ธŒ์ ํŠธ๊ณผ ๋ถ™์–ด์„œ ํ˜„์‹ค๊ฐ ์žˆ๊ฒŒ ๋ฏธ๋„๋Ÿฌ์ง€๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ ์ผ๋ฐ˜์ ์œผ๋กœ 0(๋งˆ์ฐฐ๋ ฅ์ด ์ „ํ˜€์—†์œผ๋ฏ€๋กœ ์—„์ฒญ ๋ฏธ๋Œ๊ฑฐ๋ฆผ)๊ณผ 1(๊ฐ•๋ ฅํ•œ ๋งˆ์ฐฐ๋ ฅ์œผ๋กœ ์—„์ฒญ ๊ฑฐ์น ์–ด์ง) ์‚ฌ์ด๋กœ ์„ค์ •๋˜๋ฉฐ ์–‘์ˆ˜ ๊ฐ’(positive value)๋งŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ฐฐ๋ ฅ์˜ ๊ฐ•๋„๋Š” ์ˆ˜์งํ•ญ๋ ฅ(normal force: ์ฟจ๋กฑ ๋งˆ์ฐฐ(Coulomb friction)์œผ๋กœ๋„ ๋ถˆ๋ฆผ)์— ๋น„๋ก€ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ฐฐ๋ ฅ์ด ๋‘ ๋ชจํ˜•(shapes) ์‚ฌ์ด์—์„œ ๊ณ„์‚ฐ๋˜๋ฉด, ๋‘ ์˜ค๋ธŒ์ ํŠธ์˜ ๋งˆ์ฐฐ๊ฐ’์ด ๊ธฐํ•˜ํ‰๊ท (geometric mean)์— ์˜ํ•ด ๊ฒฐํ•ฉ๋ฉ๋‹ˆ๋‹ค.

combined_friction = math.sqrt(shape1_friction * shape2_friction)

์ฆ‰, ๋‘ ์˜ค๋ธŒ์ ํŠธ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋งˆ์ฐฐ์ด ์—†๋Š” ๊ฒฝ์šฐ์— ์ด๋“ค ์‚ฌ์ด์˜ ์ ‘์ด‰๋ฉด์€ ๋งˆ์ฐฐ์ด ์—†๋Š” ๊ฒƒ์œผ๋กœ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

Restitution

๋ฐ˜๋ฐœ๋ ฅ ๊ฐ’์€ ์˜ค๋ธŒ์ ํŠธ์˜ ํƒ„์„ฑ(bounciness)์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ ์ผ๋ฐ˜์ ์œผ๋กœ 0(๋น„ํƒ„์„ฑ ์ถฉ๋Œ๋กœ์„œ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ „ํ˜€ ํŠ•๊ธฐ์ง€ ์•Š์Œ)์—์„œ 1(์™„์ „ํ•œ ํƒ„์„ฑ ์ถฉ๋Œ๋กœ์„œ ์˜ค๋ธŒ์ ํŠธ์˜ ์†๋„์™€ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ํŠ•๊ฒจ๋‚˜๊ฐ) ์‚ฌ์ด๋กœ ์„ค์ • ๋ฉ๋‹ˆ๋‹ค.

๋‘ ์˜ค๋ธŒ์ ํŠธ ์‚ฌ์ด์˜ ๋ฐ˜๋ฐœ๋ ฅ์€ ์•„๋ž˜ ๊ณต์‹์œผ๋กœ ๊ฒฐํ•ฉ๋ฉ๋‹ˆ๋‹ค.

combined_restitution = math.max(shape1_restitution, shape2_restitution)

๋ชจํ˜•(shape)์ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ ‘์ด‰๋ฉด(multiple contacts)์œผ๋กœ ๊ฐœ๋ฐœ ๋˜์—ˆ๋‹ค๋ฉด, Box2D๊ฐ€ iterative solver(๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฌผ๋ฆฌ ์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•˜๋Š” ํ•ด๊ฒฐ์‚ฌ)๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋ฐœ๋ ฅ์€ ๋Œ€๋žต์ ์œผ๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Box2D๋Š” ์ถฉ๋Œ ์†๋„๊ฐ€ ๋„ˆ๋ฌด ์ž‘์„ ๋•Œ์—๋Š” ๋น„ํƒ„์„ฑ ์ถฉ๋Œ(inelastic collisions)์„ ์‚ฌ์šฉํ•˜์—ฌ bounce-jitter(๋ฐ”์šด์Šค์‹œ์— ๋œ๋œ ๋–จ๋ฆฌ๋Š” ํ˜„์ƒ)๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

Linear and angular damping

๊ฐ์‡ (damping)๋Š” ๋ชธ์ฒด์˜ ์„ ํ˜•(linear) ์†๋„์™€ ๊ฐํ˜•(angular) ์†๋„๋ฅผ ๊ฐ์†Œ ์‹œํ‚ต๋‹ˆ๋‹ค. ์ด๋Š” ์ ‘์ด‰๋ฉด์—์„œ๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๋งˆ์ฐฐ๋ ฅ๊ณผ๋Š” ๋‹ค๋ฅด๋ฉฐ, ๊ณต๊ธฐ๋ณด๋‹ค ๋ฌด๊ฑฐ์šด ๊ณต๊ฐ„์„ ์ง€๋‚˜๊ฐ€๋“ฏ์ด ๋– ๋‹ค๋‹ˆ๋Š” ๊ฒƒ์„ ํ‘œํ˜„ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์œ ํšจํ•œ ๊ฐ’์€ 0๋ถ€ํ„ฐ 1๊นŒ์ง€์˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.

Box2D๋Š” ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ๋•Œ๋ฌธ์— ๊ฐ์‡ ๊ฐ’์„ ๋Œ€๋žต์ ์œผ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ž‘์€ ๊ฐ’์˜ ๊ฐ์‡  ํšจ๊ณผ๋Š” ์‹œ๊ฐ„ ํ๋ฆ„์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ๋ฐ˜๋ฉด, ํฐ ๊ฐ์‡  ๊ฐ’์€ ์‹œ๊ฐ„ ํ๋ฆ„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๊ณ ์ •๋œ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ(fixed time step)์œผ๋กœ ๊ฒŒ์ž„์„ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, ์ด๊ฒƒ์€ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Locked rotation

์ด ์†์„ฑ์„ ์„ค๋ช…ํ•˜๋ฉด ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š”์ง€์™€ ๊ด€๊ณ„ ์—†์ด ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ํšŒ์ „์„ ์™„์ „ํžˆ ๋น„ํ™œ์„ฑํ™” ํ•ฉ๋‹ˆ๋‹ค.

Group and Mask

์ด ๊ธฐ๋Šฅ์€ ํŠน์ • ์œ ํ˜•์˜ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋‹ค๋ฅธ ํŠน์ • ์œ ํ˜•์˜ ์˜ค๋ธŒ์ ํŠธ์™€ ์ถฉ๋Œํ•˜๋ฉด์„œ ๋˜ ๋‹ค๋ฅธ ์ œ3์˜ ์˜ค๋ธŒ์ ํŠธ์™€๋Š” ์ถฉ๋Œํ•˜์ง€ ์•Š๊ฒŒ ํ•„ํ„ฐ๋งํ•˜๋Š”๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด์–ด ์ŠˆํŒ… ๊ฒŒ์ž„์—์„œ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ๊ฐ€ ์ด์•Œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฐœ์‚ฌํ•จ
  2. ์ด์•Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ์  ์˜ค๋ธŒ์ ํŠธ์™€ ์ถฉ๋Œ ํ•ด์•ผํ•จ
  3. ์ด์•Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ์™€๋Š” ์ถฉ๋Œํ•˜์ง€ ๋ง์•„์•ผ ํ•จ
  4. ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ๋Š” ์  ์˜ค๋ธŒ์ ํŠธ์™€ ์ถฉ๋Œ ํ•ด์•ผํ•จ
  5. ํ”Œ๋ ˆ์ด์–ด์™€ ์  ์˜ค๋ธŒ์ ํŠธ๋“ค์€ ๊ฒŒ์ž„์„ธ์ƒ์˜ ํƒ€์ผ(tile)์—๋Š” ์ถฉ๋Œํ•จ

๋ฌผ๋ฆฌ ์—”์ง„์€ ๋ฌผ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๊ทธ๋ฃนํ™” ํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ์ถฉ๋Œํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ํ•„ํ„ฐ๋ง ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค. ์ด๋Š” ์ถฉ๋Œ ๊ทธ๋ฃน(collision group)์˜ ์ด๋ฆ„์œผ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๋‘ ๊ฐ€์ง€ ์†์„ฑ์€ ์–ด๋–ป๊ฒŒ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋‹ค๋ฅธ ์˜ค๋ธŒ์ ํŠธ์™€ ์ถฉ๋Œํ•˜๋Š”์ง€๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

Group

์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์†ํ•ด์•ผ ํ•˜๋Š” ์ถฉ๋Œ ๊ทธ๋ฃน์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. 16๊ฐœ์˜ ๋‹ค๋ฅธ ๊ทธ๋ฃน์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹น์‹ ์˜ ๊ฒŒ์ž„์— ์–ด์šธ๋ฆฌ๋Š” ์ด๋ฆ„(์˜ˆ๋ฅผ ๋“ค์–ด "players", "bullets", "enemies", "world" ๋“ฑ๋“ฑ)์œผ๋กœ ์ง€์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Mask

์ด ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ถฉ๋Œํ•ด์•ผ ํ•˜๋Š” ๋‹ค๋ฅธ ๊ทธ๋ฃน์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฃน ํ•˜๋‚˜์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ์‰ผํ‘œ(,)๋กœ ์—ฌ๋Ÿฌ ๊ทธ๋ฃน์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด Mask ํ•„๋“œ๊ฐ€ ๋นˆ๊ฐ’์œผ๋กœ ๋˜์–ด ์žˆ๋‹ค๋ฉด, ์˜ค๋ธŒ์ ํŠธ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์ถฉ๋Œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ ์ถฉ๋Œ์€ ๋‘ ๊ฐœ์˜ ์˜ค๋ธŒ์ ํŠธ์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ๋‘ ์˜ค๋ธŒ์ ํŠธ ์ƒํ˜ธ๊ฐ„์— Group์˜ ์ด๋ฆ„์„ Mask ํ•„๋“œ์— ์„œ๋กœ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Collision groups and masks

์œ„์˜ ์ƒ˜ํ”Œ ์ŠˆํŒ…๊ฒŒ์ž„์˜ ์ถฉ๋Œ ๊ณ„ํš์„ ๋‹ฌ์„ฑํ•˜๋ ค๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Players

Group: "players", Mask: "world, enemies"

Bullet

Group: "bullets", Mask: "enemies"

Enemies

Group: "enemies", Mask: "players, bullets"

World

Group: "world", Mask: "players, enemies"

Tilesource collision shapes

Defold ์—๋””ํ„ฐ์—๋Š” ํƒ€์ผ ์†Œ์Šค๋ฅผ ์œ„ํ•œ ๋ฌผ๋ฆฌ ๋ชจ์–‘(shape)์„ ๋น ๋ฅด๊ฒŒ ์ƒ์„ฑํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํƒ€์ผ์†Œ์Šค ์—๋””ํ„ฐ์—์„œ, ์ถฉ๋Œ์„ ์œ„ํ•ด ๊ธฐ์ดˆ๋กœ ์‚ฌ์šฉํ•  ์ด๋ฏธ์ง€๋ฅผ ์„ ํƒํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด ์—๋””ํ„ฐ๋Š” 100%๋กœ ํˆฌ๋ช…ํ•˜์ง€ ์•Š์€ ํ”ฝ์…€์„ ๊ณ ๋ คํ•˜์—ฌ, ๊ฐ ํƒ€์ผ ์ฃผ๋ณ€์œผ๋กœ ๋ณผ๋กํ•œ ๋ชจํ˜•(convex shape)์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

Physics tilesource

์ด ์—๋””ํ„ฐ๋Š” ํƒ€์ผ์— ํ• ๋‹น๋œ ์ถฉ๋Œ ๊ทธ๋ฃน์˜ ์ƒ‰์ƒ์œผ๋กœ ์ด ๋ชจํ˜•(shape)๋“ค์„ ๊ทธ๋ ค์ค๋‹ˆ๋‹ค. ํƒ€์ผ ์†Œ์Šค๋‹น ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ถฉ๋Œ ๊ทธ๋ฃน์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—๋””ํ„ฐ์— ์˜ํ•ด ๊ทธ๋ฃน ์ƒ‰์ƒ์ด ์ž๋™์œผ๋กœ ์„ ํƒ๋ฉ๋‹ˆ๋‹ค.

Add collision group

ํƒ€์ผ ๋ฌผ๋ฆฌ ๋ชจ์–‘(tile physics shape)์„ ํŠน์ •ํ•œ ์ถฉ๋Œ ๊ทธ๋ฃน์œผ๋กœ ์„ค์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, group์„ ์„ ํƒํ•˜๊ณ  shape์„ ํด๋ฆญํ•˜์„ธ์š”. ์ด๋“ค ์ถฉ๋Œ ๊ทธ๋ฃน์œผ๋กœ๋ถ€ํ„ฐ ํƒ€์ผ ๋ชจํ˜•(tile shape)์„ ์‚ญ์ œํ•˜๋ ค๋ฉด, "Tile source"์˜ ์ตœ์ƒ์œ„(root)๋ฅผ ์„ ํƒํ•˜๊ณ  ํƒ€์ผ์„ ํด๋ฆญํ•˜์„ธ์š”.

ํƒ€์ผ ์†Œ์Šค๋กœ๋ถ€ํ„ฐ ์ถฉ๋Œ ๋ชจํ˜•(collision shape)์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, ์›ํ•˜๋Š” ๊ฒŒ์ž„ ์˜ค๋ธŒ์ ํŠธ์— ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ(Collision Object)๋ฅผ ๋งŒ๋“ค๊ณ  Collision Shape ์†์„ฑ์— ํƒ€์ผ ์†Œ์Šค๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Physics level example

  1. ํƒ€์ผ ๋งต์— ์—ฐ๊ฒฐ๋œ ํƒ€์ผ์†Œ์Šค๊ฐ€ ์ถฉ๋Œ์„ ์œ„ํ•ด ์„ค์ •๋œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ์ด๋Š” ์—๋””ํ„ฐ ์ฐฝ์—์„œ ํ…์Šค์ณ์˜ ์ƒ๋‹จ์— ์„ ์œผ๋กœ ๋ Œ๋”๋ง ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ์ถฉ๋Œ์„ ์ง€์›ํ•˜๋Š” ํƒ€์ผ๋“ค์— ๋Œ€ํ•˜์—ฌ ํƒ€์ผ ์†Œ์Šค์˜ ์ถฉ๋Œ ๊ทธ๋ฃน์ด ์ƒ‰์น  ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.
  3. ์ถ”๊ฐ€ํ•œ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ํƒ€์ž…์„ Static์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”.
  4. Group๊ณผ Mask ์†์„ฑ์„ ์„ค์ •ํ•˜์„ธ์š”.
  5. ํƒ€์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถฉ๋Œ์‹œํ‚ค๋ ค๋Š” ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ Group๊ณผ Mask ์†์„ฑ๊ฐ’์„ ํ™•์ธํ•˜์„ธ์š”.

Collision messages

๋‘ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ถฉ๋Œํ•˜๋ฉด, ์—”์ง„์€ ๋‘ ์˜ค๋ธŒ์ ํŠธ์˜ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘์—๊ฒŒ ๋ฉ”์„ธ์ง€๋ฅผ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ ํ•ฉ๋‹ˆ๋‹ค.

collision_response

์ด ๋ฉ”์„ธ์ง€๋Š” ๋ชจ๋“  ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์— ๋Œ€ํ•ด ์ „์†ก๋˜๋ฉฐ ์•„๋ž˜์˜ ํ•„๋“œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

other_id

์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ถฉ๋Œํ•œ ์ƒ๋Œ€ ์ธ์Šคํ„ด์Šค์˜ ์•„์ด๋”” (hash)

other_position

์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ถฉ๋Œํ•œ ์ƒ๋Œ€ ์ธ์Šคํ„ด์Šค์˜ ์›”๋“œ ์ขŒํ‘œ (vector3)

group

์ƒ๋Œ€ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ์ถฉ๋Œ ๊ทธ๋ฃน (hash)

collision_response ๋ฉ”์„ธ์ง€๋Š” ์˜ค๋ธŒ์ ํŠธ์˜ ์‹ค์ œ ๊ต์ฐจ๊ตฌ๊ฐ„(intersection)์— ๋Œ€ํ•ด ์ž์„ธํ•œ ์ •๋ณด๊ฐ€ ํ•„์š” ์—†๋Š” ์ถฉ๋Œ์„ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด์•Œ์ด ์ ์„ ๋งž์ท„์Œ์„ ๊ฐ์ง€ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์ถฉ๋Œํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ ์Œ(pair)์„ ์œ„ํ•ด ๋ฉ”์„ธ์ง€ ์ค‘ ํ•˜๋‚˜๋งŒ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.

contact_point_response

์ด ๋ฉ”์„ธ์ง€๋Š” ์ถฉ๋Œํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ ์ค‘ ํ•˜๋‚˜๊ฐ€ Dynamic ์ด๊ฑฐ๋‚˜ Kinematic์ผ ๊ฒฝ์šฐ ์ „์†ก๋˜๋ฉฐ ์•„๋ž˜์˜ ํ•„๋“œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

position

์ถฉ๋Œ ์ง€์ (contact point)์˜ ์›”๋“œ ํฌ์ง€์…˜ (vector3)

normal

์ƒ๋Œ€ ์˜ค๋ธŒ์ ํŠธ์—์„œ ํ˜„์žฌ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ–ฅํ•œ ์ถฉ๋Œ ์ง€์ (contact point)์˜ ์›”๋“œ ๊ณต๊ฐ„(world space)์—์„œ์˜ ๋ฒ•์„  (vector3)

relative_velocity

์ƒ๋Œ€ ์˜ค๋ธŒ์ ํŠธ์—์„œ ๊ด€์ฐฐ๋œ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ์ƒ๋Œ€์†๋„ (vector3)

distance

์˜ค๋ธŒ์ ํŠธ๊ฐ„์˜ ๊ฑฐ๋ฆฌ(์–‘์ˆ˜(+)๋กœ ๋œ number)

applied_impulse

์ ‘์ด‰์ด ์ผ์œผํ‚จ ์ถฉ๊ฒฉ๋Ÿ‰ (number)

life_time

์ ‘์ด‰์˜ ์ˆ˜๋ช… (ํ˜„์žฌ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Œ!) (number)

mass

ํ˜„์žฌ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ kg ์งˆ๋Ÿ‰ (number)

other_mass

์ƒ๋Œ€ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ kg ์งˆ๋Ÿ‰ (number)

other_id

์ƒ๋Œ€ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ์ธ์Šคํ„ด์Šค ์•„์ด๋”” (hash)

other_position

์ƒ๋Œ€ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ์›”๋“œ์ขŒํ‘œ (vector3)

group

์ƒ๋Œ€ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ ์ถฉ๋Œ ๊ทธ๋ฃน (hash)

์˜ค๋ธŒ์ ํŠธ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•ด์•ผํ•˜๋Š” ๊ฒŒ์ž„์˜ ๊ฒฝ์šฐ, contact_point_response ๋ฉ”์„ธ์ง€๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ถฉ๋Œ ์Œ(collision pair)์ด ์ฃผ์–ด์ง€๋ฏ€๋กœ, ํ”„๋ ˆ์ž„ ๋งˆ๋‹ค ๋‹ค์ˆ˜์˜ contact_point_response ๋ฉ”์„ธ์ง€๊ฐ€ ์ˆ˜์‹ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Triggers

ํŠธ๋ฆฌ๊ฑฐ๋Š” ๊ฐ€๋ฒผ์šด ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์ž…๋‹ˆ๋‹ค. ํŠธ๋ฆฌ๊ฑฐ์™€ ์ถฉ๋Œํ•˜๋ฉด collision_response ๋ฉ”์„ธ์ง€๊ฐ€ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋Š” ์ถฉ๋Œ์ด ์‹œ์ž‘(begin)๋˜์—ˆ๊ฑฐ๋‚˜ ๋(end)๋‚ฌ์„ ๊ฒฝ์šฐ ํŠน๋ณ„ํ•œ trigger_response ๋˜ํ•œ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„ธ์ง€์—๋Š” ์•„๋ž˜ ํ•„๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

other_id

์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ถฉ๋Œํ•œ ์ธ์Šคํ„ด์Šค์˜ ์•„์ด๋”” (hash)

enter

์ƒํ˜ธ์ž‘์šฉ์„ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด true, ์ƒํ˜ธ์ž‘์šฉ์„ ๋๋ƒˆ๋‹ค๋ฉด false.

Resolving Kinematic collisions

ํ‚ค๋„ค๋งˆํ‹ฑ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ถฉ๋Œ์„ ์Šค์Šค๋กœ ํ•ด๊ฒฐํ•˜๊ณ  ์นจํˆฌ๋œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์›€์ง์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ธŒ์ ํŠธ์˜ ๋ถ„๋ฆฌ๋ฅผ ๋Œ€์ถฉ ๊ตฌํ˜„ํ•˜์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

function on_message(self, message_id, message, sender)
  -- ์ถฉ๋Œ ๋‹ค๋ฃจ๊ธฐ
  if message_id == hash("contact_point_response") then
    local newpos = go.get_position() + message.normal * message.distance
    go.set_position(newpos)
  end
end

์ด ์ฝ”๋“œ๋Š” ์ƒ๋Œ€ ๋ฌผ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ํ‚ค๋„ค๋งˆํ‹ฑ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋šซ๊ณ  ๋“ค์–ด์™”์„ ๊ฒฝ์šฐ ์„œ๋กœ ๋–ผ์–ด๋†“๋Š” ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€๋งŒ, ์ด๋Š” ๋งŽ์€ ๊ฒฝ์šฐ์— ๋„ˆ๋ฌด ๋‚˜๊ฐ€๊ฑฐ๋‚˜(overshoots) ํ”๋“ค๋ ค(jitter) ๋ณด์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ‚ค๋„ค๋งˆํ‹ฑ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ถฉ๋Œ๋กœ๋ถ€ํ„ฐ ์ ์ ˆํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์ƒํ™ฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Physics collision

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” Object A์™€ Object B, ๋‘ ๊ฐœ์˜ contact point ๋ฉ”์„ธ์ง€๋ฅผ ์–ป์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์œ„์˜ ๋‹จ์ˆœํ•œ ๋ถ„๋ฆฌ ๊ณผ์ •์„ ์‹คํ–‰ํ•˜๋ฉด, ์นจํˆฌ ๋ฒกํ„ฐ(penetration vectors)๊ฐ€ ๊ฐ๊ฐ ์ถ”๊ฐ€๋˜์–ด, ์•„๋ž˜ ์ฒ˜๋Ÿผ ๋ถ„๋ฆฌ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Physics separation naive

๋Œ€์‹ , ์šฐ๋ฆฌ๋Š” ์ ‘์ด‰ ์ง€์ (contact point)์„ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ์ด๋ฏธ ์ด์ „ ๋ถ„๋ฆฌ(previous separation)๊ฐ€ ์™„์ „ํžˆ ํ˜น์€ ๋ถ€๋ถ„์ ์œผ๋กœ ํ•ด๊ฒฐ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์ถฉ๋Œ ์˜ˆ์ œ์—์„œ๋Š” Object A ์—์„œ๋ถ€ํ„ฐ Character Collision Shape์˜ ๋ถ„๋ฆฌ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Physics separation, step 1

์šฐ๋ฆฌ๋Š” Object A์˜ ๋ฒ•์„ ์„ ๋”ฐ๋ผ์„œ ์บ๋ฆญํ„ฐ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์นจํˆฌ๊ฑฐ๋ฆฌ(์œ„์—์„œ ๋ถ‰์€์ƒ‰ ์ ์„  ํ™”์‚ดํ‘œ)๋งŒํผ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค. Object B์˜ ๋ฒ•์„ ์„ ๋”ฐ๋ผ ์šฐ๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋งˆ์ง€๋ง‰ ์›€์ง์ž„์ด ์ด๋ฏธ ์ฒซ๋ฒˆ์งธ๋กœ ๋ถ„๋ฆฌ๋œ Object A์— ๋Œ€ํ•˜์—ฌ ๋ถ€๋ถ„์ ์œผ๋กœ ๊ฒน์ณ์ง„ ๊ฒƒ์„ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์›๋ž˜์˜ ํ™”์‚ดํ‘œ(๋…น์ƒ‰ ์ ์„ ) ๋Œ€์‹ ์— ๋…น์ƒ‰์œผ๋กœ ์ฑ„์›Œ์ง„ ํ™”์‚ดํ‘œ์˜ ๋ฒกํ„ฐ๋ฅผ ๋”ฐ๋ผ ๋ถ„๋ฆฌ์ž‘์—…์„ ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Object B์—์„œ ์ด์ „ ์›€์ง์ž„(previous movement)์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

Physics projection

์ด ๊ฑฐ๋ฆฌ๋Š” Object B์— ๋Œ€ํ•œ Object A์˜ ์นจํˆฌ๋ฒกํ„ฐ๋ฅผ ํˆฌ์˜ํ•˜์—ฌ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ์ด๋™(movement)์„ ์ฐพ์œผ๋ ค๋ฉด ๊ทธ์ € ์›๋ž˜์˜ ์นจํˆฌ ๋ฐฑํ„ฐ์—์„œ l์„ ๋นผ๋ฉด(subtract) ๋ฉ๋‹ˆ๋‹ค. ์ž„์˜์˜ ์นจํˆฌ ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด, ๋ฒกํ„ฐ๋กœ ์‹ค์ œ ์ด๋™๊ฐ’๋“ค์„ ํ•ฉ์‚ฐํ•˜๊ณ  ๊ฐ ์นจํˆฌ๋ฒกํ„ฐ์— ๋Œ€ํ•˜์—ฌ ์ฐจ๋ก€๋Œ€๋กœ ํˆฌ์˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ „์ฒด ๊ตฌํ˜„์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

function on_message(self, message_id, message, sender)
    -- ์ถฉ๋Œ ๋‹ค๋ฃจ๊ธฐ
    if message_id == hash("contact_point_response") then
        -- ์ถฉ๋Œ์—์„œ ๋ฒ—์–ด๋‚˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ •๋ณด ์–ป๊ธฐ
        -- ์—ฌ๋Ÿฌ๋ฒˆ ์ถฉ๋Œ์ง€์ ์„ ๋˜๋Œ๋ฆฌ๋ฉด์„œ, ๋ˆ„์ ํ•ด๊ฐ€๋ฉฐ ์ด๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ณ„์‚ฐ ํ•ด์•ผํ•จ
        if message.distance > 0 then
            -- ์šฐ์„  ๋ˆ„์ ๋œ ๋ณด์ •๊ฐ’์— ์นจํˆฌ ๋ฒกํ„ฐ๋ฅผ ํˆฌ์˜ํ•ฉ๋‹ˆ๋‹ค.
            local proj = vmath.project(self.correction, message.normal * message.distance)
            if proj < 1 then
                -- ๋„˜์–ด๊ฐ€๋ฒ„๋ฆฌ์ง€ ์•Š๋„๋ก ํˆฌ์‚ฌ(projections)์— ์‹ ๊ฒฝ ์“ธ๊ฒƒ
                local comp = (message.distance - message.distance * proj) * message.normal
                -- ๋ณด์ƒ(compensation) ๋ฐ˜์˜ํ•˜๊ธฐ
                go.set_position(go.get_position() + comp)
                -- ๋ณด์ •๊ฐ’์„ ๋ˆ„์ ํ•ฉ์‚ฐํ•˜๊ธฐ
                self.correction = self.correction + comp
            end
        end
    end
end

Best practices

Triggers

ํŠธ๋ฆฌ๊ฑฐ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋Š” ์ œํ•œ์ ์ธ๊ฒŒ ๋งŽ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋กœ ์ด๋™ํ–ˆ์„ ๋•Œ ์ถฉ๋Œ์˜ ๊ฐ•์•ฝ๊ณผ ๋น„๋ก€ํ•˜๋Š” ํฌ๊ธฐ ๋งŒํผ์˜ ์†Œ๋ฆฌ๊ฐ€ ๋‚˜์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ํŠธ๋ฆฌ๊ฑฐ์— ์นจํˆฌํ•œ ๊ฑฐ๋ฆฌ(penetration distance)๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ, ์ผ๋ฐ˜ ํŠธ๋ฆฌ๊ฑฐ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ๋กœ๋Š” ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ํ‚ค๋„ค๋งˆํ‹ฑ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋Œ€์‹  ์‚ฌ์šฉํ•˜์—ฌ ์ถฉ๋Œ ๋ฐ์ดํ„ฐ์˜ ์นจํˆฌ๊ฑฐ๋ฆฌ๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์ถฉ๋Œ์„ ์œ„ํ•œ ๋ถ„๋ฆฌ(separation of collisions)๋Š” ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํ‚ค๋„ค๋งˆํ‹ฑ ์˜ค๋ธŒ์ ํŠธ๋Š” ํŠธ๋ฆฌ๊ฑฐ์— ๋น„ํ•ด ์„ฑ๋Šฅ ๋น„์šฉ์ด ๋งŽ์ด ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Choosing between Dynamic or Kinematic objects

ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ๊ฐ€ ๋ ˆ๋ฒจ์„ ๋”ฐ๋ผ ์›€์ง์ด๋Š” ํ”Œ๋žซํฌ๋จธ๋ฅ˜์˜ ๊ฒŒ์ž„์„ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. ์—ฌ๊ธฐ์„œ ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ๋ฅผ Dynamic ๋ฌผ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋กœ, ์›”๋“œ๊ฐ์ฒด๋ฅผ Static ๋ฌผ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋กœ ๋งŒ๋“œ๋Š”๊ฒƒ์ด ์ผ๋‹จ ์ข‹์€ ์ƒ๊ฐ์ธ ๊ฒƒ ์ฒ˜๋Ÿผ ๋А๊ปด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ‚ค ์ž…๋ ฅ์„ ํ•˜๋ฉด ํ”Œ๋ ˆ์ด์–ด ์˜ค๋ธŒ์ ํŠธ์— ๋‹ค์–‘ํ•œ ๋ฌผ๋ฆฌ์  ํž˜์„ ๊ฐ€ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์›€์ง์ž„์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด ๊ตฌํ˜„ ์ž์ฒด๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋ฉ‹์ง„ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด ๋‚ด๊ธฐ๋Š” ๋งค์šฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๊ฒŒ์ž„์˜ ์ œ์–ด๊ฐ€ ๋™์ผํ•œ ๋ฌผ๋ฆฌ์—”์ง„์—์„œ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋ฏ€๋กœ ๋‹ค๋ฅธ ์ˆ˜์ฒœ๊ฐ€์ง€ ๊ฒŒ์ž„๋“ค๊ณผ ๋‹ค๋ฅผ ๋ฐ” ์—†๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” Box2D ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ํ˜„์‹ค๊ฐ™์€ ๋‰ดํ„ด์˜ ๋ฒ•์น™์„ ๋”ฐ๋ฅธ ๋ฐ˜๋ฉด, ํ”Œ๋žซํฌ๋จธ ๊ฒŒ์ž„์˜ ๋ฌผ๋ฆฌ ๋ฒ•์น™์€ ๊ทผ๋ณธ์ ์œผ๋กœ ์กฐ๊ธˆ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋ฒŒ์–ด์ง‘๋‹ˆ๋‹ค. ๋‰ดํ„ด ๋ฐฉ์‹์˜ ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ๋น„ ๋‰ดํ„ด ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“ค๋ ค๋ฉด ๋งŽ์€ ๋…ธ๋ ฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์˜ˆ๋ฅผ ๋“ค๋ฉด, ๊ฐ€์žฅ์ž๋ฆฌ(edges)์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”๋ฐ, ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํ”Œ๋žซํผ ๊ฐ€์žฅ์ž๋ฆฌ์— ๊ฑธ์ณ์ง€๋ฉด ํ˜„์‹ค์˜ ์ƒ์ž์ฒ˜๋Ÿผ ๋ชจ์„œ๋ฆฌ์— ๊ฑธ์ณ ๊ธฐ์šธ์–ด ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Dynamic physics

์ด ๋ฌธ์ œ๋Š” ์บ๋ฆญํ„ฐ ์ถฉ๋Œ ์˜ค๋ธŒ์ ํŠธ์˜ "Locked Rotation" ์†์„ฑ์„ ์„ค์ •ํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ๋ฌธ์ œ์˜ ํ•ต์‹ฌ์€ ์ด ์ œํ•œ์ ์ธ ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ๋„˜์–ด ์ง์ ‘ ํ†ต์ œํ•˜๋ ค๋ฉด ๋””์ž์ด๋„ˆ๋‚˜ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ํž˜์„ ๋นŒ์–ด ์บ๋ฆญํ„ฐ๋ฅผ ์›€์ง์ด๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฏ€๋กœ ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ๋ฅผ ํ‚ค๋„ค๋งˆํ‹ฑ ๋ฌผ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋กœ ๊ตฌํ˜„ํ•˜๋Š”๊ฒƒ์„ ๊ฐ•๋ ฅํžˆ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋ฌผ๋ฆฌ ์—”์ง„์€ ์ถฉ๋Œ์„ ๊ฐ์ง€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ณ  ์ถฉ๋Œํ•œ ์˜ค๋ธŒ์ ํŠธ๋“ค์„ ๋ถ„๋ฆฌํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ดˆ๋ฐ˜์—” ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•˜์ง€๋งŒ, ๋‚˜์ค‘์—๋Š” ํ”Œ๋ ˆ์ด์–ด์˜ ๊ฒฝํ—˜์„ ๋ญ”๊ฐ€ ๋” ๋ฉ‹์ง€๊ณ  ๊ฐœ์„ฑ์žˆ๊ฒŒ ํŠœ๋‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(๊ทธ๋ž˜ํ”ฝ ์—์…‹ ์ผ๋ถ€๋Š” Kenney: http://kenney.nl/assets ๊ฐ€ ์ œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.)