【Laya】Component 使用说明
Laya.Component组件使用摘要(148字): Laya.Component是LayaAir引擎中所有组件的基类,用于扩展节点功能。组件生命周期包括onAdded(添加时)、onAwake(激活时)、onEnable/onDisable(启用/禁用时)、onUpdate(每帧更新)和onDestroy(销毁时)等方法。开发者可通过继承Component创建自定义组件,使用addCompon
·
Laya.Component 使用说明
简介
Laya.Component 是所有组件的基类,是 LayaAir 引擎中实现游戏逻辑的核心机制。通过将功能封装为组件并附加到节点上,可以灵活地构建复杂的游戏对象。
组件系统的优势:
- 模块化:每个组件负责单一功能
- 可复用:同一组件可添加到多个节点
- 可组合:通过组合不同组件实现复杂行为
- 易维护:组件之间相对独立,便于调试
常见组件类型:
- 脚本组件(
Laya.Script) - 渲染组件(
MeshRenderer、Sprite2D) - 物理组件(
Rigidbody3D、Collider) - 动画组件(
Animator)
目录
API 参考
属性
| 属性 | 类型 | 只读 | 说明 |
|---|---|---|---|
owner |
Laya.Node |
✅ | 组件所属的节点 |
enabled |
boolean |
❌ | 是否启用组件 |
destroyed |
boolean |
✅ | 是否已销毁 |
awaked |
boolean |
✅ | 是否已执行过 onAwake |
id |
number |
✅ | 唯一标识 ID |
方法
| 方法 | 返回值 | 说明 |
|---|---|---|
destroy() |
void |
销毁组件 |
hasHideFlag(flag: number) |
boolean |
检查是否有指定的隐藏标志 |
生命周期方法
| 方法 | 调用时机 |
|---|---|
onAdded() |
被添加到节点后调用(即使节点未激活) |
onAwake() |
组件被激活后执行,此时所有节点和组件均已创建完毕,只执行一次 |
onStart() |
第一次执行 update 之前执行,只会执行一次 |
onEnable() |
组件被启用后执行 |
onDisable() |
组件被禁用时执行 |
onUpdate() |
每帧更新时执行 |
onLateUpdate() |
每帧更新后执行 |
onPreRender() |
渲染前执行 |
onDestroy() |
组件销毁时调用 |
组件生命周期
生命周期流程图
┌─────────────┐
│ onAdded() │ 添加到节点时
└──────┬──────┘
│
▼
┌─────────────┐
│ onAwake() │ 只执行一次
└──────┬──────┘
│
▼
┌─────────────┐
│ onStart() │ 只执行一次
└──────┬──────┘
│
▼
┌──────────────┴──────────────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ onEnable() │◄────────────►│ onDisable() │
└──────┬───────┘ └──────────────┘
│
▼
┌──────────────┐
│ onUpdate() │◄────── 每帧循环
└──────┬───────┘
│
▼
┌──────────────┐
│onLateUpdate() │
└──────┬───────┘
│
▼
┌──────────────┐
│ onPreRender() │
└──────────────┘
销毁时: onDestroy()
生命周期详解
| 阶段 | 方法 | 说明 |
|---|---|---|
| 初始化 | onAdded() |
组件被添加到节点时调用,此时可能无法访问其他组件 |
onAwake() |
所有节点和组件创建完毕后调用,只执行一次,适合初始化 | |
onStart() |
第一次更新前执行,适合获取其他组件的引用 | |
| 运行时 | onEnable() |
组件启用时调用 |
onUpdate() |
每帧调用,用于游戏逻辑更新 | |
onLateUpdate() |
每帧更新后调用,适合处理相机跟随等 | |
onPreRender() |
渲染前调用 | |
| 清理 | onDisable() |
组件禁用时调用 |
onDestroy() |
组件销毁时调用,释放资源 |
创建自定义组件
基本结构
const { regClass, property } = Laya;
@regClass()
export class MyComponent extends Laya.Component {
// @property 标记的属性可在编辑器中设置
@property(Number)
public speed: number = 10;
private _counter: number = 0;
onAwake(): void {
console.log("组件已激活,owner:", this.owner.name);
}
onUpdate(): void {
this._counter += Laya.timer.delta * 0.001;
}
onDestroy(): void {
console.log("组件已销毁");
}
}
继承 Script 类
Laya.Script 是 Laya.Component 的子类,专门用于编写游戏逻辑:
@regClass()
export class MyScript extends Laya.Script {
declare owner: Laya.Sprite; // 声明 owner 类型以便类型提示
onAwake(): void {
// this.owner 自动有类型提示
this.owner.x = 100;
}
}
组件管理
添加组件
// 方式一:添加组件并获取引用
const component = sprite.addComponent(MyComponent);
// 方式二:添加后获取
sprite.addComponent(MyComponent);
const component = sprite.getComponent(MyComponent);
// 设置组件属性
component.speed = 20;
获取组件
// 获取指定类型的组件(只获取第一个)
const myComponent = sprite.getComponent(MyComponent);
// 获取指定类型的所有组件
const components = sprite.getComponents(MyComponent);
// 获取节点及其父节点的组件
const parentComponent = sprite.getComponentInParent(MyComponent);
// 获取节点及其子节点的组件
const childComponent = sprite.getComponentInChildren(MyComponent);
移除组件
// 方式一:通过组件引用销毁
const component = sprite.getComponent(MyComponent);
if (component) {
component.destroy();
}
// 方式二:通过节点移除
sprite.removeComponent(MyComponent);
// 移除所有指定类型的组件
sprite.removeComponents(MyComponent);
启用/禁用组件
const component = sprite.getComponent(MyComponent);
// 禁用组件(会触发 onDisable)
component.enabled = false;
// 启用组件(会触发 onEnable)
component.enabled = true;
// 检查组件是否启用
if (component.enabled) {
// 组件处于启用状态
}
实用示例
示例1: 旋转组件
@regClass()
export class RotateComponent extends Laya.Component {
@property(Number)
public rotationSpeed: number = 90;
onUpdate(): void {
if (this.owner instanceof Laya.Sprite) {
const sprite = this.owner as Laya.Sprite;
const delta = Laya.timer.delta * 0.001;
sprite.rotation += this.rotationSpeed * delta;
}
}
}
// 使用
const sprite = new Laya.Sprite();
sprite.graphics.drawRect(-50, -50, 100, 100, "#4CAF50");
sprite.pos(400, 300);
sprite.pivotX = 50;
sprite.pivotY = 50;
const rotator = sprite.addComponent(RotateComponent);
rotator.rotationSpeed = 180;
Laya.stage.addChild(sprite);
示例2: 键盘移动控制
@regClass()
export class KeyboardMoveComponent extends Laya.Component {
@property(Number)
public moveSpeed: number = 200;
private _direction = { x: 0, y: 0 };
onAwake(): void {
Laya.stage.on(Laya.Event.KEY_DOWN, this, this.onKeyDown);
Laya.stage.on(Laya.Event.KEY_UP, this, this.onKeyUp);
}
private onKeyDown(e: Laya.Event): void {
const code = e["keyCode"];
switch (code) {
case 37: case 65: // 左箭头 / A
this._direction.x = -1;
break;
case 39: case 68: // 右箭头 / D
this._direction.x = 1;
break;
case 38: case 87: // 上箭头 / W
this._direction.y = -1;
break;
case 40: case 83: // 下箭头 / S
this._direction.y = 1;
break;
}
}
private onKeyUp(e: Laya.Event): void {
const code = e["keyCode"];
switch (code) {
case 37: case 39: case 65: case 68:
this._direction.x = 0;
break;
case 38: case 40: case 87: case 83:
this._direction.y = 0;
break;
}
}
onUpdate(): void {
if (this.owner instanceof Laya.Sprite) {
const sprite = this.owner as Laya.Sprite;
const delta = Laya.timer.delta * 0.001;
sprite.x += this._direction.x * this.moveSpeed * delta;
sprite.y += this._direction.y * this.moveSpeed * delta;
}
}
onDestroy(): void {
Laya.stage.offAllCaller(this);
}
}
示例3: 脉动缩放效果
@regClass()
export class PulseComponent extends Laya.Component {
@property(Number)
public scaleAmount: number = 0.2;
@property(Number)
public pulseSpeed: number = 3;
private _time: number = 0;
private _baseScale: number = 1;
onAwake(): void {
if (this.owner instanceof Laya.Sprite) {
this._baseScale = this.owner.scaleX;
}
}
onUpdate(): void {
this._time += Laya.timer.delta * 0.001;
const offset = Math.sin(this._time * this.pulseSpeed) * this.scaleAmount;
const scale = this._baseScale + offset;
if (this.owner instanceof Laya.Sprite) {
const sprite = this.owner as Laya.Sprite;
sprite.scaleX = scale;
sprite.scaleY = scale;
}
}
}
示例4: 生命值系统
/**
* 生命值组件
*/
@regClass()
export class HealthComponent extends Laya.Component {
@property(Number)
public maxHealth: number = 100;
public currentHealth: number = 100;
onAwake(): void {
this.currentHealth = this.maxHealth;
}
public takeDamage(damage: number): void {
this.currentHealth = Math.max(0, this.currentHealth - damage);
console.log("受到伤害:", damage, "剩余血量:", this.currentHealth);
if (this.currentHealth <= 0) {
this.owner.event("DEATH");
}
}
public heal(amount: number): void {
this.currentHealth = Math.min(this.currentHealth + amount, this.maxHealth);
console.log("恢复血量:", amount, "当前血量:", this.currentHealth);
}
}
/**
* 血条显示组件
*/
@regClass()
export class HealthBarComponent extends Laya.Component {
private _background: Laya.Sprite;
private _foreground: Laya.Sprite;
private _health: HealthComponent;
private _offsetY: number = -60;
onAwake(): void {
// 创建血条背景
this._background = new Laya.Sprite();
this._background.size(100, 10);
this._background.graphics.drawRect(0, 0, 1, 1, "#333333").percent = true;
this._background.pos(0, this._offsetY);
this._background.pivotX = 50;
// 创建血条前景
this._foreground = new Laya.Sprite();
this._foreground.size(100, 10);
this._foreground.graphics.drawRect(0, 0, 1, 1, "#FF0000").percent = true;
this._foreground.pos(0, this._offsetY);
this._foreground.pivotX = 50;
this.owner.addChild(this._background);
this.owner.addChild(this._foreground);
// 获取生命值组件
this._health = this.owner.getComponent(HealthComponent);
}
onUpdate(): void {
if (this._health) {
const percent = this._health.currentHealth / this._health.maxHealth;
this._foreground.width = 100 * percent;
}
}
onDestroy(): void {
this._background.destroy();
this._foreground.destroy();
}
}
// 使用示例
const player = new Laya.Sprite();
player.graphics.drawCircle(0, 0, 30, "#4CAF50");
player.pos(400, 300);
const health = player.addComponent(HealthComponent);
health.maxHealth = 100;
player.addComponent(HealthBarComponent);
player.on("DEATH", this, () => {
console.log("玩家死亡");
Laya.stage.removeChild(player);
});
Laya.stage.addChild(player);
// 模拟受伤
Laya.timer.once(2000, this, () => {
health.takeDamage(30);
});
示例5: 定时销毁
@regClass()
export class AutoDestroyComponent extends Laya.Component {
@property(Number)
public lifetime: number = 3; // 存活时间(秒)
private _elapsed: number = 0;
onUpdate(): void {
this._elapsed += Laya.timer.delta * 0.001;
if (this._elapsed >= this.lifetime) {
// 可以先播放销毁动画
this.owner.destroy();
}
}
}
// 使用:创建 3 秒后自动销毁的特效
const effect = new Laya.Sprite();
effect.graphics.drawCircle(0, 0, 20, "#FFD700");
effect.pos(400, 300);
const autoDestroy = effect.addComponent(AutoDestroyComponent);
autoDestroy.lifetime = 3;
Laya.stage.addChild(effect);
最佳实践
1. 使用 declare 声明 owner 类型
@regClass()
export class MyScript extends Laya.Script {
declare owner: Laya.Sprite; // 提供类型提示
onAwake(): void {
this.owner.x = 100; // 自动补全和类型检查
}
}
2. 在 onStart 中获取组件引用
@regClass()
export class MyComponent extends Laya.Component {
private _sprite: Laya.Sprite;
private _renderer: MeshRenderer;
onAwake(): void {
// 此时其他组件可能还未初始化
}
onStart(): void {
// 在 onStart 中获取其他组件更安全
this._sprite = this.owner as Laya.Sprite;
this._renderer = this.owner.getComponent(MeshRenderer);
}
}
3. 及时清理事件监听
@regClass()
export class MyComponent extends Laya.Component {
onAwake(): void {
Laya.stage.on(Laya.Event.CLICK, this, this.onClick);
}
onDestroy(): void {
// 销毁时移除监听,避免内存泄漏
Laya.stage.off(Laya.Event.CLICK, this, this.onClick);
}
private onClick(): void {
console.log("Clicked");
}
}
4. 使用 @property 暴露可配置属性
@regClass()
export class EnemyComponent extends Laya.Component {
@property(Number)
public maxHealth: number = 100;
@property(Number)
public moveSpeed: number = 100;
@property(Number)
public attackDamage: number = 10;
// 这些属性可在编辑器中设置,方便设计师调整
}
5. 组件间通信优先使用事件
// 好的做法:使用事件解耦
class HealthComponent extends Laya.Component {
takeDamage(damage: number): void {
this.currentHealth -= damage;
this.owner.event("HEALTH_CHANGED", [this.currentHealth]);
}
}
// 避免:直接调用其他组件
class HealthComponent extends Laya.Component {
takeDamage(damage: number): void {
this.currentHealth -= damage;
const bar = this.owner.getComponent(HealthBarComponent);
if (bar) bar.update(); // 耦合度高
}
}
6. 避免在 onUpdate 中创建对象
// ❌ 错误:每帧创建对象
onUpdate(): void {
const pos = new Laya.Vector2();
pos.x = this.owner.x;
pos.y = this.owner.y;
}
// ✅ 正确:复用对象
private _tempPos = new Laya.Vector2();
onUpdate(): void {
this._tempPos.x = this.owner.x;
this._tempPos.y = this.owner.y;
}
7. 检查组件是否已销毁
// 使用组件前检查
if (component && !component.destroyed) {
component.doSomething();
}
// 在异步操作中检查
onDestroy(): void {
Laya.timer.clear(this, this._timerHandle);
Laya.stage.offAllCaller(this);
}
注意事项
- 组件必须添加到节点:
owner属性只有在组件添加到节点后才有效 - 生命周期顺序:
onAwake→onStart→onEnable,其他组件的onAwake可能尚未执行 - 启用状态:
enabled = false会停止onUpdate等方法的调用 - 销毁检查:销毁后
destroyed为true,不应再访问组件属性 - 事件清理:在
onDestroy中移除所有事件监听 - 性能考虑:避免在
onUpdate中进行复杂计算或创建对象
相关文档
更多推荐


所有评论(0)