gratitude.durian.xpcool.com/WECHAT_OPTIMIZATION_GUIDE.md
2026-08-14 18:01:45 +08:00

12 KiB
Raw Blame History

微信小游戏性能优化指南

📊 性能指标要求

微信官方标准

  • 启动时间:冷启动 < 3秒热启动 < 1秒
  • 首屏渲染< 2秒
  • 帧率:稳定 60 FPS低端机可降至 30 FPS
  • 内存占用< 200 MBiOS< 300 MBAndroid
  • 包体大小:主包 ≤ 20 MB总包 ≤ 200 MB

🎯 关键优化点

1. 包体优化

代码分包策略

// project.json 配置
{
  "subpackages": [
    {
      "name": "core",
      "root": "subpackages/core/"
    },
    {
      "name": "levels",
      "root": "subpackages/levels/",
      "lazy": true  // 按需加载
    }
  ]
}

资源压缩

  • 图片:使用 TinyPNG 或 ImageOptim 压缩,目标减少 50-70%
  • 音频MP3 格式,比特率 128kbps单声道
  • 纹理:使用 ASTC 格式Android和 PVRTCiOS

代码优化

// ❌ 避免:频繁创建对象
function spawnFruit() {
    const fruit = new Fruit();  // 每次new会触发GC
    return fruit;
}

// ✅ 推荐:使用对象池
const fruitPool: Fruit[] = [];
function spawnFruit() {
    let fruit = fruitPool.pop();
    if (!fruit) {
        fruit = new Fruit();
    }
    fruit.reset();
    return fruit;
}

2. 内存管理

主动触发 GC

// 在合适的时机触发垃圾回收
class GameManager {
    onGameOver() {
        // 清理临时对象
        this.clearEffects();
        this.clearBullets();
        
        // 微信环境触发GC
        if (typeof wx !== 'undefined' && wx.triggerGC) {
            setTimeout(() => wx.triggerGC(), 1000);
        }
    }
}

资源释放策略

// 场景切换时释放资源
import { resources, AssetManager } from 'cc';

class ResourceManager {
    static releaseUnusedAssets() {
        // 释放未使用的资源
        resources.releaseAll();
        
        // 强制清理缓存
        AssetManager.cacheManager?.clear();
    }
    
    static releaseTexture(textureName: string) {
        const texture = resources.get(textureName);
        if (texture) {
            resources.release(textureName);
            texture.destroy();  // 立即销毁
        }
    }
}

内存监控

// 定期检查内存使用
class MemoryMonitor {
    private static checkInterval = 10000; // 10秒
    
    static startMonitoring() {
        setInterval(() => {
            if (wx.getSystemInfoSync) {
                const info = wx.getSystemInfoSync();
                const memoryMB = (info.memoryUsage || 0) / 1024 / 1024;
                
                if (memoryMB > 200) {
                    console.warn(`[Memory] 内存警告: ${memoryMB.toFixed(1)} MB`);
                    this.triggerCleanup();
                }
            }
        }, this.checkInterval);
    }
    
    private static triggerCleanup() {
        console.log('[Memory] 执行内存清理...');
        // 1. 清理特效
        // 2. 清理粒子
        // 3. 触发GC
    }
}

3. 渲染优化

减少 Draw Calls

// ✅ 合并相同材质的Sprite
// 将多个小水果合并到一个节点下,使用同一材质

// ❌ 避免:每个水果单独一个节点
fruit1.node.parent = rootNode;
fruit2.node.parent = rootNode;

// ✅ 推荐:使用批量渲染
const batchNode = new Node('FruitBatch');
fruit1.node.parent = batchNode;
fruit2.node.parent = batchNode;
batchNode.parent = rootNode;

合批技巧

  • 相同材质的Sprite放在同一父节点下
  • 使用 SpriteAtlas 打包小图
  • 避免动态修改材质参数

降低 Overdraw

// 设置合理的渲染层级
camera.clearFlags = ClearFlag.SOLID | ClearFlag.DEPTH;

// 隐藏不可见对象
node.active = false;  // 完全禁用
// 而不是
node.opacity = 0;     // 仍然参与渲染

4. 音频优化

音频格式选择

类型 格式 比特率 声道 文件大小
BGM MP3 128kbps 立体声 ~2MB/分钟
SFX MP3 96kbps 单声道 ~50KB/个
Voice MP3 64kbps 单声道 ~30KB/个

音频管理最佳实践

class AudioManager {
    // 限制同时播放的音效数量
    private maxConcurrentSFX = 5;
    private activeSFXCount = 0;
    
    playSFX(name: string) {
        if (this.activeSFXCount >= this.maxConcurrentSFX) {
            console.warn('[Audio] 音效并发数已达上限');
            return;
        }
        
        this.activeSFXCount++;
        // 播放音效...
        
        // 播放完成后递减计数
        setTimeout(() => {
            this.activeSFXCount--;
        }, duration);
    }
}

5. 网络优化

广告预加载

// 在游戏启动3秒后预加载广告
setTimeout(() => {
    AdManager.preloadAds();
}, 3000);

// 关卡结束前提前准备广告
class LevelManager {
    onLevelComplete() {
        // 提前加载插屏广告
        AdManager.preloadInterstitial();
        
        // 显示结算界面
        this.showResultPanel();
    }
}

数据上报优化

// ❌ 避免:频繁上报
wx.reportAnalytics('merge', { level: 1 });  // 每次合成

// ✅ 推荐:批量上报
class AnalyticsManager {
    private eventQueue: any[] = [];
    
    recordMerge(level: number) {
        this.eventQueue.push({
            event: 'merge',
            data: { level },
            timestamp: Date.now()
        });
        
        // 每10个事件或每30秒上报一次
        if (this.eventQueue.length >= 10) {
            this.flushEvents();
        }
    }
    
    private flushEvents() {
        this.eventQueue.forEach(event => {
            wx.reportAnalytics(event.event, event.data);
        });
        this.eventQueue = [];
    }
}

🔧 微信开发者工具调试

性能面板使用

  1. 打开微信开发者工具
  2. 点击「调试器」→「Performance」
  3. 观察以下指标:
    • FPS 曲线
    • 内存占用
    • Draw Calls
    • JS 执行时间

真机测试

# 1. 构建微信小游戏
cocos build --platform wechatgame --output ./build

# 2. 用微信开发者工具打开 build 目录

# 3. 点击「预览」生成二维码

# 4. 用手机微信扫码,在真机上测试

性能问题定位

// 添加性能埋点
class PerformanceTracker {
    private static marks: Map<string, number> = new Map();
    
    static mark(name: string) {
        this.marks.set(name, performance.now());
    }
    
    static measure(name: string): number {
        const start = this.marks.get(name);
        if (!start) return 0;
        
        const duration = performance.now() - start;
        console.log(`[Perf] ${name}: ${duration.toFixed(2)}ms`);
        return duration;
    }
}

// 使用示例
PerformanceTracker.mark('levelLoadStart');
// ... 加载关卡 ...
PerformanceTracker.measure('levelLoad');

📱 低端机适配

检测低端设备

class DeviceDetector {
    static isLowEndDevice(): boolean {
        if (!wx.getSystemInfoSync) return false;
        
        const info = wx.getSystemInfoSync();
        
        // CPU核心数 ≤ 2
        if (info.cpuNum <= 2) return true;
        
        // 内存 ≤ 2GB
        if (info.totalMemory <= 2 * 1024 * 1024 * 1024) return true;
        
        // 旧款iPhone
        if (info.model.includes('iPhone 6') || 
            info.model.includes('iPhone 7')) {
            return true;
        }
        
        return false;
    }
    
    static applyLowEndSettings() {
        console.log('[Device] 应用低端机优化设置...');
        
        // 降低目标帧率
        GAME_CONFIG.targetFPS = 30;
        
        // 减少最大水果数量
        GAME_CONFIG.maxFruitsOnScreen = 25;
        
        // 禁用部分特效
        GAME_CONFIG.enableParticles = false;
        
        // 降低音频质量
        AudioManager.getInstance().setSFXVolume(0.5);
    }
}

分级画质设置

enum QualityLevel {
    Low,
    Medium,
    High
}

class QualitySettings {
    static apply(level: QualityLevel) {
        switch (level) {
            case QualityLevel.Low:
                // 低画质
                this.setMaxParticles(10);
                this.setShadowEnabled(false);
                this.setAntiAliasing(false);
                break;
                
            case QualityLevel.Medium:
                // 中画质
                this.setMaxParticles(30);
                this.setShadowEnabled(true);
                this.setAntiAliasing(false);
                break;
                
            case QualityLevel.High:
                // 高画质
                this.setMaxParticles(50);
                this.setShadowEnabled(true);
                this.setAntiAliasing(true);
                break;
        }
    }
}

🚀 构建发布流程

1. 构建前检查清单

  • 移除所有 console.log(或使用条件编译)
  • 压缩所有图片和音频
  • 测试广告位ID是否正确
  • 验证存档系统正常
  • 检查内存泄漏(长时间运行测试)

2. 构建命令

# Cocos Creator 命令行构建
cocos build \
  --platform wechatgame \
  --output ./build/wechatgame \
  --debug false \
  --compress true

3. 上传到微信后台

# 使用微信开发者工具命令行上传
wechat-miniprogram auto \
  --project ./build/wechatgame \
  --appid wxb2b7651c561f9d53 \
  --version 1.0.0 \
  --desc "报恩榴莲v1.0.0"

4. 提交审核

  1. 登录微信公众平台
  2. 进入「版本管理」
  3. 选择刚上传的版本
  4. 填写审核信息:
    • 游戏简介
    • 分类:休闲 → 益智
    • 截图5张 gameplay 截图
  5. 提交审核

🐛 常见问题排查

Q1: 游戏启动慢

原因:资源加载过多
解决

  • 使用分包加载
  • 延迟加载非核心资源
  • 压缩图片和音频

Q2: 内存持续增长

原因:对象未正确释放
解决

// 确保在场景切换时清理
onDestroy() {
    this.node.removeAllChildren();
    resources.releaseAll();
    if (wx.triggerGC) wx.triggerGC();
}

Q3: 帧率不稳定

原因Draw Calls 过多或逻辑太重
解决

  • 合并相同材质的Sprite
  • 使用对象池
  • 优化碰撞检测算法

Q4: 广告不显示

原因广告位ID错误或未真机测试
解决

  • 确认广告位ID已替换
  • 必须在真机测试(模拟器不显示广告)
  • 检查网络连接

📈 性能监控建议

关键指标

class MetricsCollector {
    private metrics = {
        fps: 0,
        memory: 0,
        drawCalls: 0,
        avgFrameTime: 0,
    };
    
    collect() {
        // FPS
        this.metrics.fps = director.getScheduler().getFramesPerSecond();
        
        // 内存
        if (wx.getSystemInfoSync) {
            this.metrics.memory = wx.getSystemInfoSync().memoryUsage;
        }
        
        // 上报
        if (this.shouldReport()) {
            wx.reportAnalytics('perf_metrics', this.metrics);
        }
    }
}

异常监控

// 全局错误捕获
window.onerror = function(msg, url, line, col, error) {
    console.error('[Error]', msg, 'at', line, ':', col);
    
    // 上报错误
    wx.reportAnalytics('js_error', {
        message: msg,
        line: line,
        column: col,
        stack: error?.stack
    });
    
    return false;
};

总结

优化优先级

  1. P0:包体大小(必须 ≤ 20MB 主包)
  2. P0:内存管理(防止崩溃)
  3. P1帧率稳定60 FPS
  4. P1:启动速度(< 3秒
  5. P2Draw Calls 优化
  6. P2:音频优化

持续改进

  • 每周分析性能数据
  • 根据用户反馈调整难度
  • A/B 测试广告频控策略
  • 监控留存率和通关率

最后更新2026-08-14
适用版本Cocos Creator 3.8 + 微信小游戏