Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

플러그인 만들기

플러그인에 대해서

A plugin is a great way to extend the editor with useful tools. It can be made entirely with GDScript and standard scenes, without even reloading the editor. Unlike modules, you don't need to create C++ code nor recompile the engine. While this makes plugins less powerful, there are still many things you can do with them. Note that a plugin is similar to any scene you can already make, except it is created using a script to add editor functionality.

이 튜토리얼에서는 플러그인의 작동 방식을 이해하고, 자신만의 플러그인을 개발하기 위해 두 가지 플러그인을 만드는 과정을 안내합니다. 첫 번째는 프로젝트의 모든 씬에 추가할 수 있는 사용자 정의 노드이고, 다른 하나는 에디터에 추가되는 사용자 정의 독(dock)입니다.

플러그인 생성하기

시작하기 전에 원하는 위치에 빈 프로젝트를 만드세요. 이는 플러그인을 개발하고 테스트하기 위한 기반 역할을 합니다.

가장 먼저, 에디터가 새 플러그인을 인식하기 위해 두 개의 파일이 필요합니다. 구성을 위한 ``plugin.cfg``와 기능이 포함된 툴 스크립트입니다. 플러그인은 프로젝트 폴더 내에 ``addons/plugin_name``형태의 표준 경로를 가지고 있습니다. Godot는 해당 파일을 생성하고 필요한 위치에 배치하기 위한 대화 상자를 제공합니다.

메인 툴바에서 '프로젝트(Project)' 드롭다운을 클릭하세요. 그런 다음 '프로젝트 설정...(Project Settings...)'을 클릭하세요. '플러그인(Plugins)' 탭으로 이동한 다음 오른쪽 상단에 있는 '새 플러그인 만들기(Create New Plugin)' 버튼을 클릭하세요.

다음과 같은 대화 상자가 나타나는 것을 볼 수 있습니다.

../../../_images/making_plugins-create_plugin_dialog.webp

각 필드의 자리 표시자 텍스트는 플러그인의 파일 생성 및 구성 파일 값에 어떤 영향을 미치는지 설명합니다.

예제를 계속하려면, 다음 값을 사용하십시오.

Plugin Name: My Custom Node
Subfolder: my_custom_node
Description: A custom node made to extend the Godot Engine.
Author: Your Name Here
Version: 1.0.0
Language: GDScript
Script Name: custom_node.gd
Activate now: No

경고

다른 모든 C# 스크립트와 마찬가지로 EditorPlugin 스크립트를 컴파일해야 프로젝트를 빌드해야 하기 때문에 C#에서 지금 활성화하시겠습니까? 옵션을 선택 취소해야 합니다. 프로젝트를 빌드한 후 프로젝트 설정``의 ``플러그인 탭에서 플러그인을 활성화할 수 있습니다.

다음과 같은 디렉터리 구조로 끝나야 합니다.

../../../_images/making_plugins-my_custom_mode_folder.webp

``plugin.cfg``는 플러그인에 대한 메타데이터가 포함된 INI 파일입니다. 이름과 설명은 사람들이 그 기능을 이해하는 데 도움이 됩니다. 이름을 남겨두면 작업한 업무에 대해 적절한 인정을 받는 데 도움이 됩니다. 버전 번호는 다른 사람들이 오래된 버전인지 알 수 있도록 도와줍니다. 버전 번호를 찾는 방법을 잘 모르겠으면 `Semantic Versioning <https://semver.org/>`_을 확인하세요. 메인 스크립트 파일은 플러그인이 활성화되면 에디에서 플러그인이 수행하는 작업을 Godot에게 지시니다.

The script file

Upon creation of the plugin, the dialog will automatically open the EditorPlugin script for you. The script has two requirements that you cannot change: it must be a @tool script, or else it will not load properly in the editor, and it must inherit from EditorPlugin.

경고

In addition to the EditorPlugin script, any other GDScript that your plugin uses must also be a tool. Any GDScript without @tool imported into the editor will act like an empty file!

It's important to deal with initialization and clean-up of resources. A good practice is to use the virtual function _enter_tree() to initialize your plugin and _exit_tree() to clean it up. Thankfully, the dialog generates these callbacks for you. Your script should look something like this:

@tool
extends EditorPlugin


func _enter_tree():
    # Initialization of the plugin goes here.
    pass


func _exit_tree():
    # Clean-up of the plugin goes here.
    pass

This is a good template to use when creating new plugins.

A custom node

Sometimes you want a certain behavior in many nodes, such as a custom scene or control that can be reused. Instancing is helpful in a lot of cases, but sometimes it can be cumbersome, especially if you're using it in many projects. A good solution to this is to make a plugin that adds a node with a custom behavior.

경고

Nodes added via an EditorPlugin are "CustomType" nodes. While they work with any scripting language, they have fewer features than the Script Class system. If you are writing GDScript or NativeScript, we recommend using Script Classes instead.

To create a new node type, you can use the function add_custom_type() from the EditorPlugin class. This function can add new types to the editor (nodes or resources). However, before you can create the type, you need a script that will act as the logic for the type. While that script doesn't have to use the @tool annotation, it can be added so the script runs in the editor.

For this tutorial, we'll create a button that prints a message when clicked. For that, we'll need a script that extends from Button. It could also extend BaseButton if you prefer:

@tool
extends Button


func _enter_tree():
    pressed.connect(clicked)


func clicked():
    print("You clicked me!")

That's it for our basic button. You can save this as my_button.gd inside the plugin folder. You'll also need a 16×16 icon to show in the scene tree. If you don't have one, you can grab the default one from the engine and save it in your addons/my_custom_node folder as icon.png, or use the default Godot logo (preload("res://icon.svg")).

SVG images that are used as custom node icons should have the Editor > Scale With Editor Scale and Editor > Convert Icons With Editor Theme import options enabled. This allows icons to follow the editor's scale and theming settings if the icons are designed with the same color palette as Godot's own icons.

../../../_images/making_plugins-custom_node_icon.png

Now, we need to add it as a custom type so it shows on the Create New Node dialog. For that, change the custom_node.gd script to the following:

@tool
extends EditorPlugin


func _enter_tree():
    # Initialization of the plugin goes here.
    # Add the new type with a name, a parent type, a script and an icon.
    add_custom_type("MyButton", "Button", preload("my_button.gd"), preload("icon.png"))


func _exit_tree():
    # Clean-up of the plugin goes here.
    # Always remember to remove it from the engine when deactivated.
    remove_custom_type("MyButton")

With that done, the plugin should already be available in the plugin list in the Project Settings, so activate it as explained in Checking the results.

Then try it out by adding your new node:

../../../_images/making_plugins-custom_node_create.webp

When you add the node, you can see that it already has the script you created attached to it. Set a text to the button, save and run the scene. When you click the button, you can see some text in the console:

../../../_images/making_plugins-custom_node_console.webp

A custom dock

Sometimes, you need to extend the editor and add tools that are always available. An easy way to do it is to add a new dock with a plugin. Docks are just scenes based on Control, so they are created in a way similar to usual GUI scenes.

Creating a custom dock is done just like a custom node. Create a new plugin.cfg file in the addons/my_custom_dock folder, then add the following content to it:

[plugin]

name="My Custom Dock"
description="A custom dock made so I can learn how to make plugins."
author="Your Name Here"
version="1.0"
script="custom_dock.gd"

Then create the script custom_dock.gd in the same folder. Fill it with the template we've seen before to get a good start.

Since we're trying to add a new custom dock, we need to create the contents of the dock. This is nothing more than a standard Godot scene: just create a new scene in the editor then edit it.

For an editor dock, the root node must be a Control or one of its child classes. For this tutorial, you can create a single button. The name of the root node will also be the name that appears on the dock tab, so be sure to give it a short and descriptive name. Also, don't forget to add some text to your button.

../../../_images/making_plugins-my_custom_dock_scene.webp

Save this scene as my_dock.tscn. Now, we need to grab the scene we created then add it as a dock in the editor. For this, you can rely on the function add_control_to_dock() from the EditorPlugin class.

You need to select a dock position and define the control to add (which is the scene you just created). Don't forget to remove the dock when the plugin is deactivated. The script could look like this:

@tool
extends EditorPlugin


# A class member to hold the dock during the plugin life cycle.
var dock


func _enter_tree():
    # Initialization of the plugin goes here.
    # Load the dock scene and instantiate it.
    dock = preload("res://addons/my_custom_dock/my_dock.tscn").instantiate()

    # Add the loaded scene to the docks.
    add_control_to_dock(DOCK_SLOT_LEFT_UL, dock)
    # Note that LEFT_UL means the left of the editor, upper-left dock.


func _exit_tree():
    # Clean-up of the plugin goes here.
    # Remove the dock.
    remove_control_from_docks(dock)
    # Erase the control from the memory.
    dock.free()

Note that, while the dock will initially appear at its specified position, the user can freely change its position and save the resulting layout.

Checking the results

It's now time to check the results of your work. Open the Project Settings and click on the Plugins tab. Your plugin should be the only one on the list.

../../../_images/making_plugins-project_settings.webp

You can see the plugin is not enabled. Click the Enable checkbox to activate the plugin. The dock should become visible before you even close the settings window. You should now have a custom dock:

../../../_images/making_plugins-custom_dock.webp

Going beyond

Now that you've learned how to make basic plugins, you can extend the editor in several ways. Lots of functionality can be added to the editor with GDScript; it is a powerful way to create specialized editors without having to delve into C++ modules.

You can make your own plugins to help yourself and share them in the Asset Library so that people can benefit from your work.

Registering autoloads/singletons in plugins

It is possible for editor plugins to automatically register autoloads when the plugin is enabled. This also includes unregistering the autoload when the plugin is disabled.

This makes setting up plugins faster for users, as they no longer have to manually add autoloads to their project settings if your editor plugin requires the use of an autoload.

Use the following code to register a singleton from an editor plugin:

@tool
extends EditorPlugin

# Replace this value with a PascalCase autoload name, as per the GDScript style guide.
const AUTOLOAD_NAME = "SomeAutoload"


func _enter_tree():
    # The autoload can be a scene or script file.
    add_autoload_singleton(AUTOLOAD_NAME, "res://addons/my_addon/some_autoload.tscn")


func _exit_tree():
    remove_autoload_singleton(AUTOLOAD_NAME)