mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-23 03:04:29 +08:00
- 添加简体中文本地化配置和导航链接 - 配置本地搜索功能并设置中文翻译 - 添加 Catch-all 404 重定向中间件 - 重构侧边栏和导航结构以支持国际化 - 移除旧的英文文档内容并更新配置 - 添加页脚导航和面包屑文字本地化
21 KiB
21 KiB
GFramework.Godot API 参考
GFramework.Godot 模块的完整 API 参考文档,包含 Godot 特定扩展和集成的详细说明。
📋 目录
架构集成
AbstractArchitecture
Godot 特定的架构基类,继承自 Core.Architecture。
新增方法
// Godot 模块安装
protected void InstallGodotModule(IGodotModule module);
protected void InstallGodotModule<T>() where T : IGodotModule, new();
使用示例
public class GameArchitecture : AbstractArchitecture
{
protected override void Init()
{
RegisterModel(new PlayerModel());
RegisterSystem(new CombatSystem());
RegisterUtility(new StorageUtility());
}
protected override void InstallModules()
{
InstallGodotModule(new AudioModule());
InstallGodotModule(new InputModule());
}
}
IGodotModule
Godot 模块接口,继承自 IArchitectureModule。
属性
Node Node { get; }
方法
void Install(IArchitecture architecture);
void OnAttach(Architecture architecture);
void OnDetach(Architecture architecture);
void OnPhase(ArchitecturePhase phase, IArchitecture architecture);
使用示例
public class AudioModule : AbstractGodotModule
{
// 模块节点本身
public override Node Node => this;
private AudioStreamPlayer _musicPlayer;
public override void Install(IArchitecture architecture)
{
// 注册音频系统
architecture.RegisterSystem(new AudioSystem());
architecture.RegisterUtility(new AudioUtility());
}
public override void OnAttach(Architecture architecture)
{
// 创建音频播放器
_musicPlayer = new AudioStreamPlayer();
AddChild(_musicPlayer);
Logger.Info("Audio module attached");
}
public override void OnDetach(Architecture architecture)
{
// 清理音频播放器
_musicPlayer?.QueueFree();
Logger.Info("Audio module detached");
}
public override void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
{
switch (phase)
{
case ArchitecturePhase.Ready:
PlayBackgroundMusic();
break;
}
}
private void PlayBackgroundMusic()
{
var music = GD.Load<AudioStream>("res://audio/background.ogg");
_musicPlayer.Stream = music;
_musicPlayer.Play();
}
}
AbstractGodotModule
Godot 模块抽象基类,实现了 IGodotModule 接口。
使用示例
[ContextAware]
[Log]
public partial class SaveModule : AbstractGodotModule
{
private Timer _autoSaveTimer;
public override void Install(IArchitecture architecture)
{
architecture.RegisterSystem(new SaveSystem());
architecture.RegisterUtility(new SaveUtility());
}
public override void OnAttach(Architecture architecture)
{
// 创建自动保存计时器
_autoSaveTimer = new Timer();
_autoSaveTimer.WaitTime = 300; // 5分钟
_autoSaveTimer.Timeout += OnAutoSave;
AddChild(_autoSaveTimer);
_autoSaveTimer.Start();
Logger.Info("Save module attached with auto-save enabled");
}
private void OnAutoSave()
{
var saveSystem = Context.GetSystem<SaveSystem>();
saveSystem.SaveGame("autosave");
Logger.Debug("Auto-save completed");
}
}
Node 扩展方法
安全节点获取
GetNodeX()
安全获取子节点,自动类型转换和 null 检查。
public static T GetNodeX<T>(this Node node, string path) where T : class;
使用示例
// 安全获取节点
var player = GetNodeX<Player>("Player");
var healthBar = GetNodeX<ProgressBar>("UI/HealthBar");
// 如果节点不存在或类型不匹配,会抛出异常
// 使用时不需要额外的 null 检查
GetChildX()
安全查找子节点,支持递归查找。
public static T GetChildX<T>(this Node node, string path) where T : class;
使用示例
// 递归查找子节点
var player = FindChildX<Player>("Player");
var sprite = FindChildX<Sprite2D>("Enemy/Sprite");
节点验证
IsValidNode()
检查节点是否有效且在场景树中。
public static bool IsValidNode(this Node node);
IsInvalidNode()
检查节点是否无效或不在场景树中。
public static bool IsInvalidNode(this Node node);
使用示例
Node someNode = GetNode("SomeNode");
if (IsValidNode(someNode))
{
someNode.DoSomething();
}
if (IsInvalidNode(someNode))
{
// 节点无效,需要重新获取
}
安全节点操作
AddChildX()
安全添加子节点,包含验证。
public static void AddChildX(this Node parent, Node child, bool forceReadableName = false, InternalMode internalMode = 0);
QueueFreeX()
安全销毁节点,包含验证。
public static void QueueFreeX(this Node node);
FreeX()
立即销毁节点,谨慎使用。
public static void FreeX(this Node node);
使用示例
// 创建并添加子节点
var bullet = bulletScene.Instantiate<Bullet>();
AddChildX(bullet);
// 安全销毁节点
bullet.QueueFreeX();
// 立即销毁(谨慎使用)
tempNode.FreeX();
异步节点操作
WaitUntilReady()
等待节点准备就绪。
public static async Task WaitUntilReady(this Node node);
WaitUntil()
等待条件满足。
public static async Task WaitUntil(this Node node, Func<bool> condition);
WaitUntilTimeout()
等待指定时间或条件满足。
public static async Task WaitUntilTimeout(this Node node, float timeoutSeconds);
使用示例
// 等待节点准备就绪
await this.WaitUntilReady();
// 等待条件满足
await this.WaitUntil(() => SomeCondition());
// 等待 2 秒
await this.WaitUntilTimeout(2.0f);
场景树操作
GetParentX()
安全获取父节点。
public static T GetParentX<T>(this Node node) where T : class;
ForEachChild()
遍历所有子节点。
public static void ForEachChild<T>(this Node node, Action<T> action) where T : Node;
使用示例
// 获取父节点
var parent = GetParentX<GameLevel>();
// 遍历所有子节点
this.ForEachChild<Node>(child => {
if (child is Sprite2D sprite)
{
ProcessSprite(sprite);
}
});
信号系统
SignalBuilder
信号构建器,提供流畅的信号连接 API。
构造函数
public SignalBuilder(Node node);
连接方法
public SignalBuilder Connect(Callable callable);
public SignalBuilder Connect<T1>(Callable<T1> callable);
public SignalBuilder Connect<T1, T2>(Callable<T1, T2> callable);
public SignalBuilder Connect<T1, T2, T3>(Callable<T1, T2, T3> callable);
public SignalBuilder Connect<T1, T2, T3, T4>(Callable<T1, T2, T3, T4> callable);
配置方法
public SignalBuilder WithFlags(ConnectFlags flags);
public SignalBuilder CallImmediately();
生命周期方法
public SignalBuilder UnRegisterWhenNodeExitTree(Node node);
public SignalBuilder AddToUnregisterList(IUnRegisterList unregisterList);
使用示例
// 基础连接
this.CreateSignalBuilder(Button.SignalName.Pressed)
.Connect(OnButtonPressed)
.UnRegisterWhenNodeExitTree(this);
// 带标志的连接
this.CreateSignalBuilder(Timer.SignalName.Timeout)
.WithFlags(ConnectFlags.OneShot)
.Connect(OnTimerTimeout);
// 立即调用连接
this.CreateSignalBuilder(CustomSignal.SignalName.CustomEvent)
.CallImmediately()
.Connect(OnCustomEvent);
// 多参数连接
this.CreateSignalBuilder()
.AddSignal(SignalName.Parameter1, OnParameter1)
.AddSignal(SignalName.Parameter2, OnParameter2)
.AddSignal(SignalName.Parameter3, OnParameter3)
.UnRegisterWhenNodeExitTree(this);
SignalExtension
信号扩展方法,简化信号创建。
CreateSignalBuilder()
创建信号构建器。
public static SignalBuilder CreateSignalBuilder(this Node node, string signalName);
ConnectSignal()
直接连接信号。
public static IUnRegister ConnectSignal(this Node node, string signalName, Callable callable);
public static IUnRegister ConnectSignal<T1>(this Node node, string signalName, Callable<T1> callable);
使用示例
// 创建信号构建器连接
this.CreateSignalBuilder(Button.SignalName.Pressed)
.Connect(OnButtonPressed);
// 直接连接信号
this.ConnectSignal(Button.SignalName.Pressed, Callable.From(OnButtonPressed));
// 多参数信号连接
this.ConnectSignal(ComplexSignal.SignalName.DataChanged,
Callable.From(OnDataChanged));
信号与框架事件桥接
SignalEventBridge
信号事件桥接器,将 Godot 信号转换为框架事件。
使用示例
[ContextAware]
[Log]
public partial class GameController : Node, IController
{
public override void _Ready()
{
// Godot 信号 -> 框架事件
this.CreateSignalBuilder(Button.SignalName.Pressed)
.Connect(() => {
Context.SendEvent(new ButtonClickEvent { ButtonId = "start" });
})
.UnRegisterWhenNodeExitTree(this);
// 框架事件 -> Godot 信号
this.RegisterEvent<PlayerHealthChangeEvent>(OnPlayerHealthChange)
.UnRegisterWhenNodeExitTree(this);
}
private void OnPlayerHealthChange(PlayerHealthChangeEvent e)
{
// 更新 Godot UI
var healthBar = GetNode<ProgressBar>("UI/HealthBar");
healthBar.Value = (float)e.NewHealth / e.MaxHealth * 100;
// 发送 Godot 信号
EmitSignal(SignalName.HealthUpdated, e.NewHealth, e.MaxHealth);
}
[Signal]
public delegate void HealthUpdatedEventHandler(int newHealth, int maxHealth);
}
节点池化
AbstractNodePoolSystem<TKey, TNode>
节点池化系统基类,TNode 必须是 Node。
抽象方法
protected abstract TNode CreateItem(TKey key);
protected abstract void OnSpawn(TNode item, TKey key);
protected abstract void OnDespawn(TNode item);
protected abstract bool CanDespawn(TNode item);
公共方法
public TNode Spawn(TKey key);
public void Despawn(TNode item);
public void DespawnAll();
public int GetActiveCount(TKey key);
public int GetTotalCount(TKey key);
使用示例
public class BulletPoolSystem : AbstractNodePoolSystem<string, Bullet>
{
private readonly Dictionary<string, PackedScene> _scenes = new();
public BulletPoolSystem()
{
_scenes["player"] = GD.Load<PackedScene>("res://scenes/PlayerBullet.tscn");
_scenes["enemy"] = GD.Load<PackedScene>("res://scenes/EnemyBullet.tscn");
}
protected override Bullet CreateItem(string key)
{
if (_scenes.TryGetValue(key, out var scene))
{
return scene.Instantiate<Bullet>();
}
throw new ArgumentException($"Unknown bullet type: {key}");
}
protected override void OnSpawn(Bullet item, string key)
{
item.Reset();
item.Position = Vector2.Zero;
item.Visible = true;
item.SetCollisionLayerValue(1, true);
item.SetCollisionMaskValue(1, true);
}
protected override void OnDespawn(Bullet item)
{
item.Visible = false;
item.SetCollisionLayerValue(1, false);
item.SetCollisionMaskValue(1, false);
// 移除父节点
item.GetParent()?.RemoveChild(item);
}
protected override bool CanDespawn(Bullet item)
{
return !item.IsActive && item.GetParent() != null;
}
}
// 使用示例
var bulletPool = new BulletPoolSystem();
// 从池中获取子弹
var bullet = bulletPool.Spawn("player");
AddChild(bullet);
// 回收子弹
bulletPool.Despawn(bullet);
IPoolableNode
可池化节点接口。
public interface IPoolableNode
{
void Reset();
void SetActive(bool active);
bool IsActive { get; }
}
使用示例
public partial class Bullet : Area2D, IPoolableNode
{
[Export] public float Speed { get; set; } = 500.0f;
[Export] public float Damage { get; set; } = 10.0f;
private bool _isActive;
public bool IsActive => _isActive;
public void Reset()
{
Position = Vector2.Zero;
Rotation = 0;
Velocity = Vector2.Zero;
_isActive = false;
}
public void SetActive(bool active)
{
_isActive = active;
Visible = active;
SetProcess(active);
}
public override void _Ready()
{
BodyEntered += OnBodyEntered;
}
private void OnBodyEntered(Node body)
{
if (body is Enemy enemy && _isActive)
{
enemy.TakeDamage(Damage);
// 子弹命中敌人,回收到池中
var bulletPool = GetNode<BulletPoolSystem>("/root/BulletPool");
bulletPool?.Despawn(this);
}
}
public override void _Process(double delta)
{
if (!_isActive) return;
Position += Transform.X * (float)(Speed * delta);
}
}
资源管理
ResourceLoadUtility
资源加载工具类,简化和缓存 Godot 资源加载。
构造函数
public ResourceLoadUtility();
方法
public T LoadResource<T>(string path) where T : Resource;
public async Task<T> LoadResourceAsync<T>(string path) where T : Resource;
public void PreloadResource<T>(string path) where T : Resource;
public bool HasResource<T>(string path) where T : Resource;
使用示例
var resourceLoader = new ResourceLoadUtility();
// 同步加载资源
var playerTexture = resourceLoader.LoadResource<Texture2D>("res://textures/player.png");
var playerScene = resourceLoader.LoadResource<PackedScene>("res://scenes/Player.tscn");
// 异步加载资源
var musicStream = await resourceLoader.LoadResourceAsync<AudioStream>("res://audio/background.ogg");
// 预加载资源
resourceLoader.PreloadResource<Texture2D>("res://textures/enemy.png");
resourceLoader.PreloadResource<PackedScene>("res://scenes/enemy.tscn");
AbstractResourceFactoryUtility
抽象资源工厂工具基类。
抽象方法
protected abstract void RegisterFactories();
protected abstract T CreateFactory<T>(string path, Dictionary<string, object> metadata = null) where T : class;
使用示例
public class GameResourceFactory : AbstractResourceFactoryUtility
{
protected override void RegisterFactories()
{
RegisterFactory<PlayerData>("res://data/players/{id}.json");
RegisterFactory<WeaponConfig>("res://data/weapons/{id}.json");
RegisterFactory<LevelConfig>("res://data/levels/{id}.json");
}
public PlayerData CreatePlayer(string playerId)
{
return CreateFactory<PlayerData>($"res://data/players/{playerId}.json");
}
public WeaponConfig CreateWeapon(string weaponId)
{
var metadata = new Dictionary<string, object>
{
["weaponId"] = weaponId,
["loadTime"] = DateTime.Now
};
return CreateFactory<WeaponConfig>($"res://data/weapons/{weaponId}.json", metadata);
}
}
日志系统
GodotLogger
Godot 特定的日志实现。
构造函数
public GodotLogger(string categoryName);
public GodotLogger(string categoryName, LogLevel minLevel);
方法
public void Log<T>(LogLevel level, T message, params object[] args);
public void Debug<T>(T message, params object[] args);
public void Info<T>(T message, params object[] args);
public void Warning<T>(T message, params object[] args);
public void Error<T>(T message, params object[] args);
public void Error<T>(Exception exception, T message, params object[] args);
使用示例
// 创建日志器
var logger = new GodotLogger("GameController");
// 不同级别的日志
logger.Debug("Player position: {0}", player.Position);
logger.Info("Game started");
logger.Warning("Low health: {0}", player.Health);
logger.Error("Failed to load resource: {0}", resourcePath);
// 带异常的错误日志
logger.Error(exception, "An error occurred while processing player input");
GodotLoggerFactory
Godot 日志工厂。
方法
public ILogger CreateLogger(string categoryName);
public ILogger CreateLogger(Type type);
使用示例
var factory = new GodotLoggerFactory();
// 创建日志器
var gameLogger = factory.CreateLogger("GameController");
var playerLogger = factory.CreateLogger(typeof(PlayerController));
// 在架构中使用
public class GameArchitecture : AbstractArchitecture
{
protected override void Init()
{
LoggerProperties = new LoggerProperties
{
LoggerFactoryProvider = new GodotLoggerFactoryProvider(),
MinLevel = LogLevel.Info
};
RegisterSystem(new GameController());
}
}
池化管理
AbstractObjectPool
通用对象池基类。
构造函数
public AbstractObjectPool(
Func<T> createFunc,
Action<T> actionOnGet = null,
Action<T> actionOnRelease = null,
bool collectionCheck = false
);
方法
public T Get();
public void Release(T item);
public void Clear();
public int CountInactive { get; }
public int CountAll { get; }
使用示例
// 创建对象池
var explosionPool = new AbstractObjectPool<ExplosionEffect>(
createFunc: () => new ExplosionEffect(),
actionOnGet: effect => effect.Reset(),
actionOnRelease: effect => Cleanup()
);
// 使用对象池
var effect = explosionPool.Get();
effect.Play(effect.Position);
// 回收对象
explosionPool.Release(effect);
音频系统
AudioSystem
音频系统,管理音乐和音效播放。
使用示例
[ContextAware]
[Log]
public partial class AudioSystem : AbstractSystem
{
private AudioStreamPlayer _musicPlayer;
private readonly Dictionary<string, AudioStream> _soundCache = new();
protected override void OnInit()
{
InitializeAudioPlayers();
CacheSounds();
// 监听音频事件
this.RegisterEvent<PlaySoundEvent>(OnPlaySound);
this.RegisterEvent<PlayMusicEvent>(OnPlayMusic);
this.RegisterEvent<StopMusicEvent>(OnStopMusic);
this.RegisterEvent<SetVolumeEvent>(OnSetVolume);
}
private void InitializeAudioPlayers()
{
_musicPlayer = new AudioStreamPlayer();
AddChild(_musicPlayer);
// 配置音乐播放器
_musicPlayer.Bus = "Music";
}
private void CacheSounds()
{
var soundPaths = new[]
{
"res://audio/jump.wav",
"res://audio/attack.wav",
"res://audio/hurt.wav",
"res://audio/victory.wav"
};
foreach (var path in soundPaths)
{
var sound = GD.Load<AudioStream>(path);
var soundName = Path.GetFileNameWithoutExtension(path);
_soundCache[soundName] = sound;
}
}
private void OnPlaySound(PlaySoundEvent e)
{
if (_soundCache.TryGetValue(e.SoundName, out var sound))
{
PlaySound(sound);
}
else
{
Logger.Warning($"Sound not found: {e.SoundName}");
}
}
private void PlayMusic(PlayMusicEvent e)
{
var music = GD.Load<AudioStream>(e.MusicPath);
_musicPlayer.Stream = music;
_musicPlayer.Play();
Logger.Info($"Playing music: {e.MusicPath}");
}
private void OnStopMusic(StopMusicEvent e)
{
_musicPlayer.Stop();
Logger.Info("Music stopped");
}
private void OnSetVolume(SetVolumeEvent e)
{
AudioServer.SetBusVolume(e.BusName, e.Volume);
Logger.Info($"Set volume for bus {e.BusName}: {e.Volume}");
}
private void PlaySound(AudioStream sound)
{
var player = new AudioStreamPlayer();
player.Stream = sound;
player.Bus = "SFX";
player.Play();
// 自动清理播放器
this.CreateSignalBuilder(player.SignalName.Finished)
.WithFlags(ConnectFlags.OneShot)
.Connect(() => player.QueueFree())
.UnRegisterWhenNodeExitTree(this);
}
}
// 音频事件
public struct PlaySoundEvent { public string SoundName; }
public struct PlayMusicEvent { public string MusicPath; }
public struct StopMusicEvent { }
public struct SetVolumeEvent { public string BusName; public float Volume; }
文档版本: 1.0.0
更新日期: 2026-01-12