Script
We have introduced the Component in the Component Lifecycle, users can extend from ComponentBase class to develop custom components. Users can customize the running logic by overwriting the lifecycle functions of the component base class:
Initialize/stop
: likeinit
anddestroy
State change
: likestart
,onEnable
andonDisable
Update logic
: likeonUpdate
,onLateUpdate
andonBeforeUpdate
Basic Usage
Add a custom script to an entity
class Script extends ComponentBase {
//Overwrite init
public init() {
//This function is called when the component is created, and can be used to initialize internal variables
//Note that the component has not been mounted to the Object3D at this time, so it cannot be accessed by this.object3D
}
// Overwrite start
public start() {
// This function is called before the component starts rendering,
// At this time, you can access this.object3D to get the attributes of the node or other components
}
// Overwrite onUpdate
public onUpdate() {
// This function is called every frame rendering loop, usually defined the node's loop logic
// For example, update the rotation angle of the object every frame
this.object3D.rotationY += 1;
}
}
let ball: Object3D = new Object3D();
ball.addComponent(Script);
In a custom script, you can get the object3D
object which current component mounted through this.object3D
, and then change the object state.
A key point of game or animation development is to update the behavior, state and orientation of the object before each frame rendering. These update operations can usually be defined in the onUpdate
callback of the component itself. The engine will automatically register the onUpdate
callback to the main loop to achieve the update logic of each frame.
Examples
Here are three different script animation examples to show you more complex script component usage.
1. Light Animation Script Component
import { ComponentBase, Time, DirectLight, Color, LitMaterial, MeshRenderer, Scene3D, BoxGeometry, Object3D, Engine3D, Camera3D, HoverCameraController, View3D, AtmosphericComponent } from '@orillusion/core';
class LightAnimation extends ComponentBase {
private light: DirectLight;
private color: Color;
public start() {
this.light = this.object3D.getComponent(DirectLight);
this.color = this.light.lightColor;
}
public onUpdate() {
this.color.r = Math.pow(Math.sin(Time.time * 0.001), 10);
this.light.lightColor = this.color;
}
}
class UserLogic {
private scene: Scene3D;
private cube: Object3D;
private light: DirectLight;
init(scene3D: Scene3D) {
this.scene = scene3D;
this.createCube();
this.createLight();
this.createComponents();
}
private createCube() {
let mat = new LitMaterial();
mat.roughness = 1.0;
let obj: Object3D = new Object3D();
let geometry = new BoxGeometry(3, 3, 3);
let mr = obj.addComponent(MeshRenderer);
mr.material = mat;
mr.geometry = geometry;
this.scene.addChild(obj);
}
private createLight() {
let light: Object3D = new Object3D();
let component = light.addComponent(DirectLight);
light.rotationX = -45;
light.rotationZ = -45;
component.lightColor = new Color(1.0, 0, 0, 1);
component.intensity = 10;
this.scene.addChild(light);
this.light = component;
}
private createComponents() {
this.light.object3D.addComponent(LightAnimation);
}
async run() {
await Engine3D.init();
this.init(new Scene3D());
let cameraObj = new Object3D();
let camera = cameraObj.addComponent(Camera3D);
camera.perspective(60, Engine3D.aspect, 1, 5000.0);
let controller = camera.object3D.addComponent(HoverCameraController);
controller.setCamera(-135, 0, 15);
this.scene.addChild(cameraObj);
// add an Atmospheric sky enviroment
this.scene.addComponent(AtmosphericComponent).sunY = 0.6;
// create a view with target scene and camera
let view = new View3D();
view.scene = this.scene;
view.camera = camera;
// start render
Engine3D.startRenderView(view);
}
}
new UserLogic().run();
class LightAnimation extends ComponentBase {
private light: DirectLight;
private color: Color;
// Overwrite start initialize variables of start
protected start() {
this.light = this.object3D.getComponent(DirectLight);
this.color = this.light.lightColor;
}
onUpdate() {
// Update lightColor
this.color.r = Math.pow(Math.sin(Time.time * 0.001), 10);
this.light.lightColor = this.color;
}
}
Here we change the red component of the light color every frame, so that it changes with time, and finally produces the effect of light animation.
2. Material Animation Script Component
import { ComponentBase, Time, DirectLight, Color, LitMaterial, MeshRenderer, Scene3D, BoxGeometry, Object3D, Engine3D, Camera3D, HoverCameraController, BloomPost, View3D, AtmosphericComponent, PostProcessingComponent } from '@orillusion/core';
class MaterialAnimation extends ComponentBase {
private material: LitMaterial;
private time: number = 0;
start() {
let mr = this.object3D.getComponent(MeshRenderer);
this.material = mr.material as LitMaterial;
}
public onUpdate() {
let delta = Time.time * 0.001;
this.material.baseColor = new Color(Math.sin(delta), Math.cos(delta), Math.sin(delta));
}
}
class UserLogic {
private scene: Scene3D;
private cube: Object3D;
private light: DirectLight;
init(scene3D: Scene3D) {
this.scene = scene3D;
this.createCube();
this.createLight();
this.createComponents();
}
private createCube() {
let mat = new LitMaterial();
let obj: Object3D = new Object3D();
let geometry = new BoxGeometry(3, 3, 3);
let mr = obj.addComponent(MeshRenderer);
mr.material = mat;
mr.geometry = geometry;
this.cube = obj;
this.scene.addChild(obj);
}
private createLight() {
let light: Object3D = new Object3D();
let component = light.addComponent(DirectLight);
light.rotationX = 45;
light.rotationY = 30;
component.lightColor = new Color(1, 1, 1, 1);
component.intensity = 2;
this.scene.addChild(light);
this.light = component;
}
private createComponents() {
this.cube.addComponent(MaterialAnimation);
}
async run() {
await Engine3D.init();
this.init(new Scene3D());
let cameraObj = new Object3D();
let camera = cameraObj.addComponent(Camera3D);
camera.perspective(60, Engine3D.aspect, 1, 5000.0);
let controller = camera.object3D.addComponent(HoverCameraController);
controller.setCamera(45, 0, 15);
this.scene.addChild(cameraObj);
// add an Atmospheric sky enviroment
this.scene.addComponent(AtmosphericComponent).sunY = 0.6;
// create a view with target scene and camera
let view = new View3D();
view.scene = this.scene;
view.camera = camera;
// start render
Engine3D.startRenderView(view);
// add a bloom post
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(BloomPost);
}
}
new UserLogic().run();
class MaterialAnimation extends ComponentBase {
private material: LitMaterial;
// Overwrite start initialize variables of start
protected start() {
let mr = this.object3D.getComponent(MeshRenderer);
this.material = mr.material;
}
onUpdate() {
// Update baseColor
let delta = Time.time * 0.001
this.material.baseColor = new Color(Math.sin(delta), Math.cos(delta), Math.sin(delta));
}
}
Similar to above, we can change the material object of the object, such as changing the material color according to the time, so as to achieve the corresponding animation effect.
3. Path Animation Script Component
import { ComponentBase, Time, DirectLight, Color, LitMaterial, MeshRenderer, Scene3D, BoxGeometry, Object3D, Engine3D, Camera3D, HoverCameraController, View3D, AtmosphericComponent } from '@orillusion/core';
class PathAnimation extends ComponentBase {
onUpdate() {
this.object3D.x = Math.sin(Time.time * 0.001) * 2;
this.object3D.y = Math.cos(Time.time * 0.001) * 2;
}
}
class UserLogic {
private scene: Scene3D;
private cube: Object3D;
private light: DirectLight;
init(scene3D: Scene3D) {
this.scene = scene3D;
this.createCube();
this.createLight();
this.createComponents();
}
private createCube() {
let mat = new LitMaterial();
let obj: Object3D = new Object3D();
let geometry = new BoxGeometry(3, 3, 3);
let mr = obj.addComponent(MeshRenderer);
mr.material = mat;
mr.geometry = geometry;
this.scene.addChild(obj);
this.cube = obj;
}
private createLight() {
let light: Object3D = new Object3D();
let component = light.addComponent(DirectLight);
light.rotationX = 45;
light.rotationY = 30;
component.lightColor = new Color(1.0, 1.0, 0, 1);
component.intensity = 2;
this.scene.addChild(light);
this.light = component;
}
private createComponents() {
this.cube.addComponent(PathAnimation);
}
async run() {
await Engine3D.init();
this.init(new Scene3D());
let cameraObj = new Object3D();
let camera = cameraObj.addComponent(Camera3D);
camera.perspective(60, Engine3D.aspect, 1, 5000.0);
let controller = camera.object3D.addComponent(HoverCameraController);
controller.setCamera(45, 0, 15);
this.scene.addChild(cameraObj);
// add an Atmospheric sky enviroment
this.scene.addComponent(AtmosphericComponent).sunY = 0.6;
// create a view with target scene and camera
let view = new View3D();
view.scene = this.scene;
view.camera = camera;
// start render
Engine3D.startRenderView(view);
}
}
new UserLogic().run();
class PathAnimation extends ComponentBase {
onUpdate() {
// Update Position
this.object3D.x = Math.sin(Time.time * 0.001) * 2;
this.object3D.y = Math.cos(Time.time * 0.001) * 2;
}
}
In this case, we change the Position
property of the Object3D
object, so that the object moves in a circular motion on the xy
plane with time.