There has never been a better time to build delightful social experiences. If you’d like to build one of your own, it’s easy to get started with Unity and Normcore. Here’s a quick breakdown for a simple, two-player chat room.
Download the finished project on GitHub and follow along!
The final result is one scene with two distinct avatars. The first person to open the app becomes the avatar on the left, the second person becomes the avatar on the right.
In this breakdown, I’m going to focus on…
Changing an avatar’s appearance based on which player it belongs to.
Spawning avatars in different locations based on when players join.
Bringing your avatars to life with some programmatic animation.
Follow the “Getting started” guide to install the Normcore plugin and get an app key. Follow “Adding AR/VR Avatars & Voice Chat” to spawn custom avatars.
Follow “Synchronizing your own data with custom Realtime Components” to make select data available to both players.
Once you’re able to spawn an avatar into your scene using the Realtime + VR Player prefab, you can test the project by making a build and sending a copy to a friend. Once you’re set up, you can start changing the avatar’s appearance based on whom it belongs to.
1. Changing an avatar’s appearance
I want Player 1 and Player 2 to look different.
To change the avatar’s appearance based on the owning player, I used each player’s client ID (realtime.clientID) to update which avatar prefab appears in the scene.
I started by creating a real-time model to sync the client IDs between players— I followed Normcore’s guide on synchronizing custom data, but tracked an int instead of a Color for IntSync.cs. Next, I created two separate avatar prefabs for each player under Assets > Normal > Examples > VR Player > Resources.
IntSync.cs has a function— UpdateAvatar()— that assigns one of the two prefabs to the Realtime + VR Player based on the client ID. A0 loads in if the client ID is 0, and A1 loads in if the client ID is 1. Adding more avatars is as easy as making additional prefabs and adding them to IntSync.cs.
2. Spawning avatars in different locations
I want both players to face each other when the app starts.
Once I had the client ID from IntSync.cs, I was able to feed it into PositionAvatars.cs— a separate script that changes the avatar’s position based on the client ID. In my scene, I made 3 empty GameObjects:
SpawnMarker - The GameObject that PositionAvatars.cs moves, also assigned to the Root of the Realtime + VR Player. This can stay at the origin by default.
P0 - Where I want the first avatar to move.
P1 - Where I want the seconds avatar to move.
Just like UpdateAvatar() in IntSync.cs, PositionAvatars.cs moves the SpawnMarker to P0 or P1 depending on the client ID. Because the SpawnMarker is also the Root of the Realtime + VR Player, each avatar will move to its assigned position immediately after loading in. P0 and P1 are Transforms, so you can also set the rotation and scale.
3. Bringing your avatars to life
I want to make my avatars feel alive, even when no one’s talking.
To enhance my avatars, I added a short script that makes them blink intermittently. In FaceController.cs, I have a coroutine that momentarily switches the sprite assigned to each eye— that coroutine fires every 1-5 seconds, randomizing the blinking between the two avatars. You can use the same approach to add other animations at different intervals!
That’s it! The finished project has all the assets I used and a short script to animate the mouth based on mic input. Again, there has never been a better time to build delightful social experiences online— hopefully this project gives you a head start if you’re thinking about building one in Unity.
Inbetweens is a weekly newsletter on animation and technology, featuring interviews with artists, project breakdowns, and more. Subscribe to receive new issues in your inbox!