Extra2D/Docs/asset_service.md

529 lines
11 KiB
Markdown
Raw Normal View History

# Extra2D 资源服务系统
## 概述
Extra2D 资源服务系统提供了一套完整的资源管理解决方案,包括资源加载、缓存、打包和加密压缩功能。
### 主要特性
- **类型安全**:使用模板和强类型 ID 避免类型错误
- **自动缓存**LRU 缓存策略,自动管理内存
- **异步加载**:后台线程加载,不阻塞主线程
- **资源打包**:支持压缩和加密的资源包格式
- **多格式支持**:纹理、字体、着色器、音频等
## 模块结构
```
extra2d/asset/
├── asset_types.h # 资源类型定义
├── asset.h # 资源基类
├── asset_handle.h # 资源句柄
├── asset_cache.h # 资源缓存
├── asset_loader.h # 资源加载器
├── asset_pack.h # 资源包
├── data_processor.h # 数据处理器
└── asset_service.h # 资源服务
```
## 快速开始
### 1. 初始化资源服务
```cpp
#include <extra2d/extra2d.h>
using namespace extra2d;
// 创建资源服务
AssetService service;
service.init();
service.setRoot("assets");
// 注册加载器
service.registerLoader<TextureAsset>(AssetLoaderFactory::createTextureLoader());
service.registerLoader<FontAsset>(AssetLoaderFactory::createFontLoader());
service.registerLoader<ShaderAsset>(AssetLoaderFactory::createShaderLoader());
```
### 2. 同步加载资源
```cpp
// 加载纹理
AssetHandle<TextureAsset> texture = service.load<TextureAsset>("sprites/player.png");
if (texture.valid()) {
int width = texture->width();
int height = texture->height();
const u8* data = texture->data();
}
```
### 3. 异步加载资源
```cpp
// 异步加载
service.loadAsync<TextureAsset>("sprites/background.png",
[](AssetHandle<TextureAsset> handle) {
if (handle.valid()) {
// 资源加载完成,在主线程处理
}
});
// 在主线程处理回调
service.process();
```
### 4. 使用资源包
```cpp
// 挂载资源包
service.mount("data.pak");
// 从资源包加载
auto texture = service.load<TextureAsset>("textures/hero.png");
// 卸载资源包
service.unmount("data.pak");
```
### 5. 缓存管理
```cpp
// 设置缓存上限 (100MB)
service.setLimit(100 * 1024 * 1024);
// 获取缓存统计
CacheStats stats = service.stats();
std::cout << "缓存使用: " << stats.bytes << " 字节\n";
std::cout << "命中率: " << (stats.hitRate() * 100) << "%\n";
// 清理无引用资源
service.purge();
// 清空缓存
service.clear();
```
## API 参考
### AssetID
资源标识符,使用哈希值进行快速比较。
```cpp
struct AssetID {
u64 hash; // 哈希值
std::string path; // 原始路径
explicit AssetID(const std::string& path);
bool valid() const;
bool operator==(const AssetID& other) const;
};
```
### AssetHandle<T>
类型安全的资源句柄,使用弱引用避免阻止资源回收。
```cpp
template<typename T>
class AssetHandle {
public:
bool valid() const; // 检查是否有效
Ref<T> get() const; // 获取强引用
T* operator->() const; // 解引用
bool loaded() const; // 检查是否已加载
AssetState state() const; // 获取状态
};
```
### AssetCache
LRU 缓存管理器。
```cpp
class AssetCache {
public:
explicit AssetCache(size_t limit = 0);
template<typename T>
AssetHandle<T> add(Ref<T> asset);
template<typename T>
AssetHandle<T> get(const AssetID& id);
bool has(const AssetID& id) const;
bool remove(const AssetID& id);
void setLimit(size_t limit);
size_t bytes() const;
size_t count() const;
size_t purge(); // 清理无引用资源
void clear(); // 清空缓存
CacheStats stats() const;
};
```
### IAssetService
资源服务接口。
```cpp
class IAssetService : public IService {
public:
// 同步加载
template<typename T>
AssetHandle<T> load(const std::string& path);
// 异步加载
template<typename T>
void loadAsync(const std::string& path, AssetLoadCallback<T> callback);
// 获取已缓存资源
template<typename T>
AssetHandle<T> get(const std::string& path);
// 预加载
template<typename T>
void preload(const std::string& path);
// 状态查询
bool isLoaded(const std::string& path) const;
bool isLoading(const std::string& path) const;
// 资源管理
void unload(const std::string& path);
void setLimit(size_t maxBytes);
size_t size() const;
void purge();
void clear();
CacheStats stats() const;
// 加载器注册
template<typename T>
void registerLoader(Unique<AssetLoader<T>> loader);
// 资源包管理
bool mount(const std::string& path);
void unmount(const std::string& path);
// 数据处理管道
void setPipe(DataPipe pipe);
// 根目录
void setRoot(const std::string& path);
std::string root() const;
// 处理异步回调
void process();
};
```
### DataPipe
数据处理管道,支持链式调用。
```cpp
class DataPipe {
public:
DataPipe& decrypt(const std::string& key, Decryptor::Type type = Decryptor::Type::XOR);
DataPipe& decompress(Compression algo);
DataPipe& encrypt(const std::string& key, Decryptor::Type type = Decryptor::Type::XOR);
DataPipe& compress(Compression algo, int level = 3);
DataPipe& add(Unique<DataProcessor> processor);
std::vector<u8> process(const std::vector<u8>& input);
void clear();
bool empty() const;
size_t size() const;
};
```
### AssetPackBuilder
资源包构建器。
```cpp
class AssetPackBuilder {
public:
explicit AssetPackBuilder(Compression compression = Compression::None, int level = 3);
void add(const std::string& path, const std::vector<u8>& data);
void add(const std::string& path, std::vector<u8>&& data);
bool addFile(const std::string& filePath, const std::string& packPath = "");
size_t addDirectory(const std::string& dirPath, const std::string& prefix = "");
void setEncryption(const std::string& key, Decryptor::Type type = Decryptor::Type::XOR);
bool build(const std::string& outputPath);
void clear();
size_t count() const;
size_t totalOriginalSize() const;
size_t totalCompressedSize() const;
};
```
## 资源类型
### TextureAsset
纹理资源,使用 stb_image 加载。
```cpp
class TextureAsset : public Asset {
public:
AssetType type() const override { return AssetType::Texture; }
int width() const;
int height() const;
int channels() const;
const u8* data() const;
size_t dataSize() const;
};
```
### FontAsset
字体资源,支持 TrueType 字体。
```cpp
class FontAsset : public Asset {
public:
AssetType type() const override { return AssetType::Font; }
float scaleForPixelHeight(float pixels) const;
const u8* data() const;
size_t dataSize() const;
};
```
### ShaderAsset
着色器资源。
```cpp
class ShaderAsset : public Asset {
public:
AssetType type() const override { return AssetType::Shader; }
const std::string& vertexSource() const;
const std::string& fragmentSource() const;
};
```
### AudioAsset
音频资源。
```cpp
class AudioAsset : public Asset {
public:
AssetType type() const override { return AssetType::Audio; }
AudioFormat format() const;
int channels() const;
int sampleRate() const;
int bitsPerSample() const;
float duration() const;
const u8* data() const;
size_t dataSize() const;
bool streaming() const;
};
```
### DataAsset
通用二进制数据。
```cpp
class DataAsset : public Asset {
public:
AssetType type() const override { return AssetType::Data; }
const u8* data() const;
size_t size() const;
};
```
## 资源打包工具
### 安装
```bash
xmake build asset_packer
```
### 用法
```
Extra2D 资源打包工具 v1.0.0
用法:
asset_packer create <output.pack> [options] <inputs...>
asset_packer list <pack file>
asset_packer extract <pack file> <output dir>
命令:
create 创建资源包
list 列出资源包内容
extract 提取资源包内容
选项:
-c, --compression <algo> 压缩算法 (none, zstd, lz4, zlib),默认 zstd
-l, --level <level> 压缩级别 (1-22),默认 3
-e, --encrypt <key> 加密密钥
-t, --encrypt-type <type> 加密类型 (xor, aes),默认 xor
-v, --verbose 详细输出
-h, --help 显示帮助
```
### 示例
```bash
# 创建资源包(使用 Zstd 压缩)
asset_packer create game.pak -c zstd -v assets/
# 创建加密资源包
asset_packer create game.pak -c zstd -e "secret_key" -t xor -v assets/
# 列出资源包内容
asset_packer list game.pak
# 提取资源包
asset_packer extract game.pak extracted/
# 使用不同压缩算法
asset_packer create game.pak -c lz4 -v assets/
asset_packer create game.pak -c zlib -l 9 -v assets/
```
## 压缩算法对比
| 算法 | 压缩率 | 压缩速度 | 解压速度 | 适用场景 |
|------|--------|----------|----------|----------|
| Zstd | 高 | 快 | 很快 | 通用推荐 |
| LZ4 | 中 | 很快 | 很快 | 实时解压 |
| Zlib | 高 | 中 | 中 | 兼容性好 |
| None | - | - | - | 已压缩资源 |
## 设计模式
### 策略模式 (AssetLoader)
不同资源类型使用不同的加载策略。
```cpp
class AssetLoader<T> {
public:
virtual Ref<T> load(const std::string& path) = 0;
virtual Ref<T> loadFromMemory(const u8* data, size_t size) = 0;
virtual bool canLoad(const std::string& path) const = 0;
virtual AssetType type() const = 0;
virtual std::vector<std::string> extensions() const = 0;
};
```
### 享元模式 (AssetCache)
共享资源实例,减少内存占用。
### 装饰器模式 (DataProcessor)
链式处理数据流。
```cpp
DataPipe pipe;
pipe.encrypt("key")
.compress(Compression::Zstd);
```
### 服务定位器模式
全局访问资源服务。
```cpp
auto* service = ServiceLocator::get<IAssetService>();
```
## 线程安全
- `AssetCache` 使用读写锁 (`std::shared_mutex`)
- `AssetService` 使用读写锁保护资源映射
- 异步加载使用独立的工作线程
- 回调在主线程执行(需要调用 `process()`
## 最佳实践
### 1. 资源路径约定
```
assets/
├── textures/
│ ├── sprites/
│ └── backgrounds/
├── fonts/
├── shaders/
└── audio/
```
### 2. 预加载关键资源
```cpp
// 游戏启动时预加载
service.preload<TextureAsset>("textures/loading.png");
service.preload<FontAsset>("fonts/main.ttf");
```
### 3. 合理设置缓存上限
```cpp
// 根据目标平台设置
#ifdef MOBILE
service.setLimit(50 * 1024 * 1024); // 50MB
#else
service.setLimit(200 * 1024 * 1024); // 200MB
#endif
```
### 4. 定期清理缓存
```cpp
// 场景切换时清理
void onSceneChange() {
service.purge();
}
```
### 5. 使用资源包减少文件数量
```cpp
// 将小文件打包成资源包
// 减少文件 I/O 操作,提高加载速度
service.mount("textures.pak");
service.mount("audio.pak");
```
## 错误处理
```cpp
auto handle = service.load<TextureAsset>("missing.png");
if (!handle.valid()) {
// 资源加载失败
std::cerr << "Failed to load texture\n";
}
// 检查加载状态
if (handle.state() == AssetState::Failed) {
// 处理失败情况
}
```
## 版本历史
- **v1.0.0** - 初始版本
- 资源加载和缓存
- 资源打包和加密
- 异步加载支持
- 多种压缩算法