一款新出的开源框架,主要目的是用来做游戏引擎的,对标端游PUBG
因公司业务需求不同,跟着教程做了一款纯展示的展厅性质的Demo(React)
近几年元宇宙的概念有点热门,这里亦可沾点边



NPM地址
GitHub地址
官方文档地址
展厅Dem地址,PC端,简单做了做,功能很少,除基本的人物移动逻辑外,只做了图片轮播预览和视频展示的功能
官方B站教学视频
相关3D模型问题B站视频
1、纯Web前端
2、上手超简单。支持原JS,React,Vue
3、可通过websocket实现多人联机互动
4、支持PC、移动端摇杆
1、框架不断内测完善中,业务场景功能待完善
2、框架支持的3D模型具有局限性,需要blender进行处理。这也是市面上3D模型不统一导致的。
3、官方文档暂时不完善,文档阅读不便(快一点呀快一点)
一款前端构建工具,跟着官方文档走一下,create一个项目即可,不需要了解很多
当然如果业务需求很多了,可能需要了解这个工具的配置项什么的,可能会有冲突
支持TS,也支持JS,如果觉TS很搞,可以使用JS,但是还是建议使用TS,如果你要构建一个长久维护的项目的话。
用来管理你的键盘事件与动画状态的关系
建议使用blender进行模型处理,blender2.93LTS版本
import { useState, useRef } from "react"
// lingo3D库
import { World, Editor, Cube, Model, ThirdPersonCamera, Keyboard, OrbitCamera, useLoop, useKeyboard, types, Find, HTML, Reticle, useSpring } from "lingo3d-react"
// 状态机,用来管理动作动画
import { useMachine } from "@xstate/react"
// 状态机文件
import poseMachine from "./stateMachines/poseMachine"
// 一款文字动画库,也是lingo3D作者的
import AnimText from "@lincode/react-anim-text"
import './App.css'
// 图片轮播的组件
import Gallery from './components/gallery'
function App() {
const [mouseOver, setMouseOver] = useState(false) //鼠标移入的开关
const [fixedWindow, setfixedWindow] = useState(false)// fixedWindow的开关
// 角色model的ref
const characterRef = useRef<types.Model>(null)
// 状态机
const [pose, sendPose] = useMachine(poseMachine, {
actions: {
enterJumping: ()=>{
const character = characterRef.current;
if(character === null) return
character.velocity.y = 5
character.onLoop = () => {
if(character.velocity.y === 0){
character.onLoad = undefined
sendPose('LADNED')
}
}
},
enterWaving: () => {
const character = characterRef.current;
if(character === null) return
const animationTimeout = setTimeout(() => {
sendPose('ENDTHISANIMATION')
clearTimeout(animationTimeout)
}, 4000);
}
}
})
// ThirdPersonCameraInnerPosition,第三人称相机的Inner偏移量
const CamInnerX = mouseOver?20:0
const CamInnerZ = mouseOver?40:200
const xSpring = useSpring({to:CamInnerX, bounce: 0})
const zSpring = useSpring({to: CamInnerZ, bounce: 0})
// characterAnimations,主角所有的动画
const characterAnimations = {
idle: 'person/Idle.fbx',
walking: 'person/Walking.fbx',
running:'person/Running.fbx',
jumping: 'person/Falling.fbx',
waklingback:'person/WalkingBackwards.fbx',
waving:'person/Waving.fbx'
}
return (
<>
{/* Word世界,参数分别为:高质量画面,天空盒图片,Find(下文标签的边框,被遮挡是黑色),环境光遮蔽 */}
<World performance="quality" skybox='skylight.hdr' outlineHiddenColor="black" ambientOcclusion>
{/* 场景模型,参数分别为:模型地址(public下的),缩放,物理碰撞检测(我是地图)*/}
<Model
src="scene/Pavilion.glb"
scale={18}
physics='map'
boxVisible={false}
>
{/* Find,可以把他理解成,场景模型中的某一个名字是name的元素,这个name哪里来,blender建模的时候命名的,参数分别为:name,边框,鼠标移入事件、鼠标移出事件、点击事件 */}
<Find
name="a5_CRN.a5_0"
outline
onMouseOver={()=>{setMouseOver(true)}}
onMouseOut={()=>{setMouseOver(false)}}
onClick={()=>{setfixedWindow(true)}}
>
{
mouseOver &&
// Html标签,就是普通的Ht,里面可以放html的标签
<HTML>
<AnimText className='HTML_TITLE'>SDTA-Gallery</AnimText>
</HTML>
}
</Find>
{/* 另一个Find,名字不同,让他播放一个视频 */}
<Find name="b11_CRN.b11_0" texture={"https://media.sdta.cn/themes/sdta/assets/video/sdta-slider3.mp4"}></Find>
</Model>
{/* 第三人称相机,参数分别问:鼠标控制、激活、inner角度(x,y,z) */}
<ThirdPersonCamera
mouseControl
active={!fixedWindow}
innerX={xSpring}
innerY={30}
innerZ={zSpring}
>
{/* 人物模型,参数分别为:模型地址,ref(通过ref可以获取并操作这个model),物理碰撞检测(我是主角),初始位置(x,y,z),这个model都有什么动画,这个model当前执行的动画,模型的盒子线关闭,当设置环境光时需要打开pbr */}
<Model
src="person/T-Pose.fbx"
ref={characterRef}
physics='character'
x={-424.99} y={-825.31} z={-661.13}
animations={characterAnimations}
animation={pose.value as any}
boxVisible={false}
pbr
/>
</ThirdPersonCamera>
{/* 键盘事件,这里就需要配合状态机来进行操作(如果只是简单的上下左右,通过useState即可,当功能复杂时,需要状态机进行管理) */}
<Keyboard
onKeyPress={(key: string) => {
if(key === 'w'){
sendPose('KEY_W_DOWN')
characterRef.current?.moveForward(-3)
}
else if(key === 's'){
sendPose('KEY_S_DOWN')
characterRef.current?.moveForward(1)
}
else if(key === 'd'){
// sendPose('KEY_S_DOWN')
characterRef.current?.moveRight(-3)
}
else if(key === 'a'){
// sendPose('KEY_S_DOWN')
characterRef.current?.moveRight(3)
}
else if(key === 'Space'){
sendPose('KEY_SPACE_DOWN')
}
else if(key === 'Shift'){
sendPose('KEY_SHIFT_DOWN')
characterRef.current?.moveForward(-3)
}
else if(key === 'h'){
sendPose('KEY_H_DOWN')
}
}}
onKeyUp={(key: string) => {
if(key === 'w'){
sendPose('KEY_W_UP')
}
else if(key === 's'){
sendPose('KEY_S_UP')
}
else if(key === 'Shift'){
sendPose('KEY_SHIFT_UP')
}
}}
/>
</World>
{/* Model编辑器,可以查看模型的各种参数进行调试 */}
{/* <Editor /> */}
{
fixedWindow &&
<FixedWindow handleClose={()=>setfixedWindow(false)}></FixedWindow>
}
</>
)
}
function FixedWindow(props: any){
return(
<div className="fixedWindow">
<span onClick={()=>props.handleClose()} className="fixedWindow_close">{"close"}</span>
<span className="fixedWindow_websocket">{"OPEN CHAT"}</span>
{/* 图片轮播组件 */}
<Gallery></Gallery>
</div>
)
}
export default App
1、blender建议使用2.9.3稳定版
2、用vite创建的react是18,后面用到了Swiper不知道什么错,降到了17
3、期待更多的发现
修改(澄清问题)我已经花了几天时间试图弄清楚如何从Facebook游戏中抓取特定信息;但是,我遇到了一堵又一堵砖墙。据我所知,主要问题如下。我可以使用Chrome的检查元素工具手动查找我需要的html-它似乎位于iframe中。但是,当我尝试抓取该iframe时,它是空的(属性除外):如果我使用浏览器的“查看页面源代码”工具,这与我看到的输出相同。我不明白为什么我看不到iframe中的数据。答案不是它是由AJAX之后添加的。(我知道这既是因为“查看页面源代码”可以读取Ajax添加的数据,也是因为我有b/c我一直等到我可以看到数据页面之后才抓取它,但它仍然不存在)。发生这种情况是因为
我已经按照https://github.com/wayneeseguin/rvm#installation上的说明通过RVM安装了Ruby.有关信息,我有所有文件(readline-5.2.tar.gz、readline-6.2.tar.gz、ruby-1.9.3-p327.tar.bz2、rubygems-1.8.24.tgz、wayneeseguin-rvm-stable.tgz和yaml-0.1.4.tar.gz)在~/.rvm/archives目录中,我不想在任何目录中重新下载它们方式。当我这样做时:sudo/usr/bin/apt-getinstallbuild-essent
我的Ruby-on-Rails项目中有以下文件结构,用于规范:/spec/msd/serviceservice_spec.rb/support/my_modulerequests_stubs.rb我的request_stubs.rb有:moduleMyModule::RequestsStubsmodule_functiondeflist_clientsurl="dummysite.com/clients"stub_request(:get,url).to_return(status:200,body:"clientsbody")endend在我的service_spec.rb我有:re
Ruby是否支持(找不到更好的词)非转义(逐字)字符串?就像在C#中一样:@"c:\ProgramFiles\"...或者在Tcl中:{c:\ProgramFiles\} 最佳答案 是的,您需要在字符串前加上%前缀,然后是描述其类型的单个字符。你想要的是%q{c:\programfiles\}。镐书很好地涵盖了这一点here,部分是通用分隔输入。 关于ruby-Ruby是否支持逐字字符串?,我们在StackOverflow上找到一个类似的问题: https:/
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?
我正在编写一个Rubygem,在我的代码中使用{key:'value'}哈希语法。我的测试都在1.9.x中通过,但我(可以理解)在1.8.7中得到syntaxerror,unexpected':',expecting')'。是否有支持1.8.x的最佳实践?我是否需要使用我们的老friend=>重写代码,还是有更好的策略? 最佳答案 我认为你运气不好,如果你想支持1.8,那么你必须使用=>。像往常一样,我会提到在1.9的某些情况下您必须使用=>:如果键不是一个符号。请记住,任何对象(符号、字符串、类、float……)都可以是Ruby哈
在Rails中,什么是集成更新模型某些元素的UDP监听过程的最佳方式(特别是它将向其中一个表添加行)。简单的答案似乎是在同一个进程中使用UDP套接字对象启动一个线程,但我什至不清楚我应该在哪里做适合Rails方式的事情。有没有一种巧妙的方法来开始收听UDP?具体来说,我希望能够编写一个UDPController并在每个数据报消息上调用一个特定的方法。理想情况下,我希望避免在UDP上使用HTTP(因为它会浪费一些在这种情况下非常宝贵的空间),但我完全控制消息格式,因此我可以为Rails提供它需要的任何信息。 最佳答案 Rails是一个
我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click
所以我看到unity支持c#、JS和Boo。我可以学习其中一个,但我想制作一个“编译器”或类似的东西,让我可以编写ruby代码并输出JS代码或制作一个可以被Unity编译器读取的层。这有可能吗?我愿意在这方面投入很多时间并且有相当多的经验。 最佳答案 如果您的问题实际上是“我如何将Ruby编译为JavaScript”,那么这更容易回答:Opal:RubytoJavaScriptcompiler但是,学习其中一种受支持的语言会更好。当运行的是用另一种语言解释的代码时,很难调试“您的”代码。
我收到错误:unsupportedcipheralgorithm(AES-256-GCM)(RuntimeError)但我似乎具备所有要求:ruby版本:$ruby--versionruby2.1.2p95OpenSSL会列出gcm:$opensslenc-help2>&1|grepgcm-aes-128-ecb-aes-128-gcm-aes-128-ofb-aes-192-ecb-aes-192-gcm-aes-192-ofb-aes-256-ecb-aes-256-gcm-aes-256-ofbRuby解释器:$irb2.1.2:001>require'openssl';puts