用于构建多用户虚拟现实体验的Web框架

网友投稿 511 2022-10-30

用于构建多用户虚拟现实体验的Web框架

用于构建多用户虚拟现实体验的Web框架

Networked-Aframe

Multi-user VR on the Web

A framework for writing multi-user VR apps in HTML and JS.

Built on top of A-Frame.

Features — Getting Started — Examples — Documentation — Contact

Features

Support for WebRTC and/or WebSocket connections.Voice chat. Audio streaming to let your users talk in-app (WebRTC only).Bandwidth sensitive. Only send network updates when things change.Cross-platform. Works on all modern Desktop and Mobile browsers. Oculus Rift, Oculus Quest, HTC Vive and Google Cardboard.Extendable. Sync any A-Frame component, including your own, without changing the component code at all.

Getting Started

Follow the NAF Getting Started tutorial to build your own example from scratch, including setting up a local server.

To run the examples on your own PC:

git clone https://github.com/networked-aframe/networked-aframe.git # Clone the repository.cd networked-aframenpm install # Install dependencies.npm run dev # Start the local development server.

With the server running, browse the examples at http://localhost:8080. Open another browser tab and point it to the same URL to see the other client.

For info on how to host your experience on the internet, see the NAF Hosting Guide.

Basic Example

My Networked-Aframe Scene

More Examples

Open in two tabs if nobody else is online.

BasicBasic with 4 clientsDance ClubGoogle BlocksTracked ControllersPositional AudioNametagsDynamic Room NameForm to set room and usernameMinecraft CloneMore...

Made something awesome with Networked-Aframe? Let us know and we'll include it here.

Documentation

Overview

Networked-Aframe works by syncing entities and their components to connected users. To connect to a room you need to add the networked-scene component to the a-scene element. For an entity to be synced, add the networked component to it. By default the position and rotation components are synced, but if you want to sync other components or child components you need to define a schema. For more advanced control over the network messages see the sections on Broadcasting Custom Messages and Options.

Scene component

Required on the A-Frame component.

...

PropertyDescriptionDefault Value
serverURLChoose where the WebSocket / signalling server is located./
appUnique app name. Spaces are not allowed.default
roomUnique room name. Can be multiple per app. Spaces are not allowed. There can be multiple rooms per app and clients can only connect to clients in the same app & room.default
connectOnLoadConnect to the server as soon as the webpage loads.true
onConnectFunction to be called when client has successfully connected to the server.onConnect
adapterThe network service that you wish to use, see adapters.socketio
audioTurn on / off microphone audio streaming for your app. Only works if the chosen adapter supports it.false
debugTurn on / off Networked-Aframe debug logs.false

Connecting

By default, networked-scene will connect to your server automatically. To prevent this and instead have control over when to connect, set connectOnLoad to false in networked-scene. When you are ready to connect emit the connect event on the a-scene element.

AFRAME.scenes[0].emit('connect');

Disconnecting

To disconnect simply remove the networked-scene component from the a-scene element.

AFRAME.scenes[0].removeAttribute('networked-scene');

Completely removing a-scene from your page will also handle cleanly disconnecting.

Creating Networked Entities

Create an instance of a template to be synced across clients. The position and rotation will be synced by default. The aframe-lerp-component is added to allow for less network updates while keeping smooth motion.

Templates must only have one root element. When attachTemplateToLocal is set to true, the attributes on this element will be copied to the local entity and the children will be appended to the local entity. Remotely instantiated entities will be a copy of the root element of the template with the networked component added to it.

Example attachTemplateToLocal=true

Example attachTemplateToLocal=false

ParameterDescriptionDefault
templateA css selector to a template tag stored in <a-assets>''
attachTemplateToLocalDoes not attach the template for the local user when set to false. This is useful when there is different behavior locally and remotely.true
persistentOn remote owner disconnect, attempts to take ownership of persistent entities rather than delete themfalse

Deleting Networked Entities

Currently only the creator of a network entity can delete it. To delete, simply delete the element from the HTML using regular DOM APIs and Networked-Aframe will handle the syncing automatically.

Syncing Custom Components

By default, the position and rotation components on the root entity are synced.

To sync other components and components of child entities you need to define a schema per template. Here's how to define and add a schema:

NAF.schemas.add({ template: '#avatar-template', components: [ 'position', 'rotation', 'scale', { selector: '.hairs', component: 'show-child' }, { selector: '.head', component: 'material', property: 'color' }, ]});

Components of the root entity can be defined with the name of the component. Components of child entities can be defined with an object with both the selector field, which uses a standard CSS selector to be used by document.querySelector, and the component field which specifies the name of the component. To only sync one property of a multi-property component, add the property field with the name of the property.

Once you've defined the schema then add it to the list of schemas by calling NAF.schemas.add(YOUR_SCHEMA).

Component data is retrieved by the A-Frame Component data property. During the network tick each component's data is checked against its previous synced value; if the data object has changed at all it will be synced across the network.

Syncing nested templates - eg. hands

To sync nested templates setup your HTML nodes like so:

In this example the head/camera, left and right hands will spawn their own templates which will be networked independently of the root player. Note: this parent-child relationship only works between one level, ie. a child entity's direct parent must have the networked component.

Sending Custom Messages

NAF.connection.subscribeToDataChannel(dataType, callback)NAF.connection.unsubscribeToDataChannel(dataType)NAF.connection.broadcastData(dataType, data)NAF.connection.broadcastDataGuaranteed(dataType, data)NAF.connection.sendData(clientId, dataType, data)NAF.connection.sendDataGuaranteed(clientId, dataType, data)

Subscribe and unsubscribe callbacks to network messages specified by dataType. Broadcast data to all clients in your room with the broadcastData functions. To send only to a specific client, use the sendData functions instead.

ParameterDescription
clientIdClientId to send this data to
dataTypeString to identify a network message. u is a reserved data type, don't use it pls
callbackFunction to be called when message of type dataType is received. Parameters: function(senderId, dataType, data, targetId)
dataObject to be sent to all other clients

Transfer Entity Ownership

The owner of an entity is responsible for syncing its component data. When a user wants to modify another user's entity they must first take ownership of that entity. The ownership transfer example and the toggle-ownership component show how to take ownership of an entity and update it.

NAF.utils.takeOwnership(entityEl)

Take ownership of an entity.

NAF.utils.isMine(entityEl)

Check if you own the specified entity.

Events

Events are fired when certain things happen in NAF. To subscribe to these events follow this pattern:

document.body.addEventListener('clientConnected', function (evt) { console.error('clientConnected event. clientId =', evt.detail.clientId);});

Events need to be subscribed after the document.body element has been created. This could be achieved by waiting for the document.body onLoad method, or by using NAF's onConnect function. Use the NAF Events Demo as an example.

List of events:

EventDescriptionValues
clientConnectedFired when another client connects to youevt.detail.clientId - ClientId of connecting client
clientDisconnectedFired when another client disconnects from youevt.detail.clientId - ClientId of disconnecting client
entityCreatedFired when a networked entity is createdevt.detail.el - new entity
entityRemovedFired when a networked entity is deletedevt.detail-workId - networkId of deleted entity

The following events are fired on the networked component. See the toggle-ownership component for examples.

List of ownership transfer events:

EventDescriptionValues
ownership-gainedFired when a networked entity's ownership is takenevt.detail.el - the entity whose ownership was gained
evt.detail.oldOwner - the clientId of the previous owner
ownership-lostFired when a networked entity's ownership is lostevt.detail.el - the entity whose ownership was lost
evt.detail.newOwner - the clientId of the new owner
ownership-changedFired when a networked entity's ownership is changedevt.detail.el - the entity whose ownership was lost
evt.detail.oldOwner - the clientId of the previous owner
evt.detail.newOwner - the clientId of the new owner

Adapters

NAF can be used with multiple network libraries and services. An adapter is a class which adds support for a library to NAF. If you're just hacking on a small project or proof of concept you'll probably be fine with the default configuration and you can skip this section. Considerations you should make when evaluating different adapters are:

How many concurrent users do you need to support in one room?Do you want to host your own server? Or would a "serverless" solution like Firebase do the job?Do you need audio (microphone) streaming?Do you need custom server-side logic?Do you want a WebSocket (client-server) network architecture or WebRTC (peer-to-peer)?

I'll write up a post on the answers to these questions soon (please bug me about it if you're interested).

By default the socketio adapter is used, which does not support audio and uses a TCP connection. This is not ideal for production deployments however due to inherent connection issues with WebRTC we've set it as the default. To use WebRTC instead of WebSockets, change the adapter to webrtc, which supports audio and uses a UDP.

If you're interested in contributing to NAF a great opportunity is to add support for more adapters and send a pull request.

List of the supported adapters:

AdapterDescriptionSupports AudioWebSockets or WebRTCHow to start
socketioDEFAULT - SocketIO implementationNoWebSockets onlynpm run start
webrtcNative WebRTC implementationYesBothnpm run start
FirebaseFirebase for WebRTC signallingNoWebRTCSee naf-firebase-adapter
uWSImplementation of uWebSocketsNoWebSocketsSee naf-uws-adapter
EasyRTCEasyRTCYesBothSee naf-easyrtc-adapter
DeepstreamDeepstreamHub for WebRTC signallingNoWebRTCSee naf-deepstream-adapter

Audio

After adding audio: true to the networked-scene component (and using an adapter that supports it) you will not hear any audio by default. Though the audio will be streaming, it will not be audible until an entity with a networked-audio-source is created. The audio from the owner of this entity will be emitted in 3D space from that entities position. The networked-audio-source component must be added to an entity (or a child of an entity) with the networked component.

To quickly get started, try the Glitch NAF Audio Example.

Misc

NAF.connection.isConnected()

Returns true if a connection has been established to the signalling server.

NAF.connection.getConnectedClients()

Returns the list of currently connected clients.

Options

NAF.options.updateRate

Frequency the network component sync function is called, per second. 10-20 is normal for most Social VR applications. Default is 15.

NAF.options.useLerp

By default when an entity is created the aframe-lerp-component is attached to smooth out position and rotation network updates. Set this to false if you don't want the lerp component to be attached on creation.

Stay in Touch

Join the A-Frame Slack and add the #networked-aframe channelFollow changes on GitHubLet us know if you've made something with Networked-Aframe. We'd love to see it!

Help and More Information

Getting started tutorialEdit live example on glitch.comLive demo siteNetworked-Aframe AdaptersA-FrameWebXRHayden Lee, NAF Creator and MaintainerBugs and requests can be filed on GitHub Issues

Folder Structure

/ (root)Licenses and package information /dist/Packaged source code for deployment /server/Server code /examples/Example experiences /src/Client source code /tests/Unit tests

Roadmap

More examples!RoadmapAdd your suggestions

Interested in contributing? Open an issue or send a pull request.

License

This program is free software and is distributed under an MIT License.

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Playing FPS Games with Deep Reinforcement Learning
下一篇:C#堆栈、调用堆栈
相关文章

 发表评论

暂时没有评论,来抢沙发吧~