Godot C++ GDExtension:实现仅在游戏运行时执行_process/_ready中的打印逻辑
Godot C++ GDExtension:实现仅在游戏运行时执行_process/_ready中的打印逻辑
嗨,我完全懂你的困扰——每次写_ready或者_process都要手动加编辑器环境判断,确实有点繁琐。这里有两个更优雅的解决方案,帮你摆脱重复代码的烦恼:
方案1:封装一个带编辑器判断的通用基类
最一劳永逸的办法是创建一个基类,把is_editor_hint()的判断逻辑封装进去,之后所有自定义节点都继承这个基类,就不用每次重复写判断了。
首先创建基类的头文件EditorSafeNode.h:
#ifndef EDITOR_SAFE_NODE_H #define EDITOR_SAFE_NODE_H #include <godot_cpp/classes/character_body2d.hpp> #include <godot_cpp/classes/engine.hpp> namespace godot { class EditorSafeNode : public CharacterBody2D { GDCLASS(EditorSafeNode, CharacterBody2D); protected: static void _bind_methods() {} // 子类只需要重写这两个方法,代替原来的_ready和_process virtual void _ready_runtime() {} virtual void _process_runtime(double delta) {} public: EditorSafeNode() = default; ~EditorSafeNode() = default; void _ready() override { if (!Engine::get_singleton()->is_editor_hint()) { _ready_runtime(); } } void _process(double delta) override { if (!Engine::get_singleton()->is_editor_hint()) { _process_runtime(delta); } } }; } // namespace godot #endif
接下来修改你的Personnage类,让它继承这个基类,并重写对应的_runtime方法:
Personnage.h修改后:
#ifndef PERSONNAGE_H #define PERSONNAGE_H #include "EditorSafeNode.h" // 引入封装好的基类 namespace godot { class Personnage : public EditorSafeNode { // 替换原来的CharacterBody2D继承 GDCLASS(Personnage, EditorSafeNode); protected: static void _bind_methods() {} // 重写基类的运行时专属方法 void _ready_runtime() override; void _process_runtime(double delta) override; public: Personnage(); ~Personnage(); }; } #endif
Personnage.cpp修改后:
#include "Personnage.h" #include <godot_cpp/core/class_db.hpp> #include <godot_cpp/variant/utility_functions.hpp> using namespace godot; Personnage::Personnage() { UtilityFunctions::print("Bonjour depuis GDExtension avec C++ !"); } Personnage::~Personnage() {} void Personnage::_ready_runtime() { // 代替原来的_ready方法 UtilityFunctions::print("fonction Start()"); } void Personnage::_process_runtime(double delta) { // 代替原来的_process方法 UtilityFunctions::print("fonction Update()"); }
这样以后所有需要避免编辑器执行逻辑的节点,都可以直接继承EditorSafeNode,重写对应的_runtime方法就行,再也不用写重复的判断代码了。
方案2:用宏定义简化判断逻辑
如果你不想重构基类,也可以定义一个宏,把判断逻辑包装起来,写代码时会简洁很多:
你可以把这个宏放在项目的公共头文件里(比如一个Common.h),方便所有文件引用:
#define RUN_IN_RUNTIME(code) if (!Engine::get_singleton()->is_editor_hint()) { code; }
然后在你的方法里直接使用这个宏:
void Personnage::_ready(){ RUN_IN_RUNTIME( UtilityFunctions::print("fonction Start()"); // 这里可以添加其他仅在运行时执行的代码 ) } void Personnage::_process(double delta) { RUN_IN_RUNTIME( UtilityFunctions::print("fonction Update()"); ) }
这个方案不用改变类的继承关系,适合快速简化现有代码的场景。
小补充:为什么编辑器会执行这些方法?
其实这是Godot的正常行为——编辑器在预览节点、刷新场景时,会实例化节点并调用_ready等生命周期方法,所以你的代码会在编辑器环境下被触发。用is_editor_hint()区分环境也是官方推荐的标准做法哦。
备注:内容来源于stack exchange,提问作者Firrow




