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 ์์คํ
์ด ๋ด์ฅ๋์ด ์์ง ์์์.
๊ทธ๋์ ๋ณดํต ์๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค ๐
- ์ง์ ๊ตฌํ (C#์ผ๋ก ์ปค์คํ
Behavior Tree ๋ง๋ค๊ธฐ)
- ์์ ๋๊ฐ ๋์ง๋ง ์ฝ๋๋ ๋ง์.
- ์: Node, CompositeNode, ActionNode ํด๋์ค ๊ตฌ์กฐ๋ก ์ง์ ์ ์.
- ํ๋ฌ๊ทธ์ธ / ํด ์ฌ์ฉ
- 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) );
์ฒ๋ผ ์กฐํฉํด์ ํธ๋ฆฌ์ฒ๋ผ ํ๋์ ๊ตฌ์ฑํฉ๋๋ค.