Extra2D/Docs/asset_service.md

529 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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** - 初始版本
- 资源加载和缓存
- 资源打包和加密
- 异步加载支持
- 多种压缩算法