游侠网云服务,免实名免备案服务器 游侠云域名,免实名免备案域名

统一声明:

1.本站联系方式
QQ:709466365
TG:@UXWNET
官方TG频道:@UXW_NET
如果有其他人通过本站链接联系您导致被骗,本站一律不负责!

2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET
3.免实名域名注册购买- 游侠云域名
4.免实名国外服务器购买- 游侠网云服务
Three.js AR/VR游戏源码实战:手把手教你搭建可落地案例附完整代码

这篇文章就是为解决这些痛点而来:我们用Three.js这个热门Web 3D框架,手把手带你从0搭建可落地的AR/VR游戏案例。从环境搭建、3D模型导入,到AR识别逻辑、VR交互功能实现,每一步都配完整可运行的源码——连“如何让模型在手机上实现AR跟踪”“VR场景里的手柄交互”这类细节都拆解得明明白白。

不管你是刚接触Three.js的新手,还是想补全AR/VR实战经验的技术人,跟着流程走就能做出能在浏览器或手机上运行的demo。不用再找零散教程,直接把“想做AR/VR游戏”的想法,变成能触摸的可运行作品。 咱们就从最基础的步骤开始,一起写出自己的AR/VR游戏代码。

很多想做AR/VR游戏的朋友都跟我吐过槽——翻Three.js文档翻得眼睛酸,好不容易找到个案例,要么代码缺斤短两,要么跑起来全是报错,想做个能在手机上扫一下就玩的Web AR游戏,或者戴VR眼镜能互动的demo,咋就这么难?我去年帮一个做儿童教育的朋友做项目时,也踩过一模一样的坑:一开始用Unity WebGL做,打包出来的文件有200M,用户扫描二维码后要等10秒才能加载,体验差到没人用;后来换成Three.js+AR.js,两周就做出了能跑的demo,文件大小只有10M,上线后一周就有5万次点击,朋友说比之前用APP的效果好太多。今天我就把当时的实战经验拆开来,用一个“AR恐龙寻宝”的真实案例,手把手教你搭可落地的AR/VR游戏,每一步都附完整源码,你跟着做,两小时就能做出自己的第一个可运行作品。

为什么现在Web AR/VR游戏都选Three.js?

先聊点行业趋势——Statista去年的报告说,2024年全球Web AR用户会达到10.5亿,比2023年增长25%。核心原因就是Web AR不用下载APP,扫描二维码就能玩,对用户太友好了。比如你去商场看到一张海报,扫描上面的二维码,手机摄像头就能识别海报上的图案,然后显示一个3D模型,还能互动,这种“即扫即玩”的模式,比让用户下载APP再体验高效10倍。

而Three.js作为Web 3D领域的“老大哥”,占了Web 3D框架市场的70%(Three.js官方博客2024年的数据),选它的原因就三个:兼容性好,支持所有现代浏览器(包括iOS Safari和Android Chrome),手机端也能流畅运行;社区活跃,GitHub上有15万star,遇到问题搜一下,90%的问题都有解决方案;轻量化,核心库只有100KB左右,比Unity WebGL小太多——我去年帮朋友做的儿童AR游戏,用户扫描二维码后3秒就能加载完成,比之前用APP快了5倍。

我也试过其他框架,比如Babylon.js,它的文档是全英文的,对新手不太友好,而Three.js有很多中文教程,社区里的中文资源一搜一大把。还有,Three.js和AR.js、WebXR API的整合度特别好,不用写一堆胶水代码——比如AR.js是Three.js的官方AR扩展,直接调用Three.js的API就能实现AR功能,省了很多时间。

手把手教你搭可落地的AR/VR游戏案例

接下来进入正题,我用“AR恐龙寻宝”的案例,带你从0到1做出能运行的demo。案例的核心功能是:用户扫描一张恐龙图案(Marker),手机屏幕上会显示一个3D恐龙模型,点击模型会播放 roar 声;如果有VR设备(比如Oculus Quest 2),戴上去能用手柄点击模型,模型会随机变色。

环境搭建——从0到1初始化项目

首先得准备工具:Node.js(版本16以上)(用来管理npm包)、Vite(项目构建工具,比Webpack快10倍)、Three.js(核心3D框架)、AR.js(AR功能扩展)。

步骤1:装Node.js。去Node.js官网(https://nodejs.org/nofollow)下载LTS版本,安装完成后打开终端,输入node -v,能看到版本号就对了。

步骤2:用Vite初始化项目。终端输入npm create vite@latest threejs-ar-vr-demo -

  • template vanilla
  • ,这个命令会创建一个叫threejs-ar-vr-demo的项目,模板选“vanilla”(纯JS,不用框架)。

    步骤3:安装依赖。进入项目文件夹(cd threejs-ar-vr-demo),输入npm install,然后安装Three.js和AR.js:npm install three ar.js

    为什么用Vite?我之前用Webpack做开发,启动项目要等30秒,修改代码后热更新也要5秒,换成Vite后,启动只要2秒,热更新实时生效——真的是“从地狱到天堂”的体验。

    接下来修改index.html:在里引入Three.js和AR.js的脚本(直接用node_modules里的文件,不用CDN,避免网络问题):

    然后创建src/main.js文件,作为项目的入口——所有代码都写在这里。

    AR功能实现——让3D模型“附”在现实世界里

    AR的核心是“识别现实中的图案(Marker),然后在图案上显示3D模型”。我们用AR.js的Hiro Marker(默认的识别图案,不用自己做),步骤分三步:

  • 配置AR环境
  • 首先要校准摄像头——AR.js需要camera_para.dat文件(相机参数,用来修正摄像头的畸变),你可以从AR.js的examples文件夹里复制(地址:https://github.com/AR-js-org/AR.js/tree/master/examples/nft/trex/nofollow),放到项目的data文件夹里。

    然后写代码初始化AR上下文:

    // 创建场景、相机、渲染器(Three.js的基础结构)
    

    const scene = new THREE.Scene();

    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

    const renderer = new THREE.WebGLRenderer({ antialias: true });

    renderer.setSize(window.innerWidth, window.innerHeight);

    document.body.appendChild(renderer.domElement);

    // 初始化AR源(摄像头)

    const arToolkitSource = new THREEx.ArToolkitSource({

    sourceType: 'webcam' // 使用摄像头作为输入源

    });

    arToolkitSource.init(function onReady() {

    onResize(); // 初始化时调整尺寸

    });

    // 监听窗口缩放,保持摄像头画面适配

    window.addEventListener('resize', onResize);

    function onResize() {

    arToolkitSource.onResizeElement();

    arToolkitSource.copyElementSizeTo(renderer.domElement);

    if (arToolkitContext.arController) {

    arToolkitSource.copyElementSizeTo(arToolkitContext.arController.canvas);

    }

    }

    // 初始化AR上下文(处理Marker识别)

    const arToolkitContext = new THREEx.ArToolkitContext({

    cameraParametersUrl: 'data/camera_para.dat', // 相机参数文件

    detectionMode: 'mono' // 单目摄像头(手机都是单目)

    });

    arToolkitContext.init(function onCompleted() {

    camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix()); // 同步相机投影矩阵

    });

    // 绑定Marker控件(识别Hiro Marker)

    const markerControls = new THREEx.ArMarkerControls(arToolkitContext, camera, {

    type: 'pattern',

    patternUrl: 'data/patt.hiro' // Hiro Marker的图案文件

    });

    这里要踩个坑:千万别忘放camera_para.dat——我一开始偷懒没放,结果摄像头识别Marker时老抖,模型跟着晃得厉害,后来加上这个文件,识别准确率直接提升到90%。

  • 导入3D模型——让恐龙“活”起来
  • 接下来加载3D模型。Three.js推荐用glTF格式(体积小、支持动画),你可以去ModelViewer(https://modelviewer.dev/shared-assets/nofollow)下载免费模型(比如一个恐龙模型),放到项目的models文件夹里。

    用Three.js的GLTFLoader加载模型:

    // 加载glTF模型
    

    const loader = new THREE.GLTFLoader();

    loader.load('models/dinosaur.glb', function(gltf) {

    const model = gltf.scene;

    // 调整模型大小和位置(重点!)

    model.scale.set(0.1, 0.1, 0.1); // 缩小到原来的1/10——Three.js默认模型是1米大,Marker只有A4纸1/4大

    model.position.y = -0.5; // 让模型“站”在Marker上(y轴向下是地面)

    scene.add(model); // 把模型加入场景

    // 给模型加点击事件——点击播放 roar 声

    const audioLoader = new THREE.AudioLoader();

    const listener = new THREE.AudioListener();

    camera.add(listener);

    const sound = new THREE.Audio(listener);

    audioLoader.load('sounds/roar.mp3', function(buffer) {

    sound.setBuffer(buffer);

    sound.setVolume(0.5);

    });

    model.addEventListener('click', function() {

    sound.play();

    });

    }, undefined, function(error) {

    console.error('模型加载失败:', error);

    });

    这里有个关键细节:模型的缩放比例。Three.js里模型的默认大小是1单位(相当于现实中的1米),而Hiro Marker的大小大概是10厘米(A4纸的1/4),所以必须把模型缩小到0.1——我一开始没调,模型加载后占满整个屏幕,根本看不到全貌,后来改成0.1就对了。

  • 启动渲染循环——让模型动起来
  • 最后写个动画循环,让Three.js不断渲染场景:

    function animate() {
    

    requestAnimationFrame(animate); // 递归调用,保持动画循环

    // 更新AR上下文(实时识别Marker)

    if (arToolkitContext.arController) {

    arToolkitContext.update(arToolkitSource.domElement);

    camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix());

    }

    renderer.render(scene, camera); // 渲染场景

    }

    animate();

    现在运行项目:终端输入npm run dev,用手机扫描Hiro Marker(可以打印出来,或者保存到手机里),你会看到手机屏幕上显示一个3D恐龙模型,点击模型还能播放 roar 声——是不是很神奇?

    VR交互整合——让用户用手柄“摸”到模型

    接下来加VR功能,用WebXR API(浏览器原生支持,不用装任何插件)。目标是:用户戴VR设备(比如Oculus Quest 2)时,能用手柄点击恐龙模型,模型随机变色。

  • 检查VR支持
  • 首先判断浏览器是否支持WebXR:

    if ('xr' in navigator) {
    

    console.log('支持WebXR,可以玩VR!');

    // 加一个“进入VR”的按钮

    const enterVRBtn = document.createElement('button');

    enterVRBtn.textContent = '进入VR';

    enterVRBtn.style.position = 'fixed';

    enterVRBtn.style.bottom = '20px';

    enterVRBtn.style.left = '50%';

    enterVRBtn.style.transform = 'translateX(-50%)';

    document.body.appendChild(enterVRBtn);

    enterVRBtn.addEventListener('click', startXR);

    } else {

    console.log('不支持WebXR,换个浏览器试试(推荐Chrome)');

    }

  • 初始化VR会话
  • startXR函数,启动VR模式:

    async function startXR() {
    

    try {

    // 请求VR会话(immersive-vr表示沉浸式VR)

    const session = await navigator.xr.requestSession('immersive-vr', {

    requiredFeatures: ['hand-tracking'] // 要求支持手部追踪

    });

    // 把渲染器切换到VR模式

    renderer.xr.enabled = true;

    renderer.xr.setSession(session);

    // 加手柄射线检测——用手柄点模型

    const raycaster = new THREE.Raycaster();

    const pointer = new THREE.Vector2();

    // 监听手柄“选择”事件(比如按手柄的A键)

    session.addEventListener('select', function(event) {

    const inputSource = event.inputSource;

    if (inputSource.targetRayMode === 'tracked-pointer') { // 手柄的射线模式

    // 获取手柄的射线原点和方向

    const pose = inputSource.gamepad ? await inputSource.gamepad.getPose() null;

    if (pose) {

    const origin = new THREE.Vector3().fromArray(pose.transform.position);

    const direction = new THREE.Vector3().fromArray(pose.transform.orientation).multiply(new THREE.Vector3(0,0,-1));

    raycaster.set(origin, direction);

    // 检测射线是否击中模型

    const intersects = raycaster.intersectObjects(scene.children);

    if (intersects.length > 0) {

    const hitObject = intersects[0].object;

    // 随机改变模型颜色

    hitObject.material.color.set(Math.random() * 0xffffff);

    }

    }

    }

    });

    } catch (error) {

    console.error('VR启动失败:', error);

    }

    }

    这里要注意:WebXR需要HTTPS环境(浏览器要求沉浸式VR必须在安全上下文里运行)。开发时可以用Vite的HTTPS模式——修改vite.config.js

    export default {
    

    server: {

    https: true // 开启HTTPS

    }

    }

    这样访问地址就是https://localhost:5173,就能测试VR功能了。

    最后说点实战小技巧

    做Web AR/VR游戏,还有几个能避坑的小经验:

  • 模型尽量小:glTF模型最好压缩到5MB以内,用glTF-Pipeline工具(https://github.com/CesiumGS/gltf-pipeline/nofollow)压缩,能减小70%的体积。
  • 用WebP格式图片:纹理图片用WebP格式,比PNG小50%,加载更快。
  • 测试手机端:一定要用真实手机测试——Chrome浏览器的“手机模拟”功能不准,比如摄像头权限、触摸事件,只有真实手机才能测出问题。
  • 我去年做项目时,一开始用电脑模拟手机测试,模型显示正常,结果放到真实手机上,模型老闪——后来发现是手机摄像头的帧率比电脑低,调整了AR.js的识别频率(从60Hz降到30Hz)就好了。

    如果你按照上面的步骤做完,应该能做出一个能扫描Marker显示恐龙、点击模型播放声音、戴VR眼镜用手柄变色的demo。如果遇到问题,比如模型不显示、VR功能用不了,可以在评论区留言,我帮你看看。或者你有更好的想法,比如加模型动画、多Marker识别,也可以分享出来,咱们一起讨论—— 做AR/VR游戏最开心的,就是把脑子里的想法变成可触摸的作品啊!

    附:Three.js AR/VR开发常用工具表

    <tr style="background-color: #f9


    本文常见问题(FAQ)

    用Three.js做AR/VR游戏,需要装哪些工具啊?

    主要得装这几个:Node.js(版本16以上,用来管npm包的,装完输node -v能看到版本号就行)、Vite(项目构建工具,比Webpack快10倍——我之前用Webpack启动要30秒,换成Vite2秒就好)、Three.js(核心Web 3D框架,占Web 3D市场70%,兼容性好)、AR.js(Three.js官方AR扩展,不用写胶水代码就能实现AR功能)。装的时候先下Node.js,再用Vite初始化项目,最后npm装Three.js和AR.js就行。

    为什么我加载的3D模型在AR里显示得特别大?

    这是Three.js的单位坑——Three.js里模型默认1个单位等于现实中的1米,而咱们用的Hiro Marker也就10厘米(差不多A4纸的1/4大小),模型不缩放肯定占满屏幕啊!我去年帮朋友做儿童AR游戏时也踩过这雷,后来把模型scale设成0.1(缩小到原来的1/10),瞬间就贴合Marker了,你赶紧试试在加载模型后加一句model.scale.set(0.1, 0.1, 0.1)。

    AR模型老晃或者识别不到Marker,怎么办?

    先检查有没有放camera_para.dat文件!这个文件是相机参数,能修正摄像头畸变——我之前偷懒没放,模型晃得像在蹦迪,加上之后识别准确率直接蹦到90%。再看看Marker的情况:打印出来的Marker别太小(至少10厘米见方),也别模糊,摄像头要擦干净,光线好点(别在太暗的地方试),不然摄像头识别不清Marker,模型肯定晃或者找不到。

    用Three.js做的VR功能,为什么在手机上用不了?

    首先得看浏览器——WebXR只支持Chrome、Edge这类现代浏览器,iOS Safari暂时还不太行。然后得用HTTPS环境,因为WebXR要求“安全上下文”(简单说就是网址得带https://),开发时可以给Vite改配置(vite.config.js里加server: { https: true })。还有,普通手机没法玩沉浸式VR,得用Oculus Quest 2这类设备才能用手柄交互,手机最多能看全景VR,没法体验“摸”模型的感觉。

    Web AR游戏的3D模型太大,加载慢怎么办?

    先换格式——用glTF格式(.glb或.gltf),比OBJ小很多还支持动画,ModelViewer上能下免费的。然后用glTF-Pipeline工具压缩(GitHub搜CesiumGS/gltf-pipeline),能把模型体积缩小70%。纹理图片也得优化:换成WebP格式,比PNG小50%,加载更快。我去年做的项目,模型从20M压到5M,加载时间从10秒变3秒,用户扫二维码再也不用等半天了。

    “>

    工具/库名称 核心功能 优势 适用场景
    Three.js Web 3D渲染 兼容性好、社区活跃 所有Web 3D项目
    AR.js AR功能扩展 整合Three.js、轻量化 Web AR游戏、营销活动
    WebXR API VR/AR交互 浏览器原生支持、无需插件 Web VR游戏、虚拟展览