Home >Web Front-end >JS Tutorial >Building a Game with Three.js, React and WebGL

Building a Game with Three.js, React and WebGL

Jennifer Aniston
Jennifer AnistonOriginal
2025-02-16 11:33:09589browse

Building a Game with Three.js, React and WebGL

Core points

  • Using React to drive 3D scenes in game development has many advantages, including clear separation of scene rendering from game logic, easy-to-understand components, real-time reloading of game resources, and the ability to use native browser tools to 3D scenes Check and debug as markers.
  • react-three-renderer (R3R) provides a declarative API that encapsulates Three.js, allows decoupling view code from game logic, and creates small, easy-to-understand components.
  • As game engines grow, it is crucial to use reducer mode to organize game logic into separate functions. This mode allows creating a clean and clear game loop and easily add more logic to the game loop.
  • Draining and performance considerations are unique in building games using Three.js, React and WebGL. Using Chrome DevTools' timeline functionality is invaluable for debugging performance, and implementing strategies such as minimizing the number of re-renders in React can help optimize performance.

I am making a game called "Chameleon Charm". It is built using Three.js, React and WebGL. This article describes how these technologies work together using react-three-renderer (abbreviated as R3R).

Please check out the WebGL Getting Started Guide and the React and JSX Getting Started Guide on SitePoint for an introduction to React and WebGL. This article and the accompanying code use ES6 syntax.

Building a Game with Three.js, React and WebGL

The beginning of everything

A while ago, Pete Hunt made a joke in the #reactjs IRC channel, saying that he would use React to create a game:

I bet we can make a first-person shooter with React! The enemy has

etc. I smiled. He laughed, too. Everyone had a great time. "Who in the world would do this?" I thought.

A few years later, I did exactly this.

Building a Game with Three.js, React and WebGL

Chameleon Charm is a game that collects enhanced props that will allow you to narrow down to solve the infinite fractal maze. I've been working as a React developer for a few years and I'm curious to know if there is a way to use React to drive Three.js. At this time, R3R attracted my attention.

Why choose React?

I know what you are thinking: Why? Please let me explain. Here are some reasons to consider using React to drive 3D scenes:

  • The "Declarative" view allows you to clearly separate scene rendering from game logic.
  • Design easy-to-understand components such as <player></player>, <wall></wall>, <level></level>, and more.
  • "hot" (real-time) reload of game resources. Change textures and models and see their updates in the scene in real time!
  • Check and debug 3D scenes as tags using native browser tools such as Chrome Inspector.
  • Manage game resources in dependency graphs using Webpack, e.g. <texture require="" src="%7B"></texture>

Let's set up a scenario to see how this all works.

React and WebGL

I created a sample GitHub repository to work with this article. Clone the repository and run the code as in the README and continue learning. It features SitePointy 3D robot as the main character!

Building a Game with Three.js, React and WebGL

Warning: R3R is still in the testing phase. Its API is unstable and may change in the future. Currently it only processes a subset of Three.js. I found it complete enough to build a complete game, but your results may vary.

Organization view code

The main benefit of using React to drive WebGL is that our view code is decoupled from the game logic. This means that the entities we render are small and easy to understand components.

R3R exposes a declarative API that encapsulates Three.js. For example, we can write:

<code><scene>></scene>
  <perspectivecamera>    position={ new THREE.Vector3( 1, 1, 1 )
  />
>
</perspectivecamera></code>

Now we have an empty 3D scene with a camera. Adding a mesh to a scene is as simple as including a <mesh></mesh> component and giving it <geometry></geometry> is as easy as <material></material>.

<code><scene>></scene>
  …
  <mesh>></mesh>
    <boxgeometry></boxgeometry>      width={ 1 }
      height={ 1 }
      depth={ 1 }
    />
    <meshbasicmaterial></meshbasicmaterial>      color={ 0x00ff00 }
    />
>
</code>

Behind the scenes, this will create a THREE.Scene and automatically add a grid with THREE.BoxGeometry. R3R handles the differences between old scenes and any changes. If you add a new mesh to the scene, the original mesh will not be recreated. Just like using normal React and DOM, 3D scenes only update the differences.

Because we work in React, we can detach the game entity into the component file. The Robot.js file in the sample repository demonstrates how to represent a major role using pure React view code. It is a "stateless function" component, which means it does not save any local state:

<code>const Robot = ({ position, rotation }) => <group></group>  position={ position }
  rotation={ rotation }
>
  <mesh> rotation={ localRotation }></mesh>
    <geometryresource></geometryresource>      resourceId="robotGeometry"
    />
    <materialresource></materialresource>      resourceId="robotTexture"
    />
  >
>;
</code>

Now we will include <robot></robot> in our 3D scene!

<code><scene>></scene>
  …
  <mesh>></mesh>…>
  <robot></robot>    position={…}
    rotation={…}
  />
>
</code>

You can view more API examples on the R3R GitHub repository, or see the full sample settings in the included project.

Organizing game logic

The other half of the equation is to deal with game logic. Let's add some simple animations to our robot SitePointy.

Building a Game with Three.js, React and WebGL

How does traditional game loop work? They accept user input, analyze the old "world state", and return to the new world state for rendering. For convenience, let's store the "Game State" object in the component state. In a more mature project, you can move game state to Redux or Flux storage.

We will use the browser's requestAnimationFrame API callback to drive our game loop and run the loop in GameContainer.js. To animation the robot, let's calculate a new location based on the timestamp passed to requestAnimationFrame and then store the new location in the state.

<code><scene>></scene>
  <perspectivecamera>    position={ new THREE.Vector3( 1, 1, 1 )
  />
>
</perspectivecamera></code>

Calling setState() will trigger the re-render of the child component and update the 3D scene. We pass state from container component to demo component: <game></game>

<code><scene>></scene>
  …
  <mesh>></mesh>
    <boxgeometry></boxgeometry>      width={ 1 }
      height={ 1 }
      depth={ 1 }
    />
    <meshbasicmaterial></meshbasicmaterial>      color={ 0x00ff00 }
    />
>
</code>
We can apply a useful pattern to help organize this code. Updating the robot location is a simple time-based calculation. In the future, it may also consider previous robot locations from previous game states. A function that accepts some data, processes it, and returns new data is often called a reducer. We can abstract the moving code into a reducer function!

Now we can write a concise and clear game loop that contains only function calls:

<code>const Robot = ({ position, rotation }) => <group></group>  position={ position }
  rotation={ rotation }
>
  <mesh> rotation={ localRotation }></mesh>
    <geometryresource></geometryresource>      resourceId="robotGeometry"
    />
    <materialresource></materialresource>      resourceId="robotTexture"
    />
  >
>;
</code>
To add more logic to the game loop, such as handling physics, create another reducer function and pass it to the result of the previous reducer:

<code><scene>></scene>
  …
  <mesh>></mesh>…>
  <robot></robot>    position={…}
    rotation={…}
  />
>
</code>
As the growth of game engines, it becomes crucial to organize game logic into separate functions. Using reducer mode, this organization is very simple.

Resource Management

This is still an area of ​​development for R3R. For textures, you can specify a url property on the JSX tag. Using Webpack, you can ask for the local image path:

<code>// …
gameLoop( time ) {
  this.setState({
    robotPosition: new THREE.Vector3(
      Math.sin( time * 0.01 ), 0, 0
    )
  });
}
</code>
With this setting, if you change the image on disk, your 3D scene will be updated in real time! This is invaluable for fast iterating game design and content.

For other resources (such as 3D models), you still have to use Three.js' built-in loader (such as JSONLoader) to handle them. I've tried using a custom webpack loader to load 3D model files, but ended up with too much work and no benefit. It is easier to think of models as binary data and use a file loader to load them. This can still implement real-time overloading of model data. You can see this in the sample code.

Debug

R3R supports React developer tool extensions for Chrome and Firefox. You can check your scene like you would check a normal DOM! Hovering over elements in the inspector displays their bounding boxes in the scene. You can also hover over the texture definition to see which objects in the scene use these textures.

Building a Game with Three.js, React and WebGL

You can also join the react-three-renderer Gitter chat room for help in debugging the application.

Performance Precautions

When building Chameleon Charm, I encountered some performance issues that are unique to this workflow.

  • I use Webpack for a hot reload time of up to 30 seconds! This is because each overload has to write large resources to the package. The solution is to implement Webpack's DLLPlugin, which reduces the reload time to less than 5 seconds.
  • Ideally, your scene should be called only once per frame of rendering. After analyzing my game, React itself is the main bottleneck. Calling setState() multiple times per frame will result in double rendering and degrade performance. setState()
  • After exceeding a certain number of objects, R3R's performance will be worse than ordinary Three.js code. To me, it's about 1000 objects. You can compare R3R with Three.js in the "Benchmark" in the example.
Chrome DevTools' timeline functionality is an excellent tool for debugging performance. You can easily and intuitively check the game loop, and it's easier to read than DevTools' "Profile" feature.

That's it!

Check out Chameleon Charm to learn what you can do with this setting. While this toolchain is still young, I found that using R3R's React is crucial to clearly organize my WebGL game code. You can also check out the small but growing R3R sample page to see some well-organized code examples.

This article was peer-reviewed by Mark Brown and Kev Zettler. Thanks to all the peer reviewers at SitePoint for getting SitePoint content to its best!

FAQ for Building Games with ReactJS and WebGL

What are the prerequisites for building games with ReactJS and WebGL?

To start building games with ReactJS and WebGL, you need a basic understanding of JavaScript, HTML, and CSS. Also need to know ReactJS (a popular JavaScript library for building user interfaces). In addition, it is crucial to understand WebGL (Web Graphics Library), a JavaScript API for rendering interactive 3D and 2D graphics. It will also be of great benefit to be familiar with ES6 syntax, npm (Node package manager) and command line.

How to integrate Unity with ReactJS?

Unity can be integrated with ReactJS using the react-unity-webgl package. This package allows you to embed Unity WebGL builds into ReactJS applications. You can install it using npm and import it into your project. You can then use the Unity component provided by the package to embed your Unity game into your ReactJS application.

What are the different ways to create 3D applications using React?

There are several ways to create a 3D application using React. One of the most popular methods is to use Three.js, a cross-browser JavaScript library for creating and displaying animated 3D computer graphics. Another approach is to use WebGL directly, but this may be more complicated. Other libraries such as react-three-fiber and react-unity-webgl can also be used to create 3D applications using React.

How to create interactive 3D graphics using WebGL?

WebGL allows you to create interactive 3D graphics directly in your browser, without plug-ins. You can use WebGL's API to create complex 3D graphics, animations, and games. However, WebGL's API is low-level and it can be complicated to use directly. Therefore, many developers prefer to use libraries like Three.js that provide a higher level of interface to WebGL.

What is the role of react-unity-webgl in game development?

react-unity-webgl package allows you to embed Unity WebGL builds into ReactJS applications. This means you can create complex 3D games with Unity and then easily integrate them into your ReactJS application. This is especially useful if you want to create a web-based game or interactive 3D application.

How to optimize my ReactJS and WebGL games for performance?

Optimizing games built with ReactJS and WebGL may involve multiple strategies. These strategies include minimizing the number of rerenders in React, using WebGL's built-in performance features such as requestAnimationFrame to achieve smooth animations, and optimizing 3D models and textures for the web.

Can I build mobile games using ReactJS and WebGL?

Yes, you can use ReactJS and WebGL to build games running in a web browser on your mobile device. However, for native mobile games, you may want to consider using game development platforms like Unity or Unreal Engine, which can be exported directly to iOS and Android.

How to process user input in my ReactJS and WebGL games?

User input can be processed in ReactJS and WebGL games using standard JavaScript event handlers. You can listen to keyboard, mouse, and touch events and then update the game status accordingly. ReactJS also provides synthesis events that can be used to process user input across different browsers in a consistent manner.

Can I use other JavaScript libraries with ReactJS and WebGL?

Yes, you can use other JavaScript libraries with ReactJS and WebGL. For example, you might use Three.js for 3D graphics, Howler.js for audio, or Matter.js for physical processing. The key is to make sure these libraries work seamlessly in your game.

How to debug my ReactJS and WebGL games?

Games built using ReactJS and WebGL can be debugged using developer tools in a web browser. These tools allow you to check HTML, CSS, and JavaScript code, view console logs, and debug the code step by step. Additionally, React Developer Tools is a browser extension that allows you to check React component hierarchy, props, and state.

The above is the detailed content of Building a Game with Three.js, React and WebGL. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn