Godot: yield()์—์„œ ๋ฐ˜ํ™˜ ๊ฐ’ ๊ตฌํ˜„

์— ๋งŒ๋“  2015๋…„ 02์›” 19์ผ  ยท  3์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: godotengine/godot

์ƒ์„ฑ๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด yield(value)๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ yield()์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜์ง€๋งŒ 'value'๋Š” ๋‹ค์‹œ ์ „๋‹ฌ๋˜์–ด resume() ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ž ์žฌ์ ์œผ๋กœ ๊ฑฐ๋Œ€ํ•œ ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ๋Œ€์‹  range()๋ฅผ ๋ฐ˜๋ณต์ž๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋˜ํ•œ ๋ชฉ๋ก/๋”•์…”๋„ˆ๋ฆฌ ์ดํ•ด์™€ ๊ฐ™์€ ๋ฉ‹์ง„ ๊ธฐ๋Šฅ์„ ํ–ฅํ•œ ํ•œ ๊ฑธ์Œ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

archived feature proposal gdscript

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ €๋Š” Godot์™€ ํ•จ๊ป˜ ์ผํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ(์ง€๊ธˆ๊นŒ์ง€๋Š” ๋งˆ์Œ์— ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค) yield()๊ฐ€ ํ•จ์ˆ˜ ์ƒํƒœ๋ณด๋‹ค ๋” ๋งŽ์€ ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๊ณ  ๋Š๋‚€๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. yield๋Š” resume() ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์œผ๋ฏ€๋กœ ํ•จ์ˆ˜๋Š” ํ•ญ๋ณตํ•˜์—ฌ ๊ฐ’์„ "๋ฐ˜ํ™˜"ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ ํ•œ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ [GDScript]FunctionState๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
( https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html )
yield()์— ๋Œ€ํ•œ ์ธ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ value()๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

func co1():
     yield(5)

s = co1()
print(s.value())   # prints 5

GDscript์—๋Š” ์ด๋ฏธ ๋‘ ๊ฐœ์˜ ๊ฐ’์„ ์ทจํ•˜๊ณ  ์‹ ํ˜ธ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” yield๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ํ•˜๋‚˜์˜ ์ธ์ˆ˜ ๋ฒ„์ „์€ FunctionState์—์„œ ํ•ด๋‹น ์ธ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋ณ€๊ฒฝ๋งŒ์œผ๋กœ ์ƒ์„ฑ๊ธฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func xrange(count):
    var i = 0
    while i < count:
        yield(i)

func do_stuff():
    var it = xrange(5)
    while it:
        print(it.result())
        it = it.resume()

์ด๊ฒƒ์€ ๊ฝค ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ๊ณ ๋ คํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ๋ฏธ๋ฌ˜ํ•จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด ํ•จ์ˆ˜๊ฐ€ (์–‘๋ณดํ•˜๋Š” ๋Œ€์‹ ) ๋ฐ˜ํ™˜๋˜๋ฉด FunctionState๊ฐ€ ์•„๋‹Œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ null์ด ๋ฐ˜ํ™˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค(ํ•จ์ˆ˜๊ฐ€ void์ด๊ธฐ ๋•Œ๋ฌธ์—). do_stuff()์—์„œ ๋ฃจํ”„๋ฅผ ์ค‘์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด ํ•จ์ˆ˜๊ฐ€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ [์˜ˆ. xrange()] ๋์— return false ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•˜๋ฉด ํ•ด๋‹น ํ…Œ์ŠคํŠธ๊ฐ€ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„์š”.
IMO, yield(value)๋Š” ์Œ, ๊ฐ€์น˜๊ฐ€ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŽธ์ง‘: ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด yield์˜ ์‹ ํ˜ธ ๋ฒ„์ „์— ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์ด์— ๋Œ€ํ•ด ์•„๋ž˜์— ์ž‘์„ฑํ•œ ์„น์…˜์€ ์ง€๊ธˆ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์ž์„ธํžˆ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  3 ๋Œ“๊ธ€

๋ถˆ์พŒํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:

func xrange(count, dict):
    var i = 0
    while i < count:
        dict.next = i
        yield()
        i += 1

func do_stuff():
    var curr = {}
    var it = xrange(5, curr)
    while curr.value != null:
        print(curr.value)
        it.resume()

์ €๋Š” Godot์™€ ํ•จ๊ป˜ ์ผํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ(์ง€๊ธˆ๊นŒ์ง€๋Š” ๋งˆ์Œ์— ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค) yield()๊ฐ€ ํ•จ์ˆ˜ ์ƒํƒœ๋ณด๋‹ค ๋” ๋งŽ์€ ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๊ณ  ๋Š๋‚€๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. yield๋Š” resume() ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์œผ๋ฏ€๋กœ ํ•จ์ˆ˜๋Š” ํ•ญ๋ณตํ•˜์—ฌ ๊ฐ’์„ "๋ฐ˜ํ™˜"ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ ํ•œ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ [GDScript]FunctionState๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
( https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html )
yield()์— ๋Œ€ํ•œ ์ธ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ value()๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

func co1():
     yield(5)

s = co1()
print(s.value())   # prints 5

GDscript์—๋Š” ์ด๋ฏธ ๋‘ ๊ฐœ์˜ ๊ฐ’์„ ์ทจํ•˜๊ณ  ์‹ ํ˜ธ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” yield๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ํ•˜๋‚˜์˜ ์ธ์ˆ˜ ๋ฒ„์ „์€ FunctionState์—์„œ ํ•ด๋‹น ์ธ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋ณ€๊ฒฝ๋งŒ์œผ๋กœ ์ƒ์„ฑ๊ธฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func xrange(count):
    var i = 0
    while i < count:
        yield(i)

func do_stuff():
    var it = xrange(5)
    while it:
        print(it.result())
        it = it.resume()

์ด๊ฒƒ์€ ๊ฝค ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ๊ณ ๋ คํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ๋ฏธ๋ฌ˜ํ•จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด ํ•จ์ˆ˜๊ฐ€ (์–‘๋ณดํ•˜๋Š” ๋Œ€์‹ ) ๋ฐ˜ํ™˜๋˜๋ฉด FunctionState๊ฐ€ ์•„๋‹Œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ null์ด ๋ฐ˜ํ™˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค(ํ•จ์ˆ˜๊ฐ€ void์ด๊ธฐ ๋•Œ๋ฌธ์—). do_stuff()์—์„œ ๋ฃจํ”„๋ฅผ ์ค‘์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด ํ•จ์ˆ˜๊ฐ€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ [์˜ˆ. xrange()] ๋์— return false ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•˜๋ฉด ํ•ด๋‹น ํ…Œ์ŠคํŠธ๊ฐ€ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„์š”.
IMO, yield(value)๋Š” ์Œ, ๊ฐ€์น˜๊ฐ€ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŽธ์ง‘: ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด yield์˜ ์‹ ํ˜ธ ๋ฒ„์ „์— ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์ด์— ๋Œ€ํ•ด ์•„๋ž˜์— ์ž‘์„ฑํ•œ ์„น์…˜์€ ์ง€๊ธˆ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์ž์„ธํžˆ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

yield ์ž‘๋™ ๋ฐฉ์‹์— ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋ณด๋‹ค ์ง๊ด€์ ์ธ await ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์‹ค์ œ ๋ฐœ์ „๊ธฐ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ธ์ง€ ์—ฌ๋ถ€๋Š” ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ƒ์„ฑ๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์•„์ด๋””์–ด์— ์—ฌ์ „ํžˆ ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ์ฃผ์–ด์ง„ ๋ฌธ์ œ ํ…œํ”Œ๋ฆฟ ์— ๋”ฐ๋ผ GIP ์ถ”์ ๊ธฐ์—์„œ ์ƒˆ ์ œ์•ˆ์„ ์—ฌ์‹ญ์‹œ์˜ค (์ด๋ฏธ ์กด์žฌํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ ํ›„). ์ด ๋ฌธ์ œ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์ œ์•ˆ์„œ์˜ ์•„์ด๋””์–ด๋ฅผ ์š”์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰