Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
내비게이션 모드
Godot는 2D 및 3D 게임에 대한 그리드 기반 또는 메시 기반 탐색 및 경로 찾기를 용이하게 하기 위해 여러 개체, 클래스 및 서버를 제공합니다. 다음 섹션은 3D 장면을 위해 Godot에서 사용 가능한 모든 탐색 관련 객체와 그 주요 용도에 대한 빠른 개요를 제공합니다.
Godot는 다음 3D 씬 파일 형식을 지원합니다:
- Area2D
Astar3D개체는 가중치 점 그래프에서 최단 경로를 찾는 옵션을 제공합니다.AStar3D 클래스는 액터가 영역 내의 가능한 위치에 도달할 필요가 없고 미리 정의된 고유한 위치에만 도달하도록 요구하는 셀 기반 3D 게임플레이에 가장 적합합니다.
- String
``NavigationServer3D``는 탐색 메시로 정의된 영역에서 두 위치 사이의 최단 경로를 찾는 강력한 서버 API를 제공합니다.
NavigationServer는 액터가 정의된 내비게이션 메시 영역 내에서 가능한 모든 위치에 도달해야 하는 3D 실시간 게임플레이에 가장 적합합니다. 메쉬 기반 내비게이션은 대규모 게임 세계에 맞게 확장됩니다. 많은 그리드 셀이 필요한 경우 단일 다각형으로 넓은 영역을 정의할 수 있는 경우가 많기 때문입니다.
NavigationServer는 각각 탐색 메시 데이터를 보유하는 영역으로 구성된 다양한 탐색 맵을 보유합니다. 회피 계산을 위해 에이전트를 지도에 배치할 수 있습니다. RID는 서버와 통신할 때 내부 지도, 지역 및 에이전트를 참조하는 데 사용됩니다.
- 다음 NavigationServer RID 유형을 사용할 수 있습니다.
- NavMap RID
지역과 에이전트가 포함된 특정 탐색 지도에 대한 참조입니다. 지도는 근접성을 기준으로 지역의 내비게이션 메시를 결합하려고 시도합니다. 맵은 각 물리 프레임마다 지역과 에이전트를 동기화합니다.
- Nav지역 RID
탐색 메시 데이터를 보유할 수 있는 특정 탐색 영역에 대한 참조입니다. 탐색 레이어 비트마스크를 사용하여 영역을 활성화/비활성화하거나 사용을 제한할 수 있습니다.
- NavLink RID
임의의 거리에 걸쳐 두 개의 탐색 메시 위치를 연결하는 특정 탐색 링크에 대한 참조입니다.
- NavAgent RID
특정 회피 행위자에 대한 언급. 회피는 반경 값으로 정의됩니다.
- 내비게이션
에이전트의 회피 속도에 영향을 미치고 제한하는 데 사용되는 특정 회피 장애물에 대한 참조입니다.
다음 씬 트리 노드는 NavigationServer3D API 작업을 위한 도우미로 사용할 수 있습니다.
- String
NavigationServer3D에 대한 탐색 메시를 정의하는 탐색 메시 리소스를 보유하는 노드입니다.
지역을 활성화/비활성화할 수 있습니다.
경로 찾기에서의 사용은
navigation_layers비트마스크를 통해 추가로 제한될 수 있습니다.NavigationServer3D는 결합된 탐색 메시에 대한 근접성을 기준으로 영역의 탐색 메시를 결합합니다.
- String
길 찾기를 위해 임의의 거리에 걸쳐 탐색 메시의 두 위치를 연결하는 노드입니다.
링크를 활성화/비활성화할 수 있습니다.
링크는 단방향 또는 양방향으로 이루어질 수 있습니다.
경로 찾기에서의 사용은
navigation_layers비트마스크를 통해 추가로 제한될 수 있습니다.
링크는 연결이 존재하고 비용이 얼마나 드는지 길찾기에 알려줍니다. 실제 에이전트 처리 및 이동은 사용자 정의 스크립트에서 이루어져야 합니다.
- String
경로 찾기 및 회피를 위한 일반적인 NavigationServer3D API 호출을 용이하게 하는 데 사용되는 도우미 노드입니다. Node3D 상속 상위 노드와 함께 이 노드를 사용하세요.
- Dictionary
회피 가능 에이전트의 회피 속도에 영향을 미치고 제한하는 데 사용할 수 있는 노드입니다. 이 노드는 에이전트의 경로 찾기에 영향을 주지 않습니다. 대신 탐색 메시를 변경해야 합니다.
적 씬은 다음 노드들을 사용할 것입니다:
- String
3D 탐색 메시 데이터를 보유하는 리소스입니다. 이는 런타임뿐만 아니라 편집기 내에서 탐색 영역을 정의하기 위한 3D 지오메트리 베이킹 옵션을 제공합니다.
NavigationRegion3D 노드는 이 리소스를 사용하여 탐색 영역을 정의합니다.
NavigationServer3D는 이 리소스를 사용하여 개별 영역의 탐색 메시를 업데이트합니다.
GridMap Editor는 각 그리드 셀에 대해 특정 탐색 메시가 정의될 때 이 리소스를 사용합니다.
더 보기
이 문서 외에 여러가지 Godot 데모 프로젝트들도 살펴보면 좋습니다.
3D 씬 가져오기
다음 단계에서는 3D에서 최소한의 실행 가능한 탐색을 위한 기본 설정을 보여줍니다. 경로 이동을 위해 NavigationServer3D 및 NavigationAgent3D를 사용합니다.
씬에 NavigationRegion3D 노드를 추가합니다.
노드 지역을 클릭하고 노드 지역에 새 NavigationMesh 리소스를 추가합니다.
노드에 스크립트를 추가하기.
MeshInstance3D 노드를 선택하고 새 PlaneMesh를 추가하고 xy 크기를 10으로 늘립니다.
노드 지역을 다시 선택하고 상단 표시줄에 있는 "Bake Navmesh" 버튼을 누릅니다.
이제 PlaneMesh 위에서 일정 거리를 이동하는 투명한 탐색 메시가 나타납니다.
기본 충돌 모양과 시각적용 메시를 사용하여 씬에 CharacterBody3D 노드를 추가합니다.
문자 노드 아래에 NavigationAgent3D 노드를 추가합니다.
다음 내용으로 스크립트를 CharacterBody3D 노드에 추가합니다. 씬이 완전히 로드되고 NavigationServer가 동기화된 후에 이동 대상을 설정해야 합니다. 또한 Camera3D와 일부 조명 및 환경을 추가하여 무언가를 볼 수 있습니다.
extends CharacterBody3D
var movement_speed: float = 2.0
var movement_target_position: Vector3 = Vector3(-3.0,0.0,2.0)
@onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D
func _ready():
# These values need to be adjusted for the actor's speed
# and the navigation layout.
navigation_agent.path_desired_distance = 0.5
navigation_agent.target_desired_distance = 0.5
# Make sure to not await during _ready.
actor_setup.call_deferred()
func actor_setup():
# Wait for the first physics frame so the NavigationServer can sync.
await get_tree().physics_frame
# Now that the navigation map is no longer empty, set the movement target.
set_movement_target(movement_target_position)
func set_movement_target(movement_target: Vector3):
navigation_agent.set_target_position(movement_target)
func _physics_process(delta):
if navigation_agent.is_navigation_finished():
return
var current_agent_position: Vector3 = global_position
var next_path_position: Vector3 = navigation_agent.get_next_path_position()
velocity = current_agent_position.direction_to(next_path_position) * movement_speed
move_and_slide()
using Godot;
public partial class MyCharacterBody3D : CharacterBody3D
{
private NavigationAgent3D _navigationAgent;
private float _movementSpeed = 2.0f;
private Vector3 _movementTargetPosition = new Vector3(-3.0f, 0.0f, 2.0f);
public Vector3 MovementTarget
{
get { return _navigationAgent.TargetPosition; }
set { _navigationAgent.TargetPosition = value; }
}
public override void _Ready()
{
base._Ready();
_navigationAgent = GetNode<NavigationAgent3D>("NavigationAgent3D");
// These values need to be adjusted for the actor's speed
// and the navigation layout.
_navigationAgent.PathDesiredDistance = 0.5f;
_navigationAgent.TargetDesiredDistance = 0.5f;
// Make sure to not await during _Ready.
Callable.From(ActorSetup).CallDeferred();
}
public override void _PhysicsProcess(double delta)
{
base._PhysicsProcess(delta);
if (_navigationAgent.IsNavigationFinished())
{
return;
}
Vector3 currentAgentPosition = GlobalTransform.Origin;
Vector3 nextPathPosition = _navigationAgent.GetNextPathPosition();
Velocity = currentAgentPosition.DirectionTo(nextPathPosition) * _movementSpeed;
MoveAndSlide();
}
private async void ActorSetup()
{
// Wait for the first physics frame so the NavigationServer can sync.
await ToSignal(GetTree(), SceneTree.SignalName.PhysicsFrame);
// Now that the navigation map is no longer empty, set the movement target.
MovementTarget = _movementTargetPosition;
}
}
참고
첫 번째 프레임에서 NavigationServer 맵은 지역 데이터를 동기화하지 않았으며 모든 경로 쿼리는 빈 값을 반환합니다. 스크립트에서 한 프레임을 기다려 NavigationServer 동기화를 기다립니다.