Unity/RTS

Behavior tree

sehunbang 2025. 10. 22. 18:12

๐Ÿง  ๊ธฐ๋ณธ ๊ฐœ๋…

Behavior Tree๋Š” ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ “ํŠธ๋ฆฌ(Tree)” ๊ตฌ์กฐ์˜ˆ์š”.
๋ฃจํŠธ ๋…ธ๋“œ → ํ•˜์œ„ ๋…ธ๋“œ(Sequence, Selector ๋“ฑ) → ๋ฆฌํ”„ ๋…ธ๋“œ(์‹ค์ œ ํ–‰๋™) ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

โš™๏ธ ์ฃผ์š” ๋…ธ๋“œ ํƒ€์ž…

๋…ธ๋“œ ํƒ€์ž…์„ค๋ช…
Root ํŠธ๋ฆฌ์˜ ์‹œ์ž‘์ 
Selector ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ๊ฒ€์‚ฌ → ํ•˜๋‚˜๋ผ๋„ ์„ฑ๊ณตํ•˜๋ฉด ๋ฉˆ์ถค (“A ๋˜๋Š” B”)
Sequence ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰ → ํ•˜๋‚˜๋ผ๋„ ์‹คํŒจํ•˜๋ฉด ๋ฉˆ์ถค (“A ๊ทธ๋ฆฌ๊ณ  B”)
Decorator ํŠน์ • ์กฐ๊ฑด์„ ๊ฐ์‹ธ๊ฑฐ๋‚˜, ๋ฐ˜๋ณต ์ˆ˜ํ–‰์„ ์ œ์–ด (“์กฐ๊ฑด์ด ์ฐธ์ผ ๋•Œ๋งŒ ์‹คํ–‰”, “๋งค์ดˆ ๋ฐ˜๋ณต”)
Action ์‹ค์ œ๋กœ ์บ๋ฆญํ„ฐ๊ฐ€ ํ•˜๋Š” ํ–‰๋™ (๊ณต๊ฒฉ, ์ด๋™, ๋Œ€๊ธฐ ๋“ฑ)
Condition ์ƒํƒœ ๊ฒ€์‚ฌ (ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๋ณด์ด๋Š”๊ฐ€? ์ฒด๋ ฅ์ด ๋‚ฎ์€๊ฐ€?)

๐Ÿงฉ Unity์—์„œ์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

Unity๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Behavior Tree ์‹œ์Šคํ…œ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์ง„ ์•Š์•„์š”.
๊ทธ๋ž˜์„œ ๋ณดํ†ต ์•„๋ž˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘‡

  1. ์ง์ ‘ ๊ตฌํ˜„ (C#์œผ๋กœ ์ปค์Šคํ…€ Behavior Tree ๋งŒ๋“ค๊ธฐ)
    • ์ž์œ ๋„๊ฐ€ ๋†’์ง€๋งŒ ์ฝ”๋“œ๋Ÿ‰ ๋งŽ์Œ.
    • ์˜ˆ: Node, CompositeNode, ActionNode ํด๋ž˜์Šค ๊ตฌ์กฐ๋กœ ์ง์ ‘ ์ œ์ž‘.
  2. ํ”Œ๋Ÿฌ๊ทธ์ธ / ํˆด ์‚ฌ์šฉ
    • Behavior Designer (by Opsive) → ์‹œ๊ฐ์ ์œผ๋กœ Behavior Tree ๊ตฌ์„ฑ ๊ฐ€๋Šฅ (์œ ๋ฃŒ)
    • NodeCanvas, Bolt/FlowCanvas, Panda BT ๋“ฑ
    • ๋…ธ๋“œ ๊ธฐ๋ฐ˜ ๋น„์ฃผ์–ผ ์Šคํฌ๋ฆฝํŒ…์ฒ˜๋Ÿผ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ์œผ๋กœ ํŠธ๋ฆฌ ๊ตฌ์„ฑ ๊ฐ€๋Šฅ

๐Ÿง  ์˜ˆ์‹œ (์ง์ ‘ ๊ตฌํ˜„ํ•œ ๊ฐ„๋‹จํ•œ ๊ตฌ์กฐ)

 
public abstract class Node { public abstract bool Execute(); } public class Sequence : Node { private List<Node> children = new List<Node>(); public Sequence(params Node[] nodes) { children.AddRange(nodes); } public override bool Execute() { foreach (var node in children) { if (!node.Execute()) return false; // ํ•˜๋‚˜๋ผ๋„ ์‹คํŒจํ•˜๋ฉด ์ข…๋ฃŒ } return true; } } public class ActionNode : Node { private Func<bool> action; public ActionNode(Func<bool> action) => this.action = action; public override bool Execute() => action(); }

์ด๋Ÿฐ ์‹์œผ๋กœ

 
var attackSequence = new Sequence( new ActionNode(CheckPlayerInSight), new ActionNode(Attack) );

์ฒ˜๋Ÿผ ์กฐํ•ฉํ•ด์„œ ํŠธ๋ฆฌ์ฒ˜๋Ÿผ ํ–‰๋™์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.