实际示例
完整游戏集成示例
Section titled “完整游戏集成示例”import { Scene, Core, Component, ECSComponent } from '@esengine/ecs-framework';import { BlueprintSystem, BlueprintComponent, BlueprintExpose, BlueprintProperty, BlueprintMethod} from '@esengine/blueprint';
// 1. 定义游戏组件@ECSComponent('Player')@BlueprintExpose({ displayName: '玩家', category: 'gameplay' })export class PlayerComponent extends Component { @BlueprintProperty({ displayName: '移动速度', type: 'float' }) moveSpeed: number = 5;
@BlueprintProperty({ displayName: '分数', type: 'int' }) score: number = 0;
@BlueprintMethod({ displayName: '增加分数' }) addScore(points: number): void { this.score += points; }}
@ECSComponent('Health')@BlueprintExpose({ displayName: '生命值', category: 'gameplay' })export class HealthComponent extends Component { @BlueprintProperty({ displayName: '当前生命值' }) current: number = 100;
@BlueprintProperty({ displayName: '最大生命值' }) max: number = 100;
@BlueprintMethod({ displayName: '治疗' }) heal(amount: number): void { this.current = Math.min(this.current + amount, this.max); }
@BlueprintMethod({ displayName: '受伤' }) takeDamage(amount: number): boolean { this.current -= amount; return this.current <= 0; }}
// 2. 初始化游戏async function initGame() { const scene = new Scene();
// 添加蓝图系统 scene.addSystem(new BlueprintSystem());
Core.setScene(scene);
// 3. 创建玩家 const player = scene.createEntity('Player'); player.addComponent(new PlayerComponent()); player.addComponent(new HealthComponent());
// 添加蓝图控制 const blueprint = new BlueprintComponent(); blueprint.blueprintAsset = await loadBlueprintAsset('player.blueprint.json'); player.addComponent(blueprint);}自定义节点示例
Section titled “自定义节点示例”import type { Entity } from '@esengine/ecs-framework';import { BlueprintNodeTemplate, BlueprintNode, ExecutionContext, ExecutionResult, INodeExecutor, RegisterNode} from '@esengine/blueprint';
// 自定义伤害节点const ApplyDamageTemplate: BlueprintNodeTemplate = { type: 'ApplyDamage', title: 'Apply Damage', category: 'combat', color: '#aa2222', description: '对带有 Health 组件的实体造成伤害', keywords: ['damage', 'hurt', 'attack'], menuPath: ['Combat', 'Apply Damage'], inputs: [ { name: 'exec', type: 'exec', displayName: '' }, { name: 'target', type: 'entity', displayName: '目标' }, { name: 'amount', type: 'float', displayName: '伤害量', defaultValue: 10 } ], outputs: [ { name: 'exec', type: 'exec', displayName: '' }, { name: 'killed', type: 'bool', displayName: '已击杀' } ]};
@RegisterNode(ApplyDamageTemplate)class ApplyDamageExecutor implements INodeExecutor { execute(node: BlueprintNode, context: ExecutionContext): ExecutionResult { const target = context.evaluateInput(node.id, 'target', context.entity) as Entity; const amount = context.evaluateInput(node.id, 'amount', 10) as number;
if (!target || target.isDestroyed) { return { outputs: { killed: false }, nextExec: 'exec' }; }
const health = target.components.find(c => (c.constructor as any).__componentName__ === 'Health' ) as any;
if (health) { health.current -= amount; const killed = health.current <= 0; return { outputs: { killed }, nextExec: 'exec' }; }
return { outputs: { killed: false }, nextExec: 'exec' }; }}1. 使用片段复用逻辑
Section titled “1. 使用片段复用逻辑”// 将通用逻辑封装为片段const movementFragment = createFragment('Movement', { inputs: [{ name: 'speed', type: 'number', ... }], outputs: [{ name: 'position', type: 'vector2', ... }], graph: { ... }});
// 通过组合器构建复杂蓝图const composer = createComposer('Player');composer.addFragment(movementFragment, 'movement');composer.addFragment(combatFragment, 'combat');2. 合理使用变量作用域
Section titled “2. 合理使用变量作用域”// local: 临时计算结果{ name: 'tempValue', scope: 'local' }
// instance: 实体状态(如生命值){ name: 'health', scope: 'instance' }
// global: 游戏全局状态{ name: 'score', scope: 'global' }3. 避免无限循环
Section titled “3. 避免无限循环”// VM 有每帧最大执行步数限制(默认 1000)// 使用 Delay 节点打断长执行链vm.maxStepsPerFrame = 1000;4. 调试技巧
Section titled “4. 调试技巧”// 启用调试模式查看执行日志const blueprint = entity.getComponent(BlueprintComponent);blueprint.debug = true;
// 使用 Print 节点输出中间值// 在编辑器中设置断点5. 性能优化
Section titled “5. 性能优化”// 纯节点的输出会被缓存{ isPure: true }
// 避免在 Tick 中执行重计算// 使用事件驱动而非轮询