制作插件
下文僅針對2.1版本。
關於插件
插件是為編輯器擴展出更多有用工具的重要方式。它可以完全用GDScript和標准場景開發,甚至都不需重新加載編輯器就可生效。不像模塊,你無需創建C++代碼、也無需重新編譯整個引擎。這使得插件可能不夠強大,但仍能用之完成很多事情。注:插件與你已經制作的任何場景沒有不同,除了它是通過腳本添加功能。
該手冊將會通過兩個簡單插件的創建來讓你理解其工作原理並自行開發。首先,在項目中添加一個自定義節點到任意場景,然后就會有一個自定義Dock添加到編輯中。
創建插件
開始前,先新建一個空項目,用於開發和 測試插件。
項目目錄下,有存放插件的標准目錄addons/plugin_name
,所以,在addons`目錄中創建一個叫
my_custom_node``的目錄,目錄結構類似於:
創建plugin.cfg
文件,Godot還不能打開這種文件所以必須在外部編輯器中編輯其內容:
[plugin]
name="My Custom Node"
description="A custom node made to extend the Godot Engine."
author="Your Name Here"
version="1.0"
script="custom_node.gd"
這是有關你這個插件的元數據,需要設置名稱和描述以便用戶理解其作用。當插件激活時,會加載你指定的主腳本文件。指定版本號后,用戶可以去判定是否是一個過期版本(關於語義化版本規范可以參看:http://semver.org/lang/zh-CN/)。
腳本文件
打開腳本編輯器(F3)並創建一個在 my_custom_node
目錄下的名為custom_node.gd
的GDScript文件。該腳本有兩點特殊要求:它必須是 tool
腳本;必須繼承自EditorPlugin
類。
有項很重要的工作是初始化並清空資源。一種好的實踐方式是用虛擬函數_enter_tree() <class_Node__enter_tree>
來初始化插件以及用_exit_tree() <class_Node__exit_tree>
來清空它。你可以刪除默認的GDScript模板內容並用以下代碼結構替換:
tool
extends EditorPlugin
func _enter_tree():
# Initialization of the plugin goes here
pass
func _exit_tree():
# Clean-up of the plugin goes here
pass
這段模板代碼在開發新插件時一般都可以用到。
自定義節點
有時你想讓多個節點擁有某種特定的行為,可能通過重用自定義場景或控件可實現這種需求;場景實例化在很多情況是有用的,但有時會顯得累贅,尤其被用於多個項目中時。這時好的解決方案是制作一個插件,用於添加帶有自定義行為的節點。
要新建一種節點類型,通過class_EditorPlugin
類的add_custom_type() <class_EditorPlugin_add_custom_type>
函數。該函數能給編輯器添加新的類型,可以是節點或資源。不過在創建類型之前,你需要一個腳本用於承載其邏輯。這種腳本不需要用tool
關鍵詞來修飾,僅僅是讓用戶可以在編輯器中看到它。
我們來創建一個簡單的按鈕,效果是:當其被點擊時,打印一條消息。我們需要一段簡單腳本,繼承自Button
類,也可以繼承自BaseButton
類:
tool
extends Button
func _enter_tree():
connect("pressed", self, "clicked")
func clicked():
print("You clicked me!")
將代碼文件命名為 button.gd
保存到插件目錄。還需要一個16x16的小圖標用來顯示在場景樹中。如果沒有,可以暫時用場景中的默認圖標。
我們來將其添加為自定義類型以便在Create New Node對話框中顯示,修改custom_node.gd
腳本代碼:
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("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")
做完這個操作,在項目設置的插件列表中,這個插件應該就出現了,激活它,並試着添加一個新的節點來看看效果:
添加了節點后,你會看到腳本已經被附着到該節點上。設置按鈕的文本,保存並運行場景。點擊按鈕,應該就能看到控制台中輸出的文本:
自定義Dock
有時你需要通過擴展編輯器來添加已經存在的工具,一種簡單的方式是通過插件添加一個新的Dock。Dock是基於控件的場景,所以沒有新的知識點啦。
創建插件的方式與自定義節點的方式相似,所以在 addons/my_custom_dock
目錄下新建一個plugin.cfg
文件。添加內容:
[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"
Dock的內容其實完全就是標准的Godot場景。
對於編輯器Dock來說,場景的根節點強制為Control
類或其子類。根節點的名稱也將是出現在Dock選項卡上的名稱,所以要剪短精煉,別忘了給按鈕添加一段文本:
將場景保存為 my_dock.tscn
。
選取剛剛創建的場景,以Dock的形式添加到編輯器中 - 依賴EditorPlugin
類的add_control_to_dock()
的函數:
代碼很直觀,選定好Dock的位置。當插件失活時,要記得移除Dock:
tool
extends EditorPlugin
var dock # A class member to hold the dock during the plugin lifecycle
func _enter_tree():
# Initialization of the plugin goes here
# First load the dock scene and instance it:
dock = preload("res://addons/my_custom_dock/my_dock.tscn").instance()
# 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 scene from the docks:
remove_control_from_docks( dock ) # Remove the dock
dock.free() # Erase the control from the memory
用戶可以自由移動Dock的未知,並保存dock的布局位置。
檢驗結果
打開“Project Settings”,點擊“Plugin”選項卡,你的插件應該出現在列表中,如果並未出現,點擊右上角“Update”按鈕:
在“Status”列中,顯示該插件是未激活的,只要點擊狀態並選擇“激活”即可,而Dock也會即時顯示。
更深入的內容
既然你已學習了如何制作簡單的插件,你就可以用很多很好的方式來擴展編輯器。通過GDScript可以給編輯器快速添加很多功能函數,從而創建出所需的特定編輯器,而無需研究C++模塊。
你可以制作插件來助力自己的開發工作,也可以將這些插件分享到Godot的Asset Library以便更多的人受益。