| source |
|---|
Extends DisposableObject
The core class for creating new types of components and attaching functionality to entities in a world.
export declare abstract class Component<TComponent = ComponentWithConstructor<Record<string, unknown>>, TSerializableState extends SerializableState = SerializableState> implements DisposableObject In the following example, the NpcItem class extends the Component class to define a new type of component. The new component type is then registered so new instances of the NpcItem can be created in the world.
import * as hz from 'horizon/core';
class NpcItem extends hz.Component<typeof NpcItem> {
static propsDefinition = {};
start() {}
}
hz.Component.register(NpcItem);The Component class is an abstract class that you can extend to create new types of components that add properties and functionality to entities in your world. It provides properties and methods that manage the lifecycle of components, their relationship with attached entities, internal component data, and access to events including code block events.
When you create a new component in Desktop Editor, the editor generates a script that includes the following elements:
Component.propsDefinition - Defines internal properties for the class, which are also added to the Properties panel in Desktop Editor.
Component.start() - The method that executes when the class initially loads. This is where you can add event listeners that need to run when the script starts running.
Component.register() - The method that registers the new component class as a component definition that can be used to generate instances of the component in your world.
For more information about using components, see the Intro to Scripting tutorial, and the TypeScript Components, Properties, and Variables guide.
A set of asynchronous helper functions that are scoped to the component for automatic cleanup on dispose.
Signature
async: {
setTimeout: (callback: TimerHandler, timeout?: number, ...args: unknown[]) => number;
clearTimeout: (id: number) => void;
setInterval: (callback: TimerHandler, timeout?: number, ...args: unknown[]) => number;
clearInterval: (id: number) => void;
};Remarks
setTimeout - Sets a timer that executes a function or specified piece of code once the timer expires.clearTimeout - Cancels a timeout previously established by calling setTimeout().setInterval - Repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.clearInterval - Cancels a timed-repeating action that was previously established by a call to setInterval.
The entity the component is attached to.
Signature
readonly entity: Entity;The ID of the entity the component is attached to.
Signature
readonly entityId: number;The properties that modify the component.
Signature
readonly props: GetPropsFromComponentOrPropsDefinition<TComponent>;The set of properties that define the available input and default values of the component.
Signature
static propsDefinition: {};The World instance that contains the component.
Signature
readonly world: World;Called when receiving the specified CodeBlockEvent instance from the Player or Entity object.
Signature
connectCodeBlockEvent<TEventArgs extends BuiltInVariableType[], TCallbackArgs extends TEventArgs>(target: Entity | Player, event: CodeBlockEvent<TEventArgs>, callback: (...payload: TCallbackArgs) => void): EventSubscription;Parameters
The entity or player to listen to.
event: CodeBlockEvent<TEventArgs>
The incoming CodeBlockEvent object.
callback: (...payload: TCallbackArgs) => void
Called when the event is received with any data as arguments.
Returns
Examples
This example demonstrates how to receive a built-in CodeBlock event using the connectCodeBlockEvent method.
// Import CodeBlockEvents to access Built-in Events.
import { Component, CodeBlockEvents, Player } from 'horizon/core';
class BuiltInEventExample extends Component {
start() {
this.connectCodeBlockEvent(
this.entity,
CodeBlockEvents.OnIndexTriggerDown,
(player: Player) => {
// Perform an action when the Index Trigger is pressed.
}
);
this.connectCodeBlockEvent (
this.entity,
CodeBlockEvents.OnGrabEnd,
(player: Player) => {
// Perform another action when the Grab Action ends.
}
);
}
}
Component.register(BuiltInEventExample);Remarks
This method is used to listen for a given code block event sent from the player or an entity.
Adds a listener to the specified local event. The listener is called when the event is received.
Signature
connectLocalBroadcastEvent<TPayload extends LocalEventData>(event: LocalEvent<TPayload>, listener: (payload: TPayload) => void): EventSubscription;Parameters
event: LocalEvent<TPayload>
The local event to listen to.
listener: (payload: TPayload) => void
Called when the event is received with any data as arguments.
Returns
Adds a listener to the local event on the given entity. The listener is called when the event is received.
Signature
connectLocalEvent<TPayload extends LocalEventData>(target: Entity | Player, event: LocalEvent<TPayload>, callback: (payload: TPayload) => void): EventSubscription;Parameters
The entity to listen to.
event: LocalEvent<TPayload>
The local event.
callback: (payload: TPayload) => void
Called when the event is received with any data as arguments.
Returns
Adds a listener to the specified network event. The listener is called when the event is received from the network.
Signature
connectNetworkBroadcastEvent<TPayload extends NetworkEventData>(event: NetworkEvent<TPayload>, callback: (payload: TPayload) => void): EventSubscription;Parameters
event: NetworkEvent<TPayload>
The network event to listen to.
callback: (payload: TPayload) => void
Called when the event is received with any data as arguments.
Returns
Adds a listener to the specified network event on the given entity. The listener is called when the event is received from network.
Signature
connectNetworkEvent<TPayload extends NetworkEventData>(target: Entity | Player, event: NetworkEvent<TPayload>, callback: (payload: TPayload) => void): EventSubscription;Parameters
The entity or player to listen to.
event: NetworkEvent<TPayload>
The network event.
callback: (payload: TPayload) => void
Called when the event is received with any data as arguments.
Returns
Called when the component is cleaned up.
Signature
dispose(): void;Returns
void
Remarks
Subscriptions registered using , , , and are cleaned up automatically.
Returns a list of all script component instances of the specified type in the world. Only returns script component instances if they're executing in the same context (i.e. On the server or on a particular client). This method should not be used in prestart() as other script component instances may not yet be instantiated.
Signature
static getComponents<T extends Component<unknown, SerializableState> = Component>(type: new () => T): T[];Parameters
type: new () => T
The specified type of Component.
Returns
T[]
A list of all active instances of the specified component type in the current execution context (i.e., on the server or on a particular client).
Performs initialization tasks before the method is called.
Signature
preStart(): void;Returns
void
Remarks
This method runs in these scenarios as follows:World start: preStart runs for all components before the start method of any component is called. Asset spawn: preStart runs before any start methods are called for any components that are spawning. Ownership transfer: preStart is called directly before the start method is called.
Called when the script's ownership is being transferred to a new player. This method allows the new owner to receive the serializable state from the previous owner during ownership transfer.
Signature
receiveOwnership(_serializableState: TSerializableState | null, _oldOwner: Player, _newOwner: Player): void;Parameters
_serializableState: TSerializableState | null
The serializable state from prior owner, or null if that state is invalid.
_oldOwner: Player
The prior owner.
_newOwner: Player
The current owner.
Returns
void
Examples
type State = {ammo: number};
class WeaponWithAmmo extends Component<typeof WeaponWithAmmo, State> {
static propsDefinition = {
initialAmmo: {type: PropTypes.Number, default: 20},
};
private ammo: number = 0;
start() {
this.ammo = this.props.initialAmmo;
}
receiveOwnership(state: State | null, fromPlayer: Player, toPlayer: Player) {
this.ammo = state?.ammo ?? this.ammo;
}
transferOwnership(fromPlayer: Player, toPlayer: Player): State {
return {ammo: this.ammo};
}
}Remarks
When changing entity ownership to a new player, you must transfer the state of the entity as well or the state will be lost. You can use the Component.transferOwnership() and Component.receiveOwnership() methods to transfer an entity's state to a new owner. For more information, see Maintaining local state on ownership change.If ownership for a parent entity changes, the ownership change doesn't automatically apply to any child entities.You must handle the edge case when the local state isn't transferred, such as the previous owner disconnecting from Horizon during a power or connectivity outage. In these cases, there's no guarantee that the entity's local state is transferred.The maximum size of state information that can be transferred is capped at 63kB. Transfers that are larger generate an error.
Registers a component class as a component definition that is used to instantiate components of the given type, which also allows them to be attached to entities.
Signature
static register<TComponentPropsDefinition>(componentClass: // this needs to be typed with the interface type so we know it can be instantiated (is not abstract)
ComponentWithConstructor<TComponentPropsDefinition> & typeof Component<ComponentWithConstructor<TComponentPropsDefinition>>, componentName?: string): void;Parameters
componentClass: ComponentWithConstructor<TComponentPropsDefinition> & typeof Component<ComponentWithConstructor<TComponentPropsDefinition>>
The component class to register.
componentName: string
(Optional) The name of component to display in the UI.
Returns
void
Examples
In this example, the NpcItem class is registered as a component definition.
hz.Component.register(NpcItem);Remarks
Component registry is required when you create new classes that extend the abstract Component class.
Called to register a single operation. The operation runs automatically when the component is disposed unless it is manually run or canceled before the component is disposed.
Signature
registerDisposeOperation(operation: DisposeOperation): DisposeOperationRegistration;Parameters
operation: DisposeOperation
A function called to perform a single dispose operation.
Returns
A registration object that can be used to manually run or cancel the operation before dispose.
Sends a code block event to the specified player or entity. These events are networked automatically, and sent and handled asynchronously.
Signature
sendCodeBlockEvent<TPayload extends BuiltInVariableType[]>(target: Entity | Player, event: CodeBlockEvent<TPayload>, ...args: TPayload): void;Parameters
The entity or player that receives the event.
event: CodeBlockEvent<TPayload>
The CodeBlockEvent that represents the event.
args: TPayload
The data to send with the event.
Returns
void
Sends a local event to all listeners.If a local event is sent, it is sent immediately. This function does not return until delivery completes.
Signature
sendLocalBroadcastEvent<TPayload extends LocalEventData, TData extends TPayload>(event: LocalEvent<TPayload>, data: TData): void;Parameters
event: LocalEvent<TPayload>
The local event to send.
data: TData
Returns
void
Sends a local event to a specific entity from the owner of the entity.
Signature
sendLocalEvent<TPayload extends LocalEventData, TData extends TPayload>(target: Entity | Player, event: LocalEvent<TPayload>, data: TData): void;Parameters
The entity that receives the event.
event: LocalEvent<TPayload>
The local event to send.
data: TData
Returns
void
Remarks
The event is sent immediately and this function does not return until delivery completes.
Broadcasts a network event. The event is only handled if the host listens to the event.
Signature
sendNetworkBroadcastEvent<TPayload extends NetworkEventData>(event: NetworkEvent<TPayload>, data: TPayload, players?: Array<Player>): void;Parameters
event: NetworkEvent<TPayload>
The network event to broadcast.
data: TPayload
The data to send with the event. the maximum amount data supported after serialization is 63kB.
players: Array<Player>
(Optional) The list of players devices to send the event to. If you do not specify this parameter, the event is sent to all devices owned by the player. You should only use this parameter if you are familiar with how it works.
Returns
void
Sends a network event to the player that owns the given entity.
Signature
sendNetworkEvent<TPayload extends NetworkEventData>(target: Entity | Player, event: NetworkEvent<TPayload>, data: TPayload, players?: Array<Player>): void;Parameters
The player or entity that recieves the event.
event: NetworkEvent<TPayload>
The network event.
data: TPayload
The data to send with the event. the maximum amount data after serialization is 63kB.
players: Array<Player>
(Optional) The list of player devices to send the event to. If you don't specify this parameter, the event is sent to all devices owned by the player. You should only use specify this parameter if you understand it well.
Returns
void
Remarks
The event is only handled if is called on the same entity on the owner client.
Called when the component starts running. This is where you can add event listeners that need to run when the script starts running.
Signature
abstract start(): void;Returns
void
Called when transferring the script's ownership to a new player. During the transer, this method can condense the previous owner's state into a serializable format and pass it to the new owner.
Signature
transferOwnership(_oldOwner: Player, _newOwner: Player): TSerializableState;Parameters
_oldOwner: Player
The original owner.
_newOwner: Player
The new owner.
Returns
TSerializableState
The serializable state to transfer to the new owner.
Examples
type State = {ammo: number};
class WeaponWithAmmo extends Component<typeof WeaponWithAmmo, State> {
static propsDefinition = {
initialAmmo: {type: PropTypes.Number, default: 20},
};
private ammo: number = 0;
start() {
this.ammo = this.props.initialAmmo;
}
receiveOwnership(state: State | null, fromPlayer: Player, toPlayer: Player) {
this.ammo = state?.ammo ?? this.ammo;
}
transferOwnership(fromPlayer: Player, toPlayer: Player): State {
return {ammo: this.ammo};
}
}Remarks
When changing entity ownership to a new player, you must transfer the state of the entity as well or the state will be lost. You can use the Component.transferOwnership() and Component.receiveOwnership() methods to transfer an entity's state to a new owner. For more information, see Maintaining local state on ownership change.If ownership for a parent entity changes, the ownership change doesn't automatically apply to any child entities.You must handle the edge case when the local state isn't transferred, such as the previous owner disconnecting from Horizon during a power or connectivity outage. In these cases, there's no guarantee that the entity's local state is transferred.The maximum size of state information that can be transferred is capped at 63kB. Transfers that are larger generate an error.