theone-cocos-standards
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTheOne Studio Cocos Creator Development Standards
TheOne Studio Cocos Creator 开发标准
⚠️ Cocos Creator 3.x (TypeScript 4.1+): All patterns and examples are compatible with Cocos Creator 3.x playable ads development.
⚠️ Cocos Creator 3.x(TypeScript 4.1+): 所有模式和示例均兼容Cocos Creator 3.x可玩广告开发。
Skill Purpose
技能目标
This skill enforces TheOne Studio's comprehensive Cocos Creator development standards with CODE QUALITY FIRST:
Priority 1: Code Quality & Hygiene (MOST IMPORTANT)
- TypeScript strict mode, ESLint configuration, access modifiers (public/private/protected)
- Throw exceptions (never silent errors)
- console.log for development, remove in production builds
- readonly for immutable fields, const for constants
- No inline comments (use descriptive names)
- Proper error handling and type safety
Priority 2: Modern TypeScript Patterns
- Array methods (map/filter/reduce) over loops
- Arrow functions, destructuring, spread operators
- Optional chaining, nullish coalescing
- Type guards, utility types (Partial, Required, Readonly)
- Modern TypeScript features
Priority 3: Cocos Creator Architecture
- Component-based Entity-Component (EC) system
- Lifecycle methods: onLoad→start→onEnable→update→onDisable→onDestroy
- EventDispatcher pattern for custom events
- Node event system (EventTouch, keyboard events)
- Resource management and pooling for playables
Priority 4: Playable Ads Performance
- DrawCall batching (<10 DrawCalls target)
- Sprite atlas configuration (auto-atlas enabled)
- GPU skinning for skeletal animations
- Zero allocations in update() loop
- Bundle size <5MB (texture compression, code minification)
本技能以代码质量优先为原则,强制执行TheOne Studio的Cocos Creator全面开发标准:
优先级1:代码质量与规范(最重要)
- TypeScript严格模式、ESLint配置、访问修饰符(public/private/protected)
- 抛出异常(绝不允许静默错误)
- console.log仅用于开发环境,生产构建中需移除
- 只读字段使用readonly,常量使用const
- 禁止行内注释(使用具名化的命名)
- 完善的错误处理与类型安全
优先级2:现代TypeScript模式
- 优先使用数组方法(map/filter/reduce)而非循环
- 箭头函数、解构赋值、扩展运算符
- 可选链操作符、空值合并运算符
- 类型守卫、工具类型(Partial、Required、Readonly)
- 现代TypeScript特性
优先级3:Cocos Creator架构
- 基于组件的实体-组件(EC)系统
- 生命周期方法:onLoad→start→onEnable→update→onDisable→onDestroy
- 自定义事件的EventDispatcher模式
- 节点事件系统(EventTouch、键盘事件)
- 可玩广告的资源管理与对象池
优先级4:可玩广告性能优化
- DrawCall批处理(目标<10次DrawCall)
- 精灵图集配置(启用自动图集)
- 骨骼动画的GPU蒙皮
- update()循环中零内存分配
- 包体大小<5MB(纹理压缩、代码压缩)
When This Skill Triggers
本技能的触发场景
- Writing or refactoring Cocos Creator TypeScript code
- Implementing playable ads features
- Working with component lifecycle and events
- Optimizing performance for playable ads
- Reviewing code changes or pull requests
- Setting up playable project architecture
- Reducing bundle size or DrawCall counts
- 编写或重构Cocos Creator TypeScript代码
- 实现可玩广告功能
- 处理组件生命周期与事件
- 优化可玩广告的性能
- 审查代码变更或合并请求
- 搭建可玩广告项目架构
- 减小包体大小或DrawCall数量
Quick Reference Guide
快速参考指南
What Do You Need Help With?
你需要哪方面的帮助?
| Priority | Task | Reference |
|---|---|---|
| 🔴 PRIORITY 1: Code Quality (Check FIRST) | ||
| 1 | TypeScript strict mode, ESLint, access modifiers | Quality & Hygiene ⭐ |
| 1 | Throw exceptions, proper error handling | Quality & Hygiene ⭐ |
| 1 | console.log (development only), remove in production | Quality & Hygiene ⭐ |
| 1 | readonly/const, no inline comments, descriptive names | Quality & Hygiene ⭐ |
| 🟡 PRIORITY 2: Modern TypeScript Patterns | ||
| 2 | Array methods, arrow functions, destructuring | Modern TypeScript |
| 2 | Optional chaining, nullish coalescing | Modern TypeScript |
| 2 | Type guards, utility types | Modern TypeScript |
| 🟢 PRIORITY 3: Cocos Architecture | ||
| 3 | Component system, @property decorator | Component System |
| 3 | Lifecycle methods (onLoad→start→update→onDestroy) | Component System |
| 3 | EventDispatcher, Node events, cleanup | Event Patterns |
| 3 | Resource loading, pooling, memory management | Playable Optimization |
| 🔵 PRIORITY 4: Performance & Review | ||
| 4 | DrawCall batching, sprite atlas, GPU skinning | Playable Optimization |
| 4 | Update loop optimization, zero allocations | Performance |
| 4 | Bundle size reduction (<5MB target) | Size Optimization |
| 4 | Architecture review (components, lifecycle, events) | Architecture Review |
| 4 | TypeScript quality review | Quality Review |
| 4 | Performance review (DrawCalls, allocations) | Performance Review |
| 优先级 | 任务 | 参考文档 |
|---|---|---|
| 🔴 优先级1:代码质量(首先检查) | ||
| 1 | TypeScript严格模式、ESLint、访问修饰符 | 质量与规范 ⭐ |
| 1 | 抛出异常、完善的错误处理 | 质量与规范 ⭐ |
| 1 | console.log(仅开发环境)、生产构建中移除 | 质量与规范 ⭐ |
| 1 | readonly/const、禁止行内注释、具名化命名 | 质量与规范 ⭐ |
| 🟡 优先级2:现代TypeScript模式 | ||
| 2 | 数组方法、箭头函数、解构赋值 | 现代TypeScript |
| 2 | 可选链操作符、空值合并运算符 | 现代TypeScript |
| 2 | 类型守卫、工具类型 | 现代TypeScript |
| 🟢 优先级3:Cocos架构 | ||
| 3 | 组件系统、@property装饰器 | 组件系统 |
| 3 | 生命周期方法(onLoad→start→update→onDestroy) | 组件系统 |
| 3 | EventDispatcher、节点事件、清理工作 | 事件模式 |
| 3 | 资源加载、对象池、内存管理 | 可玩广告优化 |
| 🔵 优先级4:性能与审查 | ||
| 4 | DrawCall批处理、精灵图集、GPU蒙皮 | 可玩广告优化 |
| 4 | Update循环优化、零内存分配 | 性能优化 |
| 4 | 包体大小缩减(目标<5MB) | 大小优化 |
| 4 | 架构审查(组件、生命周期、事件) | 架构审查 |
| 4 | TypeScript质量审查 | 质量审查 |
| 4 | 性能审查(DrawCall、内存分配) | 性能审查 |
🔴 CRITICAL: Code Quality Rules (CHECK FIRST!)
🔴 关键:代码质量规则(首先检查!)
⚠️ MANDATORY QUALITY STANDARDS
⚠️ 强制质量标准
ALWAYS enforce these BEFORE writing any code:
- Enable TypeScript strict mode - "strict": true in tsconfig.json
- Use ESLint configuration - @typescript-eslint rules enabled
- Use access modifiers - public/private/protected on all members
- Throw exceptions for errors - NEVER silent failures or undefined returns
- console.log for development only - Remove all console statements in production builds
- Use readonly for immutable fields - Mark fields that aren't reassigned
- Use const for constants - Constants should be const, not let
- No inline comments - Use descriptive names; code should be self-explanatory
- Proper null/undefined handling - Use optional chaining and nullish coalescing
- Type safety - Avoid type, use proper types and interfaces
any
Example: Enforce Quality First
typescript
// ✅ EXCELLENT: All quality rules enforced
import { _decorator, Component, Node, EventTouch } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('PlayerController')
export class PlayerController extends Component {
// 3. Access modifier, 6. readonly for immutable
@property(Node)
private readonly targetNode: Node | null = null;
// 7. const for constants
private static readonly MAX_HEALTH: number = 100;
private currentHealth: number = 100;
// Lifecycle: onLoad → start → onEnable
protected onLoad(): void {
// 4. Throw exception for errors
if (!this.targetNode) {
throw new Error('PlayerController: targetNode is not assigned');
}
// 9. Proper event listener setup
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
}
protected onDestroy(): void {
// 9. Always cleanup event listeners
this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
}
private onTouchStart(event: EventTouch): void {
// 5. console.log only for development (remove in production)
if (CC_DEBUG) {
console.log('Touch detected');
}
this.takeDamage(10);
}
// 8. Descriptive method names (no inline comments needed)
private takeDamage(amount: number): void {
this.currentHealth -= amount;
if (this.currentHealth <= 0) {
this.handlePlayerDeath();
}
}
private handlePlayerDeath(): void {
// Death logic
}
}在编写任何代码前,必须强制执行以下规则:
- 启用TypeScript严格模式 - 在tsconfig.json中设置"strict": true
- 使用ESLint配置 - 启用@typescript-eslint规则
- 使用访问修饰符 - 所有成员均需添加public/private/protected
- 错误时抛出异常 - 绝不允许静默失败或返回undefined
- console.log仅用于开发环境 - 生产构建中移除所有console语句
- 只读字段使用readonly - 标记无需重新赋值的字段
- 常量使用const - 常量必须用const,而非let
- 禁止行内注释 - 使用具名化命名;代码应具有自解释性
- 完善的null/undefined处理 - 使用可选链操作符和空值合并运算符
- 类型安全 - 避免使用类型,使用正确的类型和接口
any
示例:优先保证代码质量
typescript
// ✅ 优秀:遵循所有质量规则
import { _decorator, Component, Node, EventTouch } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('PlayerController')
export class PlayerController extends Component {
// 3. 访问修饰符,6. 只读字段
@property(Node)
private readonly targetNode: Node | null = null;
// 7. 常量使用const
private static readonly MAX_HEALTH: number = 100;
private currentHealth: number = 100;
// 生命周期:onLoad → start → onEnable
protected onLoad(): void {
// 4. 错误时抛出异常
if (!this.targetNode) {
throw new Error('PlayerController: targetNode未赋值');
}
// 9. 正确设置事件监听器
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
}
protected onDestroy(): void {
// 9. 始终清理事件监听器
this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
}
private onTouchStart(event: EventTouch): void {
// 5. console.log仅用于开发环境(生产构建中移除)
if (CC_DEBUG) {
console.log('检测到触摸');
}
this.takeDamage(10);
}
// 8. 具名化方法名(无需行内注释)
private takeDamage(amount: number): void {
this.currentHealth -= amount;
if (this.currentHealth <= 0) {
this.handlePlayerDeath();
}
}
private handlePlayerDeath(): void {
// 死亡逻辑
}
}⚠️ Cocos Creator Architecture Rules (AFTER Quality)
⚠️ Cocos Creator架构规则(在保证质量之后)
Component System Fundamentals
组件系统基础
Entity-Component (EC) System:
- Components extend class
Component - Use and
@ccclassdecorators@property - Lifecycle: onLoad → start → onEnable → update → lateUpdate → onDisable → onDestroy
Execution Order:
- onLoad() - Component initialization, one-time setup
- start() - After all components loaded, can reference other components
- onEnable() - When component/node enabled (can be called multiple times)
- update(dt) - Every frame (use sparingly for playables)
- lateUpdate(dt) - After all update() calls
- onDisable() - When component/node disabled
- onDestroy() - Cleanup, remove listeners, release resources
Universal Rules:
- ✅ Initialize in onLoad(), reference other components in start()
- ✅ Register events in onEnable(), unregister in onDisable()
- ✅ Always cleanup listeners in onDestroy()
- ✅ Avoid heavy logic in update() (performance critical for playables)
- ✅ Use readonly for @property fields that shouldn't be reassigned
- ✅ Throw exceptions for missing required references
实体-组件(EC)系统:
- 组件继承类
Component - 使用和
@ccclass装饰器@property - 生命周期:onLoad → start → onEnable → update → lateUpdate → onDisable → onDestroy
执行顺序:
- onLoad() - 组件初始化,一次性设置
- start() - 所有组件加载完成后执行,可引用其他组件
- onEnable() - 组件/节点启用时执行(可多次调用)
- update(dt) - 每帧执行(可玩广告中需谨慎使用)
- lateUpdate(dt) - 所有update()调用完成后执行
- onDisable() - 组件/节点禁用时执行
- onDestroy() - 清理工作,移除监听器,释放资源
通用规则:
- ✅ 在onLoad()中初始化,在start()中引用其他组件
- ✅ 在onEnable()中注册事件,在onDisable()中注销事件
- ✅ 始终在onDestroy()中清理监听器
- ✅ 避免在update()中执行重逻辑(可玩广告的性能关键)
- ✅ 对于不应重新赋值的@property字段,使用readonly
- ✅ 对于缺失的必要引用,抛出异常
Brief Examples
简短示例
🔴 Code Quality First
🔴 优先保证代码质量
typescript
// ✅ EXCELLENT: Quality rules enforced
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('GameManager')
export class GameManager extends Component {
@property(Node)
private readonly playerNode: Node | null = null;
private static readonly MAX_SCORE: number = 1000;
private currentScore: number = 0;
protected onLoad(): void {
// Throw exception for missing required references
if (!this.playerNode) {
throw new Error('GameManager: playerNode is required');
}
if (CC_DEBUG) {
console.log('GameManager initialized'); // Development only
}
}
public addScore(points: number): void {
if (points <= 0) {
throw new Error('GameManager.addScore: points must be positive');
}
this.currentScore = Math.min(
this.currentScore + points,
GameManager.MAX_SCORE
);
}
}typescript
// ✅ 优秀:遵循质量规则
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('GameManager')
export class GameManager extends Component {
@property(Node)
private readonly playerNode: Node | null = null;
private static readonly MAX_SCORE: number = 1000;
private currentScore: number = 0;
protected onLoad(): void {
// 缺失必要引用时抛出异常
if (!this.playerNode) {
throw new Error('GameManager: playerNode为必填项');
}
if (CC_DEBUG) {
console.log('GameManager已初始化'); // 仅开发环境
}
}
public addScore(points: number): void {
if (points <= 0) {
throw new Error('GameManager.addScore: 分数必须为正数');
}
this.currentScore = Math.min(
this.currentScore + points,
GameManager.MAX_SCORE
);
}
}🟡 Modern TypeScript Patterns
🟡 现代TypeScript模式
typescript
// ✅ GOOD: Array methods instead of loops
const activeEnemies = allEnemies.filter(e => e.isActive);
const enemyPositions = activeEnemies.map(e => e.node.position);
// ✅ GOOD: Optional chaining and nullish coalescing
const playerName = player?.name ?? 'Unknown';
// ✅ GOOD: Destructuring
const { x, y } = this.node.position;
// ✅ GOOD: Arrow functions
this.enemies.forEach(enemy => enemy.takeDamage(10));
// ✅ GOOD: Type guards
function isPlayer(node: Node): node is PlayerNode {
return node.getComponent(PlayerController) !== null;
}typescript
// ✅ 良好:使用数组方法而非循环
const activeEnemies = allEnemies.filter(e => e.isActive);
const enemyPositions = activeEnemies.map(e => e.node.position);
// ✅ 良好:可选链操作符和空值合并运算符
const playerName = player?.name ?? 'Unknown';
// ✅ 良好:解构赋值
const { x, y } = this.node.position;
// ✅ 良好:箭头函数
this.enemies.forEach(enemy => enemy.takeDamage(10));
// ✅ 良好:类型守卫
function isPlayer(node: Node): node is PlayerNode {
return node.getComponent(PlayerController) !== null;
}🟢 Cocos Creator Component Pattern
🟢 Cocos Creator组件模式
typescript
import { _decorator, Component, Node, EventTouch, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('TouchHandler')
export class TouchHandler extends Component {
@property(Node)
private readonly targetNode: Node | null = null;
private readonly tempVec3: Vec3 = new Vec3(); // Reusable vector
// 1. onLoad: Initialize component
protected onLoad(): void {
if (!this.targetNode) {
throw new Error('TouchHandler: targetNode is required');
}
}
// 2. start: Reference other components (if needed)
protected start(): void {
// Can safely access other components here
}
// 3. onEnable: Register event listeners
protected onEnable(): void {
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
}
// 4. onDisable: Unregister event listeners
protected onDisable(): void {
this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.off(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
}
// 5. onDestroy: Final cleanup
protected onDestroy(): void {
// Release any additional resources
}
private onTouchStart(event: EventTouch): void {
// Handle touch
}
private onTouchMove(event: EventTouch): void {
// Reuse vector to avoid allocations
this.targetNode!.getPosition(this.tempVec3);
this.tempVec3.y += 10;
this.targetNode!.setPosition(this.tempVec3);
}
}typescript
import { _decorator, Component, Node, EventTouch, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('TouchHandler')
export class TouchHandler extends Component {
@property(Node)
private readonly targetNode: Node | null = null;
private readonly tempVec3: Vec3 = new Vec3(); // 可复用向量
// 1. onLoad: 初始化组件
protected onLoad(): void {
if (!this.targetNode) {
throw new Error('TouchHandler: targetNode为必填项');
}
}
// 2. start: 引用其他组件(如有需要)
protected start(): void {
// 此处可安全访问其他组件
}
// 3. onEnable: 注册事件监听器
protected onEnable(): void {
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
}
// 4. onDisable: 注销事件监听器
protected onDisable(): void {
this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.off(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
}
// 5. onDestroy: 最终清理
protected onDestroy(): void {
// 释放其他资源
}
private onTouchStart(event: EventTouch): void {
// 处理触摸事件
}
private onTouchMove(event: EventTouch): void {
// 复用向量以避免内存分配
this.targetNode!.getPosition(this.tempVec3);
this.tempVec3.y += 10;
this.targetNode!.setPosition(this.tempVec3);
}
}🟢 Event Dispatcher Pattern
🟢 EventDispatcher模式
typescript
import { _decorator, Component, EventTarget } from 'cc';
const { ccclass } = _decorator;
// Custom event types
export enum GameEvent {
SCORE_CHANGED = 'score_changed',
LEVEL_COMPLETE = 'level_complete',
PLAYER_DIED = 'player_died',
}
export interface ScoreChangedEvent {
oldScore: number;
newScore: number;
}
@ccclass('EventManager')
export class EventManager extends Component {
private static instance: EventManager | null = null;
private readonly eventTarget: EventTarget = new EventTarget();
protected onLoad(): void {
if (EventManager.instance) {
throw new Error('EventManager: instance already exists');
}
EventManager.instance = this;
}
public static emit(event: GameEvent, data?: any): void {
if (!EventManager.instance) {
throw new Error('EventManager: instance not initialized');
}
EventManager.instance.eventTarget.emit(event, data);
}
public static on(event: GameEvent, callback: Function, target?: any): void {
if (!EventManager.instance) {
throw new Error('EventManager: instance not initialized');
}
EventManager.instance.eventTarget.on(event, callback, target);
}
public static off(event: GameEvent, callback: Function, target?: any): void {
if (!EventManager.instance) {
throw new Error('EventManager: instance not initialized');
}
EventManager.instance.eventTarget.off(event, callback, target);
}
}
// Usage in component
@ccclass('ScoreDisplay')
export class ScoreDisplay extends Component {
protected onEnable(): void {
EventManager.on(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
}
protected onDisable(): void {
EventManager.off(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
}
private onScoreChanged(data: ScoreChangedEvent): void {
console.log(`Score: ${data.oldScore} → ${data.newScore}`);
}
}typescript
import { _decorator, Component, EventTarget } from 'cc';
const { ccclass } = _decorator;
// 自定义事件类型
export enum GameEvent {
SCORE_CHANGED = 'score_changed',
LEVEL_COMPLETE = 'level_complete',
PLAYER_DIED = 'player_died',
}
export interface ScoreChangedEvent {
oldScore: number;
newScore: number;
}
@ccclass('EventManager')
export class EventManager extends Component {
private static instance: EventManager | null = null;
private readonly eventTarget: EventTarget = new EventTarget();
protected onLoad(): void {
if (EventManager.instance) {
throw new Error('EventManager: 实例已存在');
}
EventManager.instance = this;
}
public static emit(event: GameEvent, data?: any): void {
if (!EventManager.instance) {
throw new Error('EventManager: 实例未初始化');
}
EventManager.instance.eventTarget.emit(event, data);
}
public static on(event: GameEvent, callback: Function, target?: any): void {
if (!EventManager.instance) {
throw new Error('EventManager: 实例未初始化');
}
EventManager.instance.eventTarget.on(event, callback, target);
}
public static off(event: GameEvent, callback: Function, target?: any): void {
if (!EventManager.instance) {
throw new Error('EventManager: 实例未初始化');
}
EventManager.instance.eventTarget.off(event, callback, target);
}
}
// 在组件中使用
@ccclass('ScoreDisplay')
export class ScoreDisplay extends Component {
protected onEnable(): void {
EventManager.on(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
}
protected onDisable(): void {
EventManager.off(GameEvent.SCORE_CHANGED, this.onScoreChanged, this);
}
private onScoreChanged(data: ScoreChangedEvent): void {
console.log(`分数: ${data.oldScore} → ${data.newScore}`);
}
}🔵 Playable Performance Optimization
🔵 可玩广告性能优化
typescript
import { _decorator, Component, Node, Sprite, SpriteAtlas } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('OptimizedSpriteManager')
export class OptimizedSpriteManager extends Component {
// Use sprite atlas for DrawCall batching
@property(SpriteAtlas)
private readonly characterAtlas: SpriteAtlas | null = null;
// Preallocate arrays to avoid allocations in update()
private readonly tempNodes: Node[] = [];
private frameCount: number = 0;
protected onLoad(): void {
if (!this.characterAtlas) {
throw new Error('OptimizedSpriteManager: characterAtlas is required');
}
// Prewarm sprite frames from atlas
this.prewarmSpriteFrames();
}
private prewarmSpriteFrames(): void {
// Load all sprites from atlas (batched in single DrawCall)
const spriteFrame = this.characterAtlas!.getSpriteFrame('character_idle');
if (!spriteFrame) {
throw new Error('Sprite frame not found in atlas');
}
}
// Optimize update: avoid allocations, use object pooling
protected update(dt: number): void {
// Run expensive operations every N frames instead of every frame
this.frameCount++;
if (this.frameCount % 10 === 0) {
this.updateExpensiveOperation();
}
}
private updateExpensiveOperation(): void {
// Reuse array instead of creating new one
this.tempNodes.length = 0;
// Batch operations to reduce DrawCalls
}
}typescript
import { _decorator, Component, Node, Sprite, SpriteAtlas } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('OptimizedSpriteManager')
export class OptimizedSpriteManager extends Component {
// 使用精灵图集进行DrawCall批处理
@property(SpriteAtlas)
private readonly characterAtlas: SpriteAtlas | null = null;
// 预分配数组以避免在update()中分配内存
private readonly tempNodes: Node[] = [];
private frameCount: number = 0;
protected onLoad(): void {
if (!this.characterAtlas) {
throw new Error('OptimizedSpriteManager: characterAtlas为必填项');
}
// 预加载图集精灵帧
this.prewarmSpriteFrames();
}
private prewarmSpriteFrames(): void {
// 从图集加载所有精灵(批处理为单次DrawCall)
const spriteFrame = this.characterAtlas!.getSpriteFrame('character_idle');
if (!spriteFrame) {
throw new Error('图集中未找到精灵帧');
}
}
// 优化update:避免内存分配,使用对象池
protected update(dt: number): void {
// 每N帧执行一次耗时操作,而非每帧执行
this.frameCount++;
if (this.frameCount % 10 === 0) {
this.updateExpensiveOperation();
}
}
private updateExpensiveOperation(): void {
// 复用数组而非创建新数组
this.tempNodes.length = 0;
// 批处理操作以减少DrawCall
}
}Code Review Checklist
代码审查清单
Quick Validation (before committing)
快速验证(提交前)
🔴 Code Quality (CHECK FIRST):
- TypeScript strict mode enabled in tsconfig.json
- ESLint rules passing (no errors)
- All access modifiers correct (public/private/protected)
- Exceptions thrown for errors (no silent failures)
- console.log removed or wrapped in CC_DEBUG
- readonly used for non-reassigned fields
- const used for constants
- No inline comments (self-explanatory code)
- Proper null/undefined handling
- No types (use proper types)
any
🟡 Modern TypeScript Patterns:
- Array methods used instead of manual loops
- Arrow functions for callbacks
- Optional chaining (?.) for safe property access
- Nullish coalescing (??) for default values
- Destructuring for cleaner code
- Type guards for type narrowing
🟢 Cocos Creator Architecture:
- Component lifecycle methods in correct order
- onLoad() for initialization, start() for references
- Event listeners registered in onEnable()
- Event listeners unregistered in onDisable()
- Resources released in onDestroy()
- @property decorator used correctly
- Required references validated (throw if null)
🔵 Playable Performance:
- No allocations in update() loop
- Sprite atlas used for DrawCall batching
- GPU skinning enabled for skeletal animations
- Expensive operations throttled (not every frame)
- Object pooling for frequently created objects
- Texture compression enabled
- Bundle size <5MB target
- DrawCall count <10 target
🔴 代码质量(首先检查):
- tsconfig.json中启用TypeScript严格模式
- ESLint规则通过(无错误)
- 所有访问修饰符设置正确(public/private/protected)
- 错误时抛出异常(无静默失败)
- console.log已移除或包裹在CC_DEBUG中
- 非重新赋值字段使用readonly
- 常量使用const
- 无行内注释(代码自解释)
- 完善的null/undefined处理
- 未使用类型(使用正确类型)
any
🟡 现代TypeScript模式:
- 使用数组方法而非手动循环
- 回调函数使用箭头函数
- 使用可选链操作符(?.)进行安全属性访问
- 使用空值合并运算符(??)设置默认值
- 使用解构赋值简化代码
- 使用类型守卫进行类型收窄
🟢 Cocos Creator架构:
- 组件生命周期方法顺序正确
- onLoad()用于初始化,start()用于引用
- 事件监听器在onEnable()中注册
- 事件监听器在onDisable()中注销
- 资源在onDestroy()中释放
- @property装饰器使用正确
- 必要引用已验证(为空时抛出异常)
🔵 可玩广告性能:
- update()循环中无内存分配
- 使用精灵图集进行DrawCall批处理
- 骨骼动画启用GPU蒙皮
- 耗时操作已节流(非每帧执行)
- 频繁创建的对象使用对象池
- 启用纹理压缩
- 包体大小<5MB目标
- DrawCall数量<10目标
Common Mistakes to Avoid
需避免的常见错误
❌ DON'T:
❌ 禁止:
- Ignore TypeScript strict mode → Enable "strict": true
- Silent error handling → Throw exceptions for errors
- Leave console.log in production → Remove or wrap in CC_DEBUG
- Skip access modifiers → Use public/private/protected
- Use type → Define proper types and interfaces
any - Add inline comments → Use descriptive names instead
- Skip event cleanup → Always unregister in onDisable/onDestroy
- Allocate in update() → Preallocate and reuse objects
- Forget sprite atlas → Use atlas for DrawCall batching
- Heavy logic in update() → Throttle expensive operations
- Skip null checks → Validate required references in onLoad
- Mutable @property fields → Use readonly when appropriate
- Manual loops over arrays → Use map/filter/reduce
- Ignore bundle size → Monitor and optimize (<5MB target)
- 忽略TypeScript严格模式 → 必须启用"strict": true
- 静默错误处理 → 错误时必须抛出异常
- 生产代码中保留console.log → 移除或包裹在CC_DEBUG中
- 跳过访问修饰符 → 必须使用public/private/protected
- 使用类型 → 定义正确的类型和接口
any - 添加行内注释 → 改用具名化命名
- 跳过事件清理 → 必须在onDisable/onDestroy中注销事件
- 在update()中分配内存 → 预分配并复用对象
- 忘记使用精灵图集 → 必须使用图集进行DrawCall批处理
- 在update()中执行重逻辑 → 节流耗时操作
- 跳过空值检查 → 在onLoad()中验证必要引用
- 可变的@property字段 → 合适时使用readonly
- 手动循环数组 → 使用map/filter/reduce
- 忽略包体大小 → 监控并优化(目标<5MB)
✅ DO:
✅ 推荐:
- Enable TypeScript strict mode ("strict": true)
- Throw exceptions for errors (never silent failures)
- Use console.log for development only (remove in production)
- Use access modifiers (public/private/protected)
- Define proper types (avoid )
any - Use descriptive names (no inline comments)
- Always cleanup events (onDisable/onDestroy)
- Preallocate objects (reuse in update())
- Use sprite atlas (DrawCall batching)
- Throttle expensive operations (not every frame)
- Validate required references (throw in onLoad if null)
- Use readonly for @property (when appropriate)
- Use array methods (map/filter/reduce)
- Monitor bundle size (<5MB target for playables)
- 启用TypeScript严格模式("strict": true)
- 错误时抛出异常(绝不允许静默失败)
- console.log仅用于开发环境(生产构建中移除)
- 使用访问修饰符(public/private/protected)
- 定义正确的类型(避免)
any - 使用具名化命名(无需行内注释)
- 始终清理事件(onDisable/onDestroy中)
- 预分配对象(在update()中复用)
- 使用精灵图集(DrawCall批处理)
- 节流耗时操作(非每帧执行)
- 验证必要引用(onLoad()中为空则抛出异常)
- 合适时为@property使用readonly
- 使用数组方法(map/filter/reduce)
- 监控包体大小(可玩广告目标<5MB)
Review Severity Levels
审查严重程度等级
🔴 Critical (Must Fix)
🔴 严重(必须修复)
- TypeScript strict mode disabled - Must enable "strict": true
- Silent error handling - Must throw exceptions for errors
- console.log in production code - Remove or wrap in CC_DEBUG
- Missing access modifiers - All members must have modifiers
- Using type without justification - Define proper types
any - Inline comments instead of descriptive names - Rename and remove comments
- Event listeners not cleaned up - Memory leak, must unregister
- Missing required reference validation - Must throw in onLoad if null
- Allocations in update() loop - Performance critical, must preallocate
- No sprite atlas for multiple sprites - DrawCall explosion, must use atlas
- Bundle size >5MB - Exceeds playable limit, must optimize
- TypeScript严格模式未启用 - 必须设置"strict": true
- 静默错误处理 - 必须抛出异常
- 生产代码中存在console.log - 移除或包裹在CC_DEBUG中
- 缺失访问修饰符 - 所有成员必须添加修饰符
- 无正当理由使用类型 - 定义正确的类型
any - 使用行内注释而非具名化命名 - 重命名并移除注释
- 事件监听器未清理 - 内存泄漏,必须注销
- 缺失必要引用验证 - onLoad()中为空则必须抛出异常
- update()循环中存在内存分配 - 性能关键,必须预分配
- 多精灵未使用精灵图集 - DrawCall激增,必须使用图集
- 包体大小>5MB - 超出可玩广告限制,必须优化
🟡 Important (Should Fix)
🟡 重要(应该修复)
- Missing readonly on @property fields - Should be readonly when not reassigned
- Missing const for constants - Should use const instead of let
- Manual loops instead of array methods - Should use map/filter/reduce
- Missing optional chaining - Should use ?. for safe access
- Missing nullish coalescing - Should use ?? for default values
- Heavy logic in update() - Should throttle expensive operations
- No object pooling for frequent allocations - Should implement pooling
- Texture compression not enabled - Should enable for smaller bundle
- DrawCall count >10 - Should optimize batching
- @property字段未使用readonly - 无需重新赋值时应使用readonly
- 常量未使用const - 应使用const而非let
- 手动循环而非数组方法 - 应使用map/filter/reduce
- 未使用可选链操作符 - 应使用?.进行安全访问
- 未使用空值合并运算符 - 应使用??设置默认值
- update()中执行重逻辑 - 应节流耗时操作
- 频繁分配的对象未使用对象池 - 应实现对象池
- 未启用纹理压缩 - 应启用以减小包体
- DrawCall数量>10 - 应优化批处理
🟢 Nice to Have (Suggestion)
🟢 建议(可选优化)
- Could use arrow function for callback
- Could destructure for cleaner code
- Could use type guard for type safety
- Could improve naming for clarity
- Could add interface for better typing
- Could optimize algorithm for better performance
- 可使用箭头函数作为回调
- 可使用解构赋值简化代码
- 可使用类型守卫保证类型安全
- 可优化命名以提升清晰度
- 可添加接口以提升类型化
- 可优化算法以提升性能
Detailed References
详细参考文档
TypeScript Language Standards
TypeScript语言标准
- Quality & Hygiene - Strict mode, ESLint, access modifiers, error handling
- Modern TypeScript - Array methods, optional chaining, type guards, utility types
- Performance - Update loop optimization, zero allocations, caching
- 质量与规范 - 严格模式、ESLint、访问修饰符、错误处理
- 现代TypeScript - 数组方法、可选链、类型守卫、工具类型
- 性能优化 - Update循环优化、零内存分配、缓存
Cocos Creator Framework
Cocos Creator框架
- Component System - EC system, lifecycle methods, @property decorator
- Event Patterns - EventDispatcher, Node events, subscription cleanup
- Playable Optimization - DrawCall batching, sprite atlas, GPU skinning, resource pooling
- Size Optimization - Bundle size reduction, texture compression, build optimization
- 组件系统 - EC系统、生命周期方法、@property装饰器
- 事件模式 - EventDispatcher、节点事件、订阅清理
- 可玩广告优化 - DrawCall批处理、精灵图集、GPU蒙皮、对象池
- 大小优化 - 包体大小缩减、纹理压缩、构建优化
Code Review
代码审查
- Architecture Review - Component violations, lifecycle errors, event leaks
- Quality Review - TypeScript quality issues, access modifiers, error handling
- Performance Review - Playable-specific performance problems, DrawCalls, allocations
- 架构审查 - 组件违规、生命周期错误、事件泄漏
- 质量审查 - TypeScript质量问题、访问修饰符、错误处理
- 性能审查 - 可玩广告特定性能问题、DrawCall、内存分配
Summary
总结
This skill provides comprehensive Cocos Creator development standards for TheOne Studio's playable ads team:
- TypeScript Excellence: Strict mode, modern patterns, type safety
- Cocos Architecture: Component lifecycle, event patterns, resource management
- Playable Performance: DrawCall batching, GPU skinning, <5MB bundles
- Code Quality: Enforced quality, hygiene, and performance rules
Use the Quick Reference Guide above to navigate to the specific pattern you need.
本技能为TheOne Studio的可玩广告团队提供全面的Cocos Creator开发标准:
- TypeScript卓越性:严格模式、现代模式、类型安全
- Cocos架构:组件生命周期、事件模式、资源管理
- 可玩广告性能:DrawCall批处理、GPU蒙皮、<5MB包体
- 代码质量:强制执行质量、规范与性能规则
使用上方的快速参考指南导航至你需要的特定模式。