Community코딩 & 개발github.com

ziva-sh/godot-control-layout

Godot 4 컨트롤 UI가 잘리거나 겹치지 않고 크기가 조절되도록 빌드합니다. 컨테이너, 앵커 프리셋, 크기 플래그, custom_minimum_size, MarginContainer 여백, Label 줄바꿈, mouse_filter, CanvasLayer HUD, Godot 4 테마 오버라이드 이름, 다중 해상도를 위한 display/window/stretch 설정을 다룹니다. 메뉴, HUD, 대화상자, 인벤토리 화면을 만들거나 수정할 때, UI 요소가 잘리거나 크기가 0이거나 겹칠 때 사용하세요.

godot-control-layout란 무엇인가요?

이 스킬은 Godot 4에서 깔끔하고 반응형 UI를 만드는 핵심 원칙과 실용적인 코드 예제를 제공합니다. 대부분의 UI 문제는 컨테이너의 자식 위치를 수동으로 설정하거나, 앵커를 설정할 때 오프셋을 초기화하지 않거나, 스트레치 설정을 기본값으로 남겨두는 세 가지 실수에서 발생합니다. 스킬은 컨테이너 내 자식의 공간을 제어하기 위해 size_flags와 custom_minimum_size를 사용하고, 루트 UI 노드에만 set_anchors_and_offsets_preset()을 사용할 것을 권장합니다. 또한 CanvasLayer 아래에 배치하여 카메라와 독립적인 HUD를 만드는 방법, 자동 줄바꿈 Label에서 너비가 부족하여 텍스트가 잘리는 문제를 해결하는 방법, mouse_filter로 클릭 이벤트가 게임으로 전달되도록 제어하는 방법, Godot 4의 새로운 테마 오버라이드 함수 이름을 올바르게 사용하는 방법, 그리고 project.godot에서 display/window/stretch 설정을 구성하여 다양한 해상도를 지원하는 방법을 설명합니다. 체크리스트를 통해 UI가 잘리거나 겹치는 문제를 단계별로 진단하고 해결할 수 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ziva-sh/godot-skills/tree/HEAD/skills/godot-control-layout

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Godot 4에서의 컨트롤 레이아웃

깨진 Godot UI의 대부분은 세 가지 실수에서 비롯됩니다: 컨테이너의 자식 위치를 수동으로 설정하거나, 오프셋을 초기화하지 않고 앵커를 설정하거나, 스트레치 설정을 기본값으로 남겨두는 것입니다. 컨테이너로 레이아웃하고, 각 UI의 루트에만 앵커를 설정하며, 최소 크기가 나머지를 결정하도록 하십시오.

컨테이너는 자식을 소유합니다

Container (VBoxContainer, HBoxContainer, GridContainer, MarginContainer, PanelContainer, CenterContainer, ScrollContainer, FlowContainer)의 자식은 자체 position, size 또는 앵커를 유지할 수 없습니다. 다음 정렬 시 컨테이너가 이를 덮어씁니다. 다음으로 자식의 공간 점유를 제어하십시오:

  • size_flags_horizontal / size_flags_vertical: Control.SIZE_FILL (기본값), SIZE_EXPAND_FILL (남는 공간 차지), SIZE_SHRINK_CENTER / SIZE_SHRINK_END (작게 유지하고 정렬).
  • size_flags_stretch_ratio: 확장하는 형제들 사이에서 남는 공간의 비율.
  • custom_minimum_size: 자식이 허용하는 가장 작은 크기. 컨테이너는 결합된 최소 크기 아래로 자식을 줄이지 않으므로 텍스트와 버튼이 잘리지 않습니다.

레이아웃에 따라 컨테이너를 선택하십시오: 행 또는 열 (VBoxContainer, HBoxContainer), 그리드 (GridContainer with columns), 패딩 (MarginContainer, margin_left, margin_top, margin_right, margin_bottom 테마 상수로 설정), 배경 (PanelContainer, panel 스타일 박스), 긴 콘텐츠 (SIZE_EXPAND_FILL인 자식이 하나 있는 ScrollContainer), 감싸는 항목 (HFlowContainer).

루트에만 앵커 사용

앵커는 컨트롤을 부모의 사각형에 상대적으로 배치하며, 가장 바깥쪽 UI 노드에 사용합니다. 코드에서는 set_anchors_and_offsets_preset()을 사용하십시오. set_anchors_preset()은 앵커만 이동시키고 기존 오프셋은 유지하므로, 코드로 생성된 컨트롤은 크기 (0, 0)으로 유지됩니다.

프리셋: PRESET_FULL_RECT, PRESET_TOP_LEFT, PRESET_TOP_RIGHT, PRESET_BOTTOM_LEFT, PRESET_BOTTOM_RIGHT, PRESET_CENTER, PRESET_TOP_WIDE, PRESET_BOTTOM_WIDE, PRESET_LEFT_WIDE, PRESET_RIGHT_WIDE, PRESET_HCENTER_WIDE, PRESET_VCENTER_WIDE, 그리고 PRESET_CENTER_TOP과 같은 중앙-가장자리 프리셋이 있습니다.

CanvasLayer의 HUD

Node2D 아래의 Control은 월드 공간에 그려지며 Camera2D와 함께 움직입니다. HUD를 CanvasLayer 아래에 두면 화면에 고정됩니다; layer는 여러 캔버스 레이어의 순서를 지정합니다 (높을수록 위에 그려짐).

extends CanvasLayer

var score_label: Label


func _ready() -> void:
	var margin := MarginContainer.new()
	margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
	for side in ["margin_left", "margin_top", "margin_right", "margin_bottom"]:
		margin.add_theme_constant_override(side, 16)
	add_child(margin)

	var column := VBoxContainer.new()
	margin.add_child(column)

	var top_bar := HBoxContainer.new()
	column.add_child(top_bar)

	score_label = Label.new()
	score_label.text = "Score: 0"
	score_label.add_theme_font_size_override("font_size", 24)
	score_label.add_theme_color_override("font_color", Color.GOLD)
	top_bar.add_child(score_label)

	var spacer := Control.new()
	spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE
	top_bar.add_child(spacer)

	var pause_button := Button.new()
	pause_button.text = "Pause"
	pause_button.custom_minimum_size = Vector2(96, 40)
	top_bar.add_child(pause_button)


func set_score(value: int) -> void:
	score_label.text = "Score: %d" % value

에디터에서 빌드된 동일한 트리는: CanvasLayer > MarginContainer (Layout: Full Rect) > VBoxContainer > HBoxContainer > Label, Control (Expand), Button 입니다.

잘리지 않는 텍스트

  • autowrap_mode가 설정된 Label은 어딘가에서 너비를 가져와야 합니다. 기본 플래그를 가진 HBoxContainer 내부에서는 너비가 1픽셀로 줄어들고 매우 높아집니다. SIZE_EXPAND_FILL 또는 custom_minimum_size.x를 지정하십시오.
  • 고정된 공간의 한 줄 텍스트의 경우 text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS (또는 clip_text = true)를 설정하십시오.
  • 컨트롤을 scale하는 것보다 add_theme_font_size_override("font_size", n)을 선호하십시오: scale은 컨테이너가 예약하는 크기를 변경하지 않습니다.
extends VBoxContainer


func add_message(text: String) -> void:
	var label := Label.new()
	label.text = text
	label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	add_child(label)


func add_title(text: String) -> void:
	var label := Label.new()
	label.text = text
	label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
	label.custom_minimum_size = Vector2(0, 32)
	add_child(label)

게임에 도달하지 않는 클릭

mouse_filter는 컨트롤이 마우스 입력을 소비할지 여부를 결정합니다. 기본값은 다릅니다: 일반 Control, ColorRect, Panel은 MOUSE_FILTER_STOP, 컨테이너는 MOUSE_FILTER_PASS, Label은 MOUSE_FILTER_IGNORE를 사용합니다. STOP 상태의 전체 화면 Control 또는 ColorRect는 모든 클릭을 삼키므로 게임의 _unhandled_input()은 이를 볼 수 없습니다. 오버레이, 스페이서 및 장식용 사각형에는 mouse_filter = Control.MOUSE_FILTER_IGNORE를 설정하십시오.

테마 오버라이드 (Godot 4 이름)

Godot 3Godot 4
add_color_override("font_color", c)add_theme_color_override("font_color", c)
add_font_override("font", f)add_theme_font_override("font", f)
(글꼴 크기는 DynamicFont에 있음)add_theme_font_size_override("font_size", 24)
add_stylebox_override("normal", sb)add_theme_stylebox_override("normal", sb)
add_constant_override("separation", 8)add_theme_constant_override("separation", 8)
add_icon_override("icon", tex)add_theme_icon_override("icon", tex)
.tscn 파일의 custom_colors/font_colortheme_override_colors/font_color

일치하는 remove_theme_*_override(name)을 사용하여 오버라이드를 제거하십시오. 일관된 모양을 위해 각 노드를 개별적으로 오버라이드하는 대신 루트 컨트롤에 하나의 Theme 리소스를 할당하십시오. 자식이 이를 상속합니다.

해상도 및 스트레치

Project Settings > Display > Window에서 설정하십시오 (project.godot에 저장됨):

  • display/window/size/viewport_width 및 viewport_height: 디자인하는 기본 해상도 (기본값 1152 x 648).
  • display/window/stretch/mode: 대부분의 게임은 canvas_items (UI와 2D가 부드럽게 크기 조정됨), 픽셀 아트는 viewport, 도구는 disabled. Godot 3의 2d 모드는 Godot 4에서 canvas_items입니다. 이 설정의 기본값은 disabled이며, Godot 4.7 이상에서 생성된 프로젝트는 canvas_items로 시작합니다.
  • display/window/stretch/aspect: expand는 앵커된 UI가 더 넓거나 높은 화면에서 여분의 공간을 사용할 수 있게 합니다; keep는 검은색 막대를 추가합니다. 기본값은 keep이며, Godot 4.7 이상에서 생성된 프로젝트는 expand로 시작합니다.
  • display/window/stretch/scale_mode: 선명한 픽셀 아트를 위해 integer.

런타임에 동일한 설정이 창에 있습니다: get_window().content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS 및 get_window().content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND.

UI가 잘리거나 잘못 배치된 경우 체크리스트

  1. 컨트롤이 수동으로 설정된 position 또는 size를 가진 컨테이너 자식입니까? 크기 플래그와 custom_minimum_size를 사용하십시오.
  2. 루트가 set_anchors_preset()만으로 앵커링되었습니까? set_anchors_and_offsets_preset()을 사용하십시오.
  3. 줄바꿈하는 Label에 너비가 있습니까?
  4. HUD가 Node2D가 아닌 CanvasLayer 아래에 있습니까?
  5. 창 크기가 변경되는 동안 display/window/stretch/mode가 여전히 disabled입니까?
  6. MOUSE_FILTER_STOP이 설정된 보이지 않는 전체 화면 컨트롤이 위에 있습니까?

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ziva-sh/godot-4-api-pitfalls

Fixes Godot 3 APIs and GDScript syntax that AI assistants write into Godot 4 projects, such as KinematicBody2D, move_and_slide(velocity), export, onready, setget, yield, string connect(), instance(), rand_range, the Tween node, File, change_scene, Spatial, rect_* properties, Pool*Array, OS time functions and the old TileMap API. Use when writing, reviewing or porting GDScript for Godot 4.x, when a script fails with "not declared", "not found in base", "was removed in Godot 4" or "is not present

ziva-sh/godot-scene-organization

Structures Godot 4 projects so scenes stay reusable and references do not break - when to make a scene, a script or a Resource, instancing with @export PackedScene, preload and load, @onready and %UniqueName node access, _ready order, groups, autoloads, class_name, and resource UIDs with the .uid files added in Godot 4.4, including how to move or rename files safely. Use when creating new scenes or scripts, deciding how nodes find each other, adding global state or an event bus, moving or renami

ziva-sh/godot-signals

Godot 4 signal patterns and their failure modes - declaring typed signals, emit(), connect() and disconnect() with Callables, bind() and unbind(), lambdas, CONNECT_ONE_SHOT and CONNECT_DEFERRED, await on signals and timers, editor-made connections stored in .tscn files, and the call down, signal up rule. Use when wiring UI buttons, timers, Area2D or body events and custom game events, when replacing Godot 3 connect("signal", self, "method") or yield code, or when debugging "already connected", "

ziva-sh/godot-tilemaplayer

Correct Godot 4.3+ TileMapLayer code - set_cell(coords, source_id, atlas_coords), reading cells and custom data, erasing, coordinate conversion, terrains, tile collision through TileSet physics layers, finding the tile a body hit, and migrating from the deprecated TileMap node and its layer-index API. Use when placing, reading or erasing tiles from GDScript, building a TileSet in code, generating levels procedurally, handling tile collisions, or porting TileMap code from Godot 3 or Godot 4.0 to

관련 스킬