Skip to content
Interactor

Interactor

INFO

It takes about 10 minutes to read this article Adding objects that characters can interact with in a project can effectively improve the immersiveness of the game and increase the vitality of the world of the game. [Interactor] can add the ability to interact with characters to the objects of a scene and define different interaction behaviors and interaction parts.

Interactor is a logical object that gives objects within a scene the ability to interact with characters. You can customize the transform property of an interaction to control the position of the interaction and set the orientation to specify the direction in which the interaction occurs. When the character interacts with the interactor, the character switches to the specified interaction pose, moves to the interaction position and welds to the Interactor. Characters that are in the interactor are no longer controlled by the input, but instead indirectly controls the character it is interacting with by controlling the interactor. Interactor provides delegated events of key nodes for the user to execute the corresponding game logic. You can find the “Interactor” in the "Gameplay Object" section of the "Asset library".

image-20240827163412401

Creating Interactor

Create by placing asset:

Interactor itself can be placed in a game scene as a game object. You can create objects by dragging [Interactor] into [Main Viewport] or [Object Manager] from the [Gameplay Object] in the [asset library].

  1. You can find the Anchor in the "Gameplay Object" section of the "Asset library".

image-20240827163423761

  1. Drag the object into the scene or [Object Manager]

image-20240827165749237

  1. Find the corresponding Interactor object in the Object column in the Object Manager on the right and customize its properties

image-20240827163609062 image-20240827163618416

Created from script:

By script you can also pass the asset ID of Interactor,”Interactor”, in [asset library] when the game is running, "dynamically generates an [Interactor] object to use. Create a new script file in the script directory under Project Content and drag the script into the Object column in Object Manager. Select the script for editing and replace the onStart method in the script with the following sample code: asynchronously generate an [Interactor] object, turn on double-ended synchronization at (300,0,50), rotate at (0,0,0), and scale by (1,1,1). Prints the gameObject ID of the generated interactor object.

TypeScript
if(SystemUtil.isServer()) {
    let chair = await GameObject.asyncSpawn("Interactor", {replicates: true, transform: new Transform(new Vector(300, 0, 50), Rotation.zero, Vector.one)}) as Interactor;
    console.log("Interactor: " + chair.gameObjectId);
}
if(SystemUtil.isServer()) {
    let chair = await GameObject.asyncSpawn("Interactor", {replicates: true, transform: new Transform(new Vector(300, 0, 50), Rotation.zero, Vector.one)}) as Interactor;
    console.log("Interactor: " + chair.gameObjectId);
}

TIP

An interactor can only interact with one character object at a time, and other characters cannot interact with an interactor when it is already in an interactive state. If an interaction request is initiated simultaneously then the first-to-arrive character can interact successfully.

Customize Interactor

The properties of an Interactor will together determine the specific performance of the Interaction, such as:

  • Interact slot (slot).
  • Interact animation (animation ID).

:::

In the [Object Manager], find the corresponding [Interactor] in the [Object] column. When selected, we can view its property panel. Through the property panel, we can modify some properties of the [interactor].

image-20240827163713861

Interact slot

The Interact Slot refers to the corresponding part of the character that interacts with the Interactor. It is readable and writable and is an enumeration of slots: 30 different slots are defined on the character depending on location. When an interaction occurs, the character slot coincides with the center of the Interactor and welds the character to the Interactor.

HairHeadLeft HeadRight HeadGlassesEyes
Face OrnamentalMouthLeft ShoulderRight ShoulderLeft GloveRight Glove
Back OrnamentalLeft BackRight BackLeft HandRight HandLeft Foot
Right FootButtocksOverhead RingsOverhead NameplateChat FrameRoot
Left ElbowRight ElbowLeft ThighRight ThighLeft KneeRight Knee
TypeScript
// Modify the interactive slot to Buttocks
let chair = this.gameObject as Interactor;
chair.interactiveSlot = HumanoidSlotType.Buttocks;
// Modify the interactive slot to Buttocks
let chair = this.gameObject as Interactor;
chair.interactiveSlot = HumanoidSlotType.Buttocks;

Interact Animation

The Interact Animation refers to the corresponding posture of the character after interacting with the Interactor. Animation asset used by Interactor are stored in the asset library. The property is readable and writable, but modifying the value during interaction does not affect the character.

TypeScript
// modify Interact Animation to 122449: swing
chair.animationId = "122449";
// modify Interact Animation to 122449: swing
chair.animationId = "122449";

TIP

Because Interact Animation belong to an animation asset, it is necessary to ensure that the asset is loaded before using Interactor. Asset can be loaded in advance by preloading or priority loading. If the asset is not ready, the Interact Animation may not be displayed.

Using Interactor

Get Interactor Object

[Interactor] object under [Object] column in [Object Manager]:

Use the asyncFind interface to get via the GameObject ID of the [Interactor] object:

  1. Select [Interactor] object and right-click [Copy GameObject ID] to get its GameObject ID. Note here the distinction between the Asset ID of the Interactor asset and the GameObject ID of the Interactor object.

image-20240827164004503

  1. Drag the script under the Object Manager and replace the onStart method in the script with the following code: The code will asynchronously find the object corresponding to the ID and receive it as an [Interactor] object.
TypeScript
protected async onStart(): Promise<void> {
    let chair = await GameObject.asyncFind("1148C8C5") as Interactor;
    console.log("chair gameObjectId " + chair.gameObjectId);
}
protected async onStart(): Promise<void> {
    let chair = await GameObject.asyncFind("1148C8C5") as Interactor;
    console.log("chair gameObjectId " + chair.gameObjectId);
}
  1. Mount the script below the Interactor object

image-20240827164102393 dw

  1. Add the following code to the script's onStart method: The code gets the script-mounted object and receives it as an [Interactor] object
TypeScript
let chair = this.gameObject as Interactor;
let chair = this.gameObject as Interactor;

Dynamically generate [Interactor] object:

Replace the onStart method in the script with the following sample code: The sample code asynchronously generates a corresponding Interactor object on the client side using the asyncSpawn interface (in which the resource ID of the Interactor is passed in).

TypeScript
protected async onStart(): Promise<void> {
    if(SystemUtil.isServer()) {
    let chair = await GameObject.asyncSpawn("Interactor", {replicates: true, transform: new Transform(new Type.Vector(300, 0, 50), Type.Rotation.zero, Type.Vector.one)}) as Interactor;
    console.log("Interactor gameObjectId: " + chair.gameObjectId);
    }
}
protected async onStart(): Promise<void> {
    if(SystemUtil.isServer()) {
    let chair = await GameObject.asyncSpawn("Interactor", {replicates: true, transform: new Transform(new Type.Vector(300, 0, 50), Type.Rotation.zero, Type.Vector.one)}) as Interactor;
    console.log("Interactor gameObjectId: " + chair.gameObjectId);
    }
}

Get the status of the Interactor

[Interactor] has two states:" interaction"and "idle", the two states are mutually exclusive. The status is obtained by occupied and returns a boolean value: true for "interactive" and false for "idle." The game usually gets the status of the Interactor in real time to execute the corresponding game logic.

TypeScript
let chair = this.gameObject as Interactor;
console.log("Interactive Current Status:" + chair.occupied);
let chair = this.gameObject as Interactor;
console.log("Interactive Current Status:" + chair.occupied);

Get character in Interaction

character that are interacting with [Interactor] can be obtained by getCurrentCharacter(). This function returns a character object,or return a null value if the Interactive is not currently interacting with the character.

TypeScript
let chair = this.gameObject as Interactor;
console.log("Interactive Current Interactive Character:" + chair.getCurrentCharacter()? chair.getCurrentCharacter().gameObjectId: "None");
let chair = this.gameObject as Interactor;
console.log("Interactive Current Interactive Character:" + chair.getCurrentCharacter()? chair.getCurrentCharacter().gameObjectId: "None");

Start Interaction & End Interaction

You can start interacting with the Interactor via the enter interface. The enter interface requires that a character object be passed in, along with 2 optional parameters: an interact slot and an interact animation. If optional parameters are not passed in then the Interactor property itself is used to perform the interactive behavior. Before performing a specific interaction, the interactor records the current character coordinates for use when exiting the interaction.

Exit interaction with [Interactor] via the leave interface. The leave interface has 3 optional parameters: exit coordinates, exit orientation, and exit animation. You can specify the position and pose of the character after exiting the Interactor. If no parameters are passed in, then the character refreshes to its pre-interaction position and faces directly in front of the Interactor, applying the default posture of the character.

The following example shows the character interacting with a chair. Make a chair in [Object Manager] first: drag [Interactive] into the scene and set the interactive animation to "Sit down and play with your phone" and the interactive slot to "Buttock." Mount the chair model below and modify to the appropriate relative position. Mount the script below the Interactive and add the code to the script onStart method. The code gets the mounted Interactive object and adds 2 key methods. Each time the keyboard "1" key is pressed, the startInteract interface is called to interact with the Interactive object. Each time the keyboard "2" key is pressed, the endInteract interface is called to exit the interaction with the Interactive.

image-20240827165706221

TypeScript
let chair = this.gameObject as Interactor;

if(SystemUtil.isClient()) {

    let myself = Player.localPlayer.character;

    InputUtil.onKeyDown(Type.Keys.One, () => {
        chair.enter(myself);
    :::

    InputUtil.onKeyDown(Type.Keys.Two, () => {
        chair.leave(chair.worldLocation.add(new Type.Vector(100, 0, 0)), chair.worldRotation);
    :::
}
let chair = this.gameObject as Interactor;

if(SystemUtil.isClient()) {

    let myself = Player.localPlayer.character;

    InputUtil.onKeyDown(Type.Keys.One, () => {
        chair.enter(myself);
    :::

    InputUtil.onKeyDown(Type.Keys.Two, () => {
        chair.leave(chair.worldLocation.add(new Type.Vector(100, 0, 0)), chair.worldRotation);
    :::
}

TIP

Player-controlled characters are recommended to call the start & end interaction interface on the corresponding client, while the rest of the NPC characters need to call the corresponding function on the server, which makes the use more stable and reliable and unaffected by network communication.

interaction event

[Interactor] There are two events: the start interaction completion event and the exit interaction completion event. After obtaining the [Interactor] object. We can add logic for delegate execution through these two events. Whenever the interaction reaches a corresponding stage, the corresponding event is triggered and the logic of the delegate is executed.

Adding the following sample code to the Start Interaction & End Interaction example, and place it after the code in the Get Objects section: The sample code adds a function to each of the Start Interaction Completion event and Exit Interaction Completion event for the Interactive object: Print a line of information.

TypeScript
chair.onEnter.add(() => {
    console.log("onInteractiveStarted");
:::

chair.onLeave.add(() => {
    console.log("onInteractiveEnded");
:::
chair.onEnter.add(() => {
    console.log("onInteractiveStarted");
:::

chair.onLeave.add(() => {
    console.log("onInteractiveEnded");
:::

TIP

The delegate event should ideally be consistent with the interface caller of the Interactor, for example, for player characters it is recommended to add delegate functions on the client side, while for NPCs it is recommended to go to the server side and add delegate functions. This ensures stable synchronization of attributes of the state.