[Unity6] 2D Behavior Tree 1( Patrol, Wait )
์นดํ ๊ณ ๋ฆฌ: Go Unity
Behavior Tree
Behaviour Tree Manual
-ย Behaviour Tree - AI ์บ๋ฆญํฐ์ ํ๋ ์ ์ด๋ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด ์ฌ์ฉํฉ๋๋ค.
-ย Behaviour Tree๋ ๊ฒ์ ๊ฐ๋ฐ์์ ๋น์ ํ์ ์ด๊ณ , ๋ณต์กํ AI ์์ฌ ๊ฒฐ์ ์ ๊ฐ๋จํ๊ฒ ๋ชจ๋ํํ์ฌ ๊ตฌํํ ์ ์๊ฒ ํด์ค๋๋ค.
-ย Unity6๋ถํฐ Built-in์ผ๋ก ์ง์, ๋
ธ๋ ๊ธฐ๋ฐ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ฒ ์ ๊ณตํฉ๋๋ค.
Node
โ Action Node : ์ค์ ํ๋์ ์ํํ๋ ๋
ธ๋
ย ย ํธ๋ฆฌ์ ํ๋จ์ ์์น, ์์ด์ ํธ๊ฐ ํด์ผ ํ ๊ตฌ์ฒด์ ์ธ ์์
์ ์
ย
โ Modifier Node : ํธ๋ฆฌ์ ํ๋ฆ์ด๋ ์คํ ์กฐ๊ฑด์ ์์
ย ย ํน์ ์กฐ๊ฑด์ ํ์ธ, ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
ย
โ Sequencing Node : ํด๋น ๋
ธ๋๊ฐ ์๋ ์์ ๋
ธ๋๋ค์ ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ์คํ
ย ย ๋ชจ๋ ์์ ๋
ธ๋๊ฐ ์ฑ๊ณตํด์ผ ์์ ๋ ์ฑ๊ณต ์ํ ๋ฐํ
ย
โ Join Node : ์ฌ๋ฌ ๋
ธ๋์์ ๋ฐ์ํ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐํฉํด ํ๋์ ๊ฒฐ์ ํ๋ ๋ฐ ์ฌ์ฉ
์ฌ์ฉ๋ฒ
1.ย Package Manager - Behavior install
ย
2.ย Project - Behavior Graph ์์ฑ
ย
3.ย Behavior Graph ๋๋ธํด๋ฆญ - ์ฐํด๋ฆญ-> ๋
ธ๋ ์ถ๊ฐ
Behavior Graph
BlackBoard : ์ฌ์ฉํ๋ ๋ณ์ ๋ชฉ๋ก, ๊ธฐ๋ณธ์ ์ผ๋ก ์๊ธฐ ์์ ์ ๋ํ๋ด๋ Self ๋ณ์ ์์ฑ
ย BlackBoard์ ์ ์ธํ ๋ณ์๋ ์ธ๋ถ์์ ์ ๊ทผ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ Insspector View์ ์ถ๋ ฅ๋๋ฉฐ, ์คํฌ๋ฆฝํธ์์ Get/Set ๊ฐ๋ฅ
ย
๋
ธ๋ ์์ฑ : ์ฐํด๋ฆญ - Add
ย Action -> Navigation -> Nav To Target(๋ชฉํ์๊ฒ ์ด๋), To Location, Patrol(์์ฐฐ)์ ์ ๊ณต
์์ฐฐ(Patrols)
1.ย ๋
ธ๋ ์์ฑ : Add -> Action -> Navigation -> Patrol
2.ย Agent - Self ๋๋๊ทธ
3.ย WayPoint ์ค์ (PatrolPoints)
BlackBoard์ List - GameObject List ์ถ๊ฐ, ๋๋๊ทธ
ย
๋๊ธฐ(Patrols)
1.ย Add -> Flow -> Sequence
2.ย Add -> Action -> Delay - Wait(Range)
3.ย Add -> Flow -> TimeOut
ย
1~3์ด ๋๊ธฐ 10์ด ์์ฐฐ ๋ฐ๋ณต
์ฝ๋
EnemyFSM
Prefab
Behavior Agent ์ปดํฌ๋ํธ ์ถ๊ฐ
Behavior Agent Graph ๋ฑ๋ก
ย
EnemyFSM
behaviorAgent.SetVariableValue(โPatrolPointsโ, wayPoints.ToList());
Behavior Graph์ Blackboard์ ์ ์ธํ ๋ณ์ ๊ฐ์ ์ค์ (๋ณ์๋ช
๋๊ฐ์ด)
EnemyFSM
using System.Linq;
using UnityEngine;
using UnityEngine.AI;
using Unity.Behavior;
public class EnemyFSM : MonoBehaviour
{
private Transform target;
private NavMeshAgent navMeshAgent;
private BehaviorGraphAgent behaviorAgent;
public void Setup(Transform target, GameObject[] wayPoints)
{
this.target = target;
navMeshAgent = GetComponent<NavMeshAgent>();
behaviorAgent = GetComponent<BehaviorGraphAgent>();
navMeshAgent.updateRotation = false;
navMeshAgent.updateUpAxis = false;
behaviorAgent.SetVariableValue("PatrolPoints", wayPoints.ToList());
}
}
EnemySpawner
EnemySpawner WayPoint ์ค์
EnemySpawner ์ ์ ์คํฐ ๊ฐ๋ฅ ์์น ์คํฐ, WayPoint(์์ฐฐ๊ตฌ์ญ)์ ์ ํ์ฌ Enemy ์คํฐ.
EnemySpawner
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class EnemySpawner : MonoBehaviour
{
[SerializeField]
private Tilemap tilemap;
[SerializeField]
private GameObject enemyPrefab;
[SerializeField]
private Transform target;
[SerializeField]
private int enemyCount = 10;
private Vector3 offset = new Vector3(0.5f, 0.5f, 0);
private List<Vector3> possibleTiles = new List<Vector3>();
[System.Serializable]
private struct WayPointData
{
public GameObject[] wayPoints;
}
[SerializeField]
private WayPointData[] wayPointData;
private void Awake()
{
// Tilemap์ Bounds ์ฌ์ค์ (๋งต์ ์์ ํ์ ๋ Bounds๊ฐ ๋ณ๊ฒฝ๋์ง ์๋ ๋ฌธ์ ํด๊ฒฐ)
tilemap.CompressBounds();
// ํ์ผ๋งต์ ๋ชจ๋ ํ์ผ์ ๋์์ผ๋ก ์ ๋ฐฐ์น๊ฐ ๊ฐ๋ฅํ ํ์ผ ๊ณ์ฐ
CalculatePossibleTiles();
// ์์์ ํ์ผ์ enemyCount ์ซ์๋งํผ ์ ์์ฑ
for ( int i = 0; i < enemyCount; ++ i )
{
int index = Random.Range(0, possibleTiles.Count);
int wayIndex = Random.Range(0, wayPointData.Length);
GameObject clone = Instantiate(enemyPrefab, possibleTiles[index], Quaternion.identity, transform);
clone.GetComponent<EnemyFSM>().Setup(target, wayPointData[wayIndex].wayPoints);
}
}
private void CalculatePossibleTiles()
{
BoundsInt bounds = tilemap.cellBounds;
// ํ์ผ๋งต ๋ด๋ถ ๋ชจ๋ ํ์ผ์ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ allTiles ๋ฐฐ์ด์ ์ ์ฅ
TileBase[] allTiles = tilemap.GetTilesBlock(bounds);
// ์ธ๊ณฝ ๋ผ์ธ์ ์ ์ธํ ๋ชจ๋ ํ์ผ ๊ฒ์ฌ
for ( int y = 1; y < bounds.size.y-1; ++ y )
{
for ( int x = 1; x < bounds.size.x-1; ++ x )
{
// [y * bounds.size.x + x]๋ฒ์งธ ๋ฐฉ์ ํ์ผ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ด
TileBase tile = allTiles[y * bounds.size.x + x];
// ํด๋น ํ์ผ์ด ๋น์ด์์ง ์์ผ๋ฉด ์ ๋ฐฐ์น ๊ฐ๋ฅ ํ์ผ๋ก ํ๋จ
if ( tile != null )
{
Vector3Int localPosition = bounds.position + new Vector3Int(x, y);
Vector3 position = tilemap.CellToWorld(localPosition) + offset;
position.z = 0;
possibleTiles.Add(position);
}
}
}
}
}
์ด๊ฒ์ ๊ฒ ๋ฉ๋ชจ
BehaviorGraph ์ ๋ ฌ
๋
ธ๋ ์ ์ฐํด๋ฆญ - Align - All Children (๋
ธ๋ ์ ๋ ฌ)
์ก๋ด, ์ผ๊ธฐ?
์ ๋ํฐ6 NavMesh, BehaviorTree
๋๊ธ๋จ๊ธฐ๊ธฐ