Game Development 21 min read

Building a 3D Incentive Game with Oasis Engine: From Concept to Optimization

This article details how a 3D interactive incentive game was created using Oasis Engine, covering scene architecture, ECS design, script development, collision handling, camera follow, skeletal and particle animations, shader effects, lane configuration, mobile orientation, performance optimizations, testing, deployment, and key lessons learned.

Alibaba Terminal Technology
Alibaba Terminal Technology
Alibaba Terminal Technology
Building a 3D Incentive Game with Oasis Engine: From Concept to Optimization

In recent years many businesses have added interactive mini‑games to boost user engagement. To explore the value of such games in B‑type scenarios, we built a 0‑to‑1 incentive game called "Yidatong Break‑Egg" using Oasis Engine, aiming to drive customers from onboarding to active usage.

Scene Analysis

The game UI is divided into three layers:

DOM UI layer : 2D UI elements such as score panels and game over screens, communicating with the 3D scene via events.

3D scene layer : Built with Oasis Engine and Oasis 3D Editor, rendered on a canvas.

Background layer : The sky‑sea backdrop placed at the bottom.

Note: Do not set the canvas background via CSS; instead set gl.clearColor to transparent and place a separate background layer to avoid scene overlap after the app goes to background on WeChat or Safari.

Implementing the 3D Scene

The development process follows the typical 3D pipeline: scene construction, script creation, and logic implementation.

Scene Construction

Using Oasis Editor’s visual editing, we assembled a scene tree where each entity is a collection of components (e.g., camera, model, scripts). The character entity loads a GLTF model exported from FBX, and custom script components encode game logic.

Scene hierarchy
Scene hierarchy

Script Development

Oasis Editor provides a cloud code editor and event panels. Scripts are created in the editor, then pulled locally with oasis pull -s (schema only) or oasis pull (full). The game uses Git for version control and isolates 3D communication logic from business‑specific features such as forced landscape, downgrade handling, and lane configuration.

Logic Development

1. Controlling Character Trajectory

Collision detection determines actions based on the character’s interaction with blue blocks. The first tap moves the character straight on the X‑axis; the second tap adds a Y component for a parabolic jump. Collision events begin_overlop and end_overlop trigger free‑fall or horizontal movement depending on relative positions.

const cd = this.entity.addComponent(o3.CollisionDetection);
cd.on("begin_overlop", e => {
  const colliderNode = e.collider._entity;
  const entityType = this.getEntityType(colliderNode);
  if (entityType === "reward") {
    const particleComponent = colliderNode.getComponent(o3.GPUParticleSystem);
    particleComponent && particleComponent.start();
    this.engine.dispatch("gotReward");
  }
});

2. Camera Follow

The camera follows the character from behind. To avoid jitter, the follow logic is placed in onLateUpdate, which runs after all onUpdate calls.

3. Skeletal Animation

Animations are exported from C4D as a single FBX, then split in Blender into separate clips (e.g., run, wave). Clip names are read from the GLTF animation property to play the correct sequence.

Animation clips
Animation clips

4. Particle Animation

Particle systems are configured in Oasis Editor. For the energy‑block explosion, initial velocities are zero, with random X/Y offsets and a slight negative Y acceleration to simulate gravity.

Particle system
Particle system
const cd = this.entity.addComponent(o3.CollisionDetection);
cd.on("begin_overlop", e => {
  const colliderNode = e.collider._entity;
  const entityType = this.getEntityType(colliderNode);
  if (entityType === "reward") {
    const particleComponent = colliderNode.getComponent(o3.GPUParticleSystem);
    particleComponent && particleComponent.start();
    this.engine.dispatch("gotReward");
  }
});

5. Shader Animation

When the character hits a red block, a shader‑based disappearance effect is applied (see the linked article for the full shader code).

6. Lane Configuration

Lane data is abstracted into boxsConfig and rewardsConfig structures, allowing easy cloning, dragging, and custom difficulty levels.

interface IGameConfig {
  boxsConfig: {
    name: string;
    position: { x: number; y: number; z: number; };
    action?: string[];
  }[];
  rewardsConfig: {
    name: string;
    position: { x: number; y: number; z: number; };
  }[];
}

7. Skinning

Before runtime, the schema.json is edited to replace texture assets, enabling dynamic skin changes.

Schema overview
Schema overview

8. Mobile Landscape Handling

The game runs in landscape mode. On orientation change, the container size is swapped and rotated 90°, with an offset to keep the canvas centered.

const clientWidth = document.documentElement.clientWidth;
const clientHeight = document.documentElement.clientHeight;
gameContainer.style.top = (clientHeight - clientWidth) / 2 + "px";
gameContainer.style.left = 0 - (clientHeight - clientWidth) / 2 + "px";

Optimizations

Canvas Energy‑Saving Mode

To balance clarity and performance on high‑DPI screens, the canvas width is set to clientWidth * devicePixelRatio / scale (scale ≈ 1.5).

Canvas scaling
Canvas scaling

Object Pool

Both blocks and energy blocks are pooled. Visible entities are fetched from the pool; out‑of‑view entities are returned, reducing GC pressure and draw calls.

Object pool diagram
Object pool diagram
getVisibleRewardConfig(positionX) {
  return this.rewardsConfig.filter(item => {
    const { position, entity } = item;
    if (position.x < positionX + SHOW_RANGE[0] && entity) {
      this.entityPool.putEntity(entity);
      item.entity = null;
    }
    return position.x >= positionX + SHOW_RANGE[0] && position.x <= positionX + SHOW_RANGE[1];
  });
}

Vertical Synchronization

Disabling VSync caused frame‑rate mismatches and visual tearing. Enabling VSync ensures the GPU waits for the display refresh before rendering the next frame.

WebGL Version Switching

On older Android DingTalk versions that crash with WebGL 2.0, the engine falls back to WebGL 1.0 by setting WebGLMode to WebGL1.

Deployment and R&D Reflections

The game is packaged as a reusable component that can be embedded with a simple canvas. Initialization code looks like:

const gameContainer = canvas.parentElement;
const oasis = await boot({
  canvas,
  gameContainer,
  level: 2,
  debug: false,
  handleDowngrade: () => { setDowngrade(true); }
});
const { engine } = oasis;
engine.dispatch("start");
engine.on("gotReward", () => setScore(x => x + 1));
engine.on("gameDie", () => {/* handle death */});
engine.on("gameOver", () => {/* handle finish */});

Key takeaways include the importance of early design‑to‑art handoff standards (e.g., avoid cameras in FBX, use power‑of‑two textures, limit triangle count to ~50k, merge materials, strip unused nodes), leveraging visual editors for rapid iteration, using Chrome’s Performance and SpectorJS tools for profiling, and establishing robust downgrade paths for devices lacking WebGL support.

Conclusion

Interactive 3D games significantly improve user retention and activation. The experience will feed into a broader user‑growth system that combines content marketing, incentive mechanisms, and technical capabilities. An open‑source release of Oasis 3D is scheduled for February 1st, streamed on B‑station.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

mobile performanceObject PoolingOasis Engine3D Game DevelopmentEntity Component SystemScene ArchitectureWebGL Optimization
Alibaba Terminal Technology
Written by

Alibaba Terminal Technology

Official public account of Alibaba Terminal

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.