theone-cocos-standards by the1studio/theone-training-skills
npx skills add https://github.com/the1studio/theone-training-skills --skill theone-cocos-standards⚠️ Cocos Creator 3.x (TypeScript 4.1+): 所有模式和示例均兼容 Cocos Creator 3.x 可玩广告开发。
本技能强制执行 TheOne Studio 全面的 Cocos Creator 开发标准,遵循 代码质量优先 原则:
优先级 1:代码质量与规范 (最重要)
优先级 2:现代 TypeScript 模式
优先级 3:Cocos Creator 架构
优先级 4:可玩广告性能
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 优先级 | 任务 | 参考 |
|---|---|---|
| 🔴 优先级 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 | 性能审查 (DrawCalls,内存分配) | 性能审查 |
在编写任何代码之前,始终强制执行以下规则:
any 类型,使用正确的类型和接口示例:首先强制执行质量
// ✅ 优秀:所有质量规则均已强制执行
import { _decorator, Component, Node, EventTouch } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('PlayerController')
export class PlayerController extends Component {
// 3. 访问修饰符,6. 对不可变字段使用 readonly
@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 is not assigned');
}
// 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('Touch detected');
}
this.takeDamage(10);
}
// 8. 描述性方法名称 (无需行内注释)
private takeDamage(amount: number): void {
this.currentHealth -= amount;
if (this.currentHealth <= 0) {
this.handlePlayerDeath();
}
}
private handlePlayerDeath(): void {
// 死亡逻辑
}
}
实体-组件 (EC) 系统:
Component 类@ccclass 和 @property 装饰器执行顺序:
通用规则:
// ✅ 优秀:质量规则已强制执行
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 is required');
}
if (CC_DEBUG) {
console.log('GameManager initialized'); // 仅用于开发
}
}
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
);
}
}
// ✅ 良好:使用数组方法而非循环
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;
}
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 is required');
}
}
// 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);
}
}
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: 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);
}
}
// 在组件中使用
@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}`);
}
}
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 is required');
}
// 预加载图集中的精灵帧
this.prewarmSpriteFrames();
}
private prewarmSpriteFrames(): void {
// 从图集加载所有精灵 (在单个 DrawCall 中批处理)
const spriteFrame = this.characterAtlas!.getSpriteFrame('character_idle');
if (!spriteFrame) {
throw new Error('Sprite frame not found in atlas');
}
}
// 优化 update:避免内存分配,使用对象池
protected update(dt: number): void {
// 每 N 帧执行一次昂贵操作,而非每帧都执行
this.frameCount++;
if (this.frameCount % 10 === 0) {
this.updateExpensiveOperation();
}
}
private updateExpensiveOperation(): void {
// 复用数组而非创建新数组
this.tempNodes.length = 0;
// 批处理操作以减少 DrawCalls
}
}
🔴 代码质量 (首先检查):
any 类型 (使用正确的类型)🟡 现代 TypeScript 模式:
🟢 Cocos Creator 架构:
🔵 可玩广告性能:
any 类型 → 定义正确的类型和接口any)any 类型 - 定义正确的类型本技能为 TheOne Studio 的可玩广告团队提供了全面的 Cocos Creator 开发标准:
使用上方的快速参考指南导航到您需要的特定模式。
每周安装次数
106
仓库
GitHub 星标数
56
首次出现
Jan 22, 2026
安全审计
安装于
gemini-cli96
opencode93
codex91
github-copilot89
cursor82
kimi-cli81
⚠️ Cocos Creator 3.x (TypeScript 4.1+): All patterns and examples are compatible with Cocos Creator 3.x playable ads development.
This skill enforces TheOne Studio's comprehensive Cocos Creator development standards with CODE QUALITY FIRST :
Priority 1: Code Quality & Hygiene (MOST IMPORTANT)
Priority 2: Modern TypeScript Patterns
Priority 3: Cocos Creator Architecture
Priority 4: Playable Ads Performance
| 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 |
ALWAYS enforce these BEFORE writing any code:
any type, use proper types and interfacesExample: Enforce Quality First
// ✅ 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
}
}
Entity-Component (EC) System:
Component class@ccclass and @property decoratorsExecution Order:
Universal Rules:
// ✅ 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
);
}
}
// ✅ 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;
}
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);
}
}
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}`);
}
}
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
}
}
🔴 Code Quality (CHECK FIRST):
any types (use proper types)🟡 Modern TypeScript Patterns:
🟢 Cocos Creator Architecture:
🔵 Playable Performance:
any type → Define proper types and interfacesany)any type without justification - Define proper typesThis skill provides comprehensive Cocos Creator development standards for TheOne Studio's playable ads team:
Use the Quick Reference Guide above to navigate to the specific pattern you need.
Weekly Installs
106
Repository
GitHub Stars
56
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli96
opencode93
codex91
github-copilot89
cursor82
kimi-cli81
Tailwind CSS v4 + shadcn/ui 生产级技术栈配置指南与最佳实践
2,600 周安装
| 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 |