Accessing Avatar and Profile
Learn how to display player information and use VIVERSE avatars in your game.
This tutorial shows you how to display a player tag above the character by accessing the user profile information from VIVERSE.
Here's a preview of what we'll build in this tutorial:
import { Sky } from '@react-three/drei' import { Canvas } from '@react-three/fiber' import { Viverse, SimpleCharacter, FixedBvhPhysicsBody, PrototypeBox } from '@react-three/viverse' import { PlayerTag } from "./Playertag" export default function App() { return ( <Canvas shadows style={{ position: "absolute", inset: "0", touchAction: "none" }}> <Viverse> <Sky /> <directionalLight intensity={1.2} position={[-10, 10, -10]} castShadow /> <ambientLight intensity={1} /> <SimpleCharacter> <PlayerTag /> </SimpleCharacter> <FixedBvhPhysicsBody> <PrototypeBox scale={[10, 1, 15]} position={[0, -0.5, 0]} /> </FixedBvhPhysicsBody> </Viverse> </Canvas> ) }
First, we use the useViverseProfile()
hook to fetch the current user's profile from VIVERSE, including their name and avatar information. We provide a fallback for when the user isn't logged in:
const profile = useViverseProfile() ?? {
name: 'Anonymous',
activeAvatar: { headIconUrl: 'https://picsum.photos/200' },
}
Next, we need a 3D ui library, install it via
npm install @react-three/uikit
UIKit provides HTML-like components (Root
, Image
, Text
) that work in 3D space. We create a card-like layout with flexbox:
<Root
depthTest={false}
renderOrder={1}
backgroundOpacity={0.5}
borderRadius={10}
paddingX={2}
height={20}
backgroundColor="white"
flexDirection="row"
alignItems="center"
gap={4}
>
<Image
width={16}
height={16}
borderRadius={14}
src={profile.activeAvatar?.headIconUrl}
/>
<Text fontWeight="bold" fontSize={12} marginRight={3}>
{profile.name}
</Text>
</Root>
Next, we use useFrame
to constantly update the tag's rotation to match the camera:
import { Group } from 'three'
const ref = useRef<Group>(null)
useFrame((state) => {
if (ref.current == null) {
return
}
ref.current.quaternion.copy(state.camera.quaternion)
})
The full PlayerTag
component looks like this:
import { useViverseProfile } from '@react-three/viverse'
import { Root, Image, Text } from '@react-three/uikit'
import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
import { Group } from 'three'
export function PlayerTag() {
const profile = useViverseProfile() ?? {
name: 'Anonymous',
activeAvatar: { headIconUrl: 'https://picsum.photos/200' },
}
const ref = useRef<Group>(null)
// Make the tag always face the camera
useFrame((state) => {
if (ref.current == null) {
return
}
ref.current.quaternion.copy(state.camera.quaternion)
})
return (
<group ref={ref} position-y={2.15}>
<Root
depthTest={false}
renderOrder={1}
backgroundOpacity={0.5}
borderRadius={10}
paddingX={2}
height={20}
backgroundColor="white"
flexDirection="row"
alignItems="center"
gap={4}
>
<Image
width={16}
height={16}
borderRadius={14}
src={profile.activeAvatar?.headIconUrl}
/>
<Text fontWeight="bold" fontSize={12} marginRight={3}>
{profile.name}
</Text>
</Root>
</group>
)
}
Now finally lets add the PlayerTag as a child of SimpleCharacter to display it
<SimpleCharacter>
<PlayerTag />
</SimpleCharacter>