설치
- godot engine은 GDScript만 사용가능
- godot engine - .NET은 C#, GDScript 사용가능
카메라 추가
- AddNode > Camera3D
형태 추가
- AddNode > MeshInstance3D
- Inspector > Mesh > New CubeMesh
- New SphereMesh, New CylinderMesh, New CapsuleMesh
조명, 카메라
- DirectionalLight3D, OmniLight3D, SpotLight3D
언어 설정 변경 방법
- Godot 열기:
- Godot을 실행하여 에디터 화면으로 들어갑니다.
- Editor Settings 접근:
- 상단 메뉴에서 “Editor”를 클릭하고 “Editor Settings”를 선택합니다. 이 메뉴는 Godot 에디터의 다양한 환경설정을 조정할 수 있는 곳입니다.
- 언어 설정 변경:
- “Editor Settings” 창에서 왼쪽 사이드바에 있는 “Interface” 탭을 탐색합니다.
- “Editor” 섹션을 찾은 다음, “Language” 옵션을 찾습니다.
- “Language” 드롭다운 메뉴를 클릭하고 “en” (영어)를 선택합니다.
- 변경사항 적용:
- 설정을 변경하면 즉시 적용됩니다. 별도의 저장 버튼이 필요 없이, 언어가 영어로 변경될 것입니다.
기본 설정 단계
- Viewport 생성:
Viewport
노드를 씬에 추가합니다.Viewport
노드의 크기, 클리어 모드 및 기타 속성을 필요에 맞게 설정합니다. 예를 들어,Size
를 설정하여 렌더링 해상도를 정의할 수 있습니다.
- Viewport 사용을 위한 Camera 추가:
Viewport
노드의 자식으로Camera3D
(또는Camera2D
, 2D의 경우)를 추가합니다.- 이 카메라는
Viewport
의 콘텐츠를 찍게 됩니다.
- MeshInstance에 텍스처 적용:
- 씬에
MeshInstance3D
노드를 추가하고, 필요한 경우QuadMesh
타입의 메쉬를 선택합니다. MeshInstance3D
의Material
속성을 클릭하여,New SpatialMaterial
을 추가합니다.- 만든
SpatialMaterial
에서Albedo
텍스처 부분에ViewportTexture
를 사용합니다. ViewportTexture
에서 원하는Viewport
를 지정하여 해당 뷰포트의 출력이Quad
에 렌더링되도록 합니다.
- 씬에
- Viewport 설정:
Viewport
노드에서 “Render Target” 옵션을 활성화하여 뷰포트 콘텐츠가 텍스처로 출력되도록 합니다.
추가 고려 요소
- Viewport 및 텍스처 품질: 뷰포트의 해상도 및 렌더링 품질을 조정하여 텍스처의 품질을 관리할 수 있습니다.
- 다중 뷰포트: 여러 개의 뷰포트 및 뷰포트 텍스처를 사용하여 복수의 화면 또는 특수 효과를 구현할 수 있습니다.
- 경계사항 처리: 크기, 해상도 및 성능 관련 최적화는 필수적이며, 예상치 못한 렌더링 비용을 최소화하도록 주의해야 합니다.
변경된 재질(Material) 옵션:
- StandardMaterial3D:
- 주로 3D 모델 및 오브젝트의 표면에 사용됩니다.
- 다양한 PBR 설정을 통해 오브젝트의 물리적 특성을 시뮬레이션할 수 있습니다. 기본적으로 색상, 알베도(색상), 메탈릭, 거칠기 등의 속성을 활용할 수 있습니다.
- ORMMaterial3D:
- ORM은 Occlusion, Roughness, Metallic의 약자로, 이 세 가지 속성을 하나의 텍스처에서 처리할 수 있는 재질입니다.
- 이를 통해 텍스처 메모리 사용량을 최적화할 수 있습니다.
- ShaderMaterial:
- 커스텀 GLSL 셰이더 코드를 작성할 수 있도록 지원하는 재질입니다.
- 자신의 고유한 셰이더를 만들어 복잡하고 독특한 시각 효과를 구현할 수 있습니다.
현재 상황에 맞는 선택:
- 대개의 경우, 기본 3D 재질을 사용할 때는
StandardMaterial3D
를 선택하는 것이 좋습니다. 이 재질은 많은 경우에 충분한 유연성과 성능을 제공합니다. - 만약 고유한 비주얼 효과를 구현해야 한다면,
ShaderMaterial
을 사용하여 셰이더를 직접 작성하면 됩니다. ORMMaterial3D
는 특정 상황에서 최적화된 텍스처 관리가 필요할 경우 고려할 수 있습니다.
ViewportTexture 생성 에러
이 오류 메시지는 ViewportTexture
를 생성하려는 Viewport
가 “Local to Scene”으로 설정되지 않았기 때문에 발생하는 문제입니다. “Local to Scene”이라는 설정은 해당 Viewport
가 직접적으로 장면(Scene) 내에 포함되어 있는 자원을 나타내는지 확인하는 데 사용됩니다. 이 설정을 활성화해야 ViewportTexture
를 올바르게 만들 수 있습니다.
문제 해결 방법
- Viewport 설정 변경:
Viewport
노드를 선택합니다.Inspector
패널에서 “Flags” 섹션을 찾습니다.- “Local to Scene” 옵션(플래그)를 찾아 체크합니다.
이 설정을 변경하면 해당
Viewport
는 로컬로 해당 씬 내에 존재하는 자원으로 인식될 수 있으며,ViewportTexture
를 생성할 수 있게 됩니다. - ViewportTexture 생성 재시도:
Viewport
의 “Local to Scene” 플래그가 활성화되면 다시ViewportTexture
를 생성할 수 있습니다.
추가 팁
- Local to Scene의 의미: “Local to Scene” 플래그는 Godot에서 자원이나 노드가 특정 씬 내에서만 고유하게 동작하도록 합니다. 일반적으로 씬 인스턴싱이나 여러 씬 간의 자원 공유 시 문제가 발생하지 않도록 하며, 특히
Viewport
와 같은 노드에서 매우 중요한 설정입니다.
- Material 하단 Resurces 항목에 Local to Scene 체크가 있음
Viewport와 SubViewport
-
Viewport: 메인 윈도우 및 화면 렌더링에 주요하게 사용되는 노드입니다. 게임의 주된 렌더링 대상이며, 여러 가지 설정 및 최적화를 위해 제공됩니다. 주로 화면 전체를 처리하거나 루트 노드로 사용됩니다.
-
SubViewport: 서브뷰(View) 혹은 특정한 목적을 위한 뷰를 관리하기 위해 도입된 노드입니다. 이는 뷰 내에 다른 뷰를 중첩하거나, 화면 일부를 위해 사용할 수 있도록 만들어졌습니다. 예를 들어, UI 위젯 내에서 3D 모델을 미리보기로 표현할 때, 또는 미니맵, 포스트 프로세스 처리 등 특정 영역이나 기능을 렌더링할 때 유용합니다.
사용 예시
- 기본 Viewport 사용:
- 대부분의 프로젝트에서
Viewport
는 기본적으로 제공되며, 메인 게임 화면을 그립니다.
- 대부분의 프로젝트에서
- SubViewport 사용:
- 추가적인 뷰를 만들고 싶을 때 사용되며,
SubViewport
는 그래픽을 렌더링하는 도구로 활용할 수 있습니다.
- 추가적인 뷰를 만들고 싶을 때 사용되며,
Godot 4.0에서는 이전과 달리 SubViewport
를 사용하여 더 많은 창의적 가능성을 제공하며, 다양한 뷰 및 특수 효과를 보다 클린하게 구현할 수 있습니다. Viewport
와 SubViewport
는 서로 대체하거나 사라지는 개념이 아니라, 용도에 맞춰 각각 사용 가능한 기능입니다.
이동관련 c#
using Godot;
public class CameraController : Spatial
{
[Export] public float MoveSpeed = 5f; // 이동 속도
[Export] public float MouseSensitivity = 0.1f; // 마우스 감도
private Vector3 _velocity = new Vector3(); // 카메라 이동 벡터
private float _yaw = 0f; // Y축 회전 (좌우)
private float _pitch = 0f; // X축 회전 (상하)
public override void _Process(float delta)
{
// 입력에 따라 이동 계산
_velocity = new Vector3();
if (Input.IsActionPressed("ui_up")) _velocity.z -= 1;
if (Input.IsActionPressed("ui_down")) _velocity.z += 1;
if (Input.IsActionPressed("ui_left")) _velocity.x -= 1;
if (Input.IsActionPressed("ui_right")) _velocity.x += 1;
if (Input.IsActionPressed("move_up")) _velocity.y += 1; // 상승 (E 키)
if (Input.IsActionPressed("move_down")) _velocity.y -= 1; // 하강 (Q 키)
// 이동 속도 적용
_velocity = _velocity.Normalized() * MoveSpeed * delta;
Translate(_velocity);
// 마우스 이동에 따른 회전 계산
if (Input.IsActionPressed("ui_accept")) // 마우스 드래그 버튼 (보통 왼쪽 클릭)
{
Vector2 mouseMovement = new Vector2(
Input.GetActionStrength("mouse_right") - Input.GetActionStrength("mouse_left"),
Input.GetActionStrength("mouse_up") - Input.GetActionStrength("mouse_down")
);
_yaw -= mouseMovement.x * MouseSensitivity;
_pitch -= mouseMovement.y * MouseSensitivity;
}
// 회전 적용
RotationDegrees = new Vector3(_pitch, _yaw, 0);
}
}
extends Camera3D
# 속도 및 감도 설정
var move_speed := 5.0
var mouse_sensitivity := 0.1
# 내부 상태 변수
var yaw := 0.0
var pitch := 0.0
func _ready():
# 마우스 커서 숨기기 및 잡기
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _unhandled_input(event):
# 마우스 회전 계산
if event is InputEventMouseMotion:
yaw -= event.relative.x * mouse_sensitivity
pitch -= event.relative.y * mouse_sensitivity
pitch = clamp(pitch, -89, 89) # X축에 대한 회전 제한
# 회전 적용
rotation_degrees = Vector3(pitch, yaw, 0)
func _process(delta):
# 이동 계산
var input_vector: Vector3 = Vector3.ZERO
if Input.is_action_pressed("ui_up"):
input_vector.z -= 1
if Input.is_action_pressed("ui_down"):
input_vector.z += 1
if Input.is_action_pressed("ui_left"):
input_vector.x -= 1
if Input.is_action_pressed("ui_right"):
input_vector.x += 1
if Input.is_action_pressed("move_up"):
input_vector.y += 1
if Input.is_action_pressed("move_down"):
input_vector.y -= 1
# 이동 적용
input_vector = input_vector.normalized() * move_speed * delta
translate(input_vector)
뷰포트 하위 객체의 종속성 등록
extends Node3D
var initial_local_transform: Transform3D = Transform3D.IDENTITY
func _ready():
# 자식 노드의 초기 로컬 변환을 저장합니다.
if has_node("SubViewport/Camera3D"):
initial_local_transform = $SubViewport/Camera3D.transform
func _process(delta):
# 노드가 존재하는지 확인합니다.
var target = $SubViewport/Camera3D if has_node("SubViewport/Camera3D") else null
if target:
var parent_global_transform = global_transform
# 부모 노드의 변환을 초기 로컬 변환과 결합하여 설정합니다.
target.global_transform = parent_global_transform * initial_local_transform
else:
print("Target node not found!")
godot setting
- godot에서 scene과 play 화면이 차이가 나는 이유 : https://www.reddit.com/r/godot/comments/170dmaw/why_does_it_look_so_different_when_i_run_it/
- The editor automatically adds sky, ground and light for you. But they are not in the real time execution. Try to add some light node in your project first, and maybe check the Environment node for sky/background color.
- 편집기가 자동으로 하늘, 지면, 빛을 추가해줍니다. 하지만 실시간 실행에서는 포함되지 않습니다. 먼저 프로젝트에 빛 노드를 추가하고, 하늘/배경색을 위해 환경 노드를 확인해 보세요.
- WorldEnvironment
WorldEnvironment
- WorldEnvironment Node 추가: 씬에
WorldEnvironment
노드를 추가합니다. - Environment Resource 생성:
WorldEnvironment
노드를 선택하고 인스펙터에서Environment
속성을 새로운Environment
리소스로 설정합니다. - Sky 설정:
Environment
설정에서Background
를 선택하고,Sky
옵션을 설정합니다.Sky
탭에서New PanoramaSky
또는New ProceduralSky
를 선택합니다.PanoramaSky
를 선택한 경우, 원하는 하늘 이미지를 로드하십시오.ProceduralSky
를 선택한 경우, 하늘의 매개변수를 조절해 원하는 하늘 모양을 설정합니다.
DirectionalLight
중간과정 저장
@tool
extends Node3D # Node3D 클래스를 상속받아 씬 내에서 3D 위치를 가질 수 있습니다.
@export var camera: Camera3D # 이 변수를 에디터에서 Camera3D 노드로 설정해야 합니다.
@export var quad: Node3D # 이 변수를 에디터에서 바라볼 Quod 노드로 설정해야 합니다.
func _process(delta):
if camera and quad:
# 쿼드의 현재 전역 좌표를 가져옵니다.
var quad_global_position = quad.global_transform.origin
# 카메라가 항상 쿼드를 바라보도록 설정합니다.
#camera.look_at(quad_global_position, camera.transform.basis.y)
# 카메라의 뷰포트 크기를 기준으로 프러스텀 오프셋을 결정합니다.
var viewport_size = get_viewport().size
var offset_x = (quad_global_position.x - camera.global_transform.origin.x)
var offset_y = (quad_global_position.y - camera.global_transform.origin.y)
# 오프셋 설정 (여기 offset_x와 offset_y는 원하는 방식으로 계산해 넣어야 함)
camera.frustum_offset = Vector2(offset_x, offset_y)
# near값(near clip)의 설정 (여기서는 쿼드와 카메라 사이의 거리로 설정)
camera.size = camera.global_transform.origin.distance_to(quad_global_position) / 2
종속성 등록 수정
@tool
extends Node3D
var initial_local_transform: Transform3D = Transform3D.IDENTITY
@export var camera: Camera3D # 이 변수를 에디터에서 Camera3D 노드로 설정해야 합니다.
func _process(delta):
# 노드가 존재하는지 확인합니다.
var target = $SubViewport/Camera3D if has_node("SubViewport/Camera3D") else null
if target:
var parent_global_transform = camera.global_transform
# 부모 노드의 변환을 초기 로컬 변환과 결합하여 설정합니다.
target.global_transform = parent_global_transform
else:
print("Target node not found!")