资源加载管理器(C#+GodotAPI)

以Godot的API为例子,Unity可以参考

资源加载器的核心:缓存

带引用计数的多级缓存加+池化

核心原理1:用一个字典存已经加载过的资源

private static Dictionary<string, Resource> _cache = new();
public static T Load<T>(string path) where T : Resource
{
    // 1. 先查字典
    if (_cache.TryGetValue(path, out var cached))
    {
        return cached as T; 
    }
    
    // 2. 字典里没有,才真正加载
    var resource = ResourceLoader.Load<T>(path);
    
    // 3. 存到字典里
    _cache[path] = resource;
    return resource;
}

核心原理2:引用计数

资源加载了,会有一个问题:什么时候去释放资源,通过引用计数看有多少地方在使用这个资源。

private static Dictionary<string, int> _refCounts = new();
public static T Load<T>(string path)
{
    if (_cache.TryGetValue(path, out var cached))
    {
        _refCounts[path]++; // 引用计数+1
        return cached;
    }
    var resource = ResourceLoader.Load<T>(path);
    _cache[path] = resource;
    _refCounts[path] = 1; // 首次加载,引用计数=1
    return resource;
}
public static void Unload(string path)
{
    if (!_refCounts.ContainsKey(path)) return;
    
    _refCounts[path]--; // 引用计数-1
    
    if (_refCounts[path] <= 0)
    {
        // 没人用了,可以删掉了
        _cache.Remove(path);
        _refCounts.Remove(path);
        // 注意:Godot 的 Resource 会被 GC 自动回收
    }
}

核心原理3:场景池化

资源加载好了,还需要实例化Instantiate它,场景池就是为了解决频繁实例化的问题。

场景池的原理:用完不删,下次接着用

private static Dictionary<string, List<Node>> _pools = new();

public static Node GetFromPool(string scenePath)
{
    // 1. 池里有现成的吗?
    if (_pools.TryGetValue(scenePath, out var pool) && pool.Count > 0)
    {
        var instance = pool[0];
        pool.RemoveAt(0);
        instance.Visible = true;
        return instance; // 复用旧的,不创建新的
    }
    
    // 2. 池空了,才创建新的
    var scene = ResourceLoader.Load<PackedScene>(scenePath);
    return scene.Instantiate();
}

public static void ReturnToPool(Node instance)
{
    instance.Visible = false;
    _pools[instance.SceneFilePath].Add(instance); // 藏起来
}

还需要异步加载资源:Godot本身有提供异步加载方法,后续可以在资源管理器里对加载方法进行封装

var loader = ResourceLoader.LoadAsync<Texture2D>("res://4k_bg.png");

 

posted @ 2026-08-18 23:50  apssic  阅读(5)  评论(0)    收藏  举报