17. Finishing the Multiplayer - Crossplay
Hello again! Jammu here. In my previous 2 posts I have already achieved multiplayer functionality on both Steam and Oculus platforms. So far we haven’t had any functionality to add those players together though.
To add cross platform support, we need a way to identify the rooms players are connected on. Currently we are just using Steam/Oculus ID’s, which is fine if the player does not need to write them to anywhere. But this quickly comes super frustrating if you are typing 15 numbers on a virtual keyboard to connect your Quest to your Steam friend’s game.
So we decided to use a 6 character string as a room code, this gives us around 1.8 trillion different combinations on the room code (alphabet and numbers 1-9), which should be plenty enough for our purposes. We bought an asset “VR UIKit ” where I grabbed a keyboard asset to use in the game. I added an Inputfield to enter the room code in, but apparently it has been bugged for years on the Quest. Oculus blames Unity and Unity blames Oculus and nobody has bothered to fix the problem, nice.
Luckily I found out a dirty way of fixing this error, when the user is typing on the virtual keyboard, I can directly modify the Inputfield text parameter and move the caret position according to the text length. This works well on one Inputfield, but would need more work on multiple.
Solution was (not surprisingly) pretty weird, when a user is creating the Oculus room, I added an datastore to Matchmaking options with an key “roomCode” by using the matchMakingOptions.SetCreateRoomDataStore() function, when the Oculus user gets invited to the game, we receive the invitation with Rooms.SetRoomInviteReceivedNotificationCallback() callback, and from there we can grab the room that we are invited to, and so we can access the Oculus room’s datastore and grab the room code from there with message.Data.DataStore.TryGetValue(). I have no idea if this is the best way or right way to do this, but seems to work. Not a surprise anymore that Oculus’s documentation did not help on any part of this.
One minor UX improvement came to life pretty much on accident, if user inputs a invalid room code (meaning that no rooms exists with this code), player makes a new room with that room code, this allows players to easily make custom rooms with custom names that their friends can remember (e.g. MEKIWI is our test room’s code).
We also wanted the multiplayer experience to be as seamless as possible, so we allowed the players to invite their own friends to any game they want. So if User1 hosts a game on their Steam account, User2 joins the game via Oculus Quest, User2 can ask his/her Oculus friend to join User1’s game. Complicated to explain? Yes.
Next I can finally give this horrible development UI to our UX/UI developers and they can make it look pretty.
Finished dev UI:
Lines of code: ~2200
Energy drinks spent: too much
I you have anything to ask or have any suggestions on other blog posts you would like to read from the multiplayer side, pop in on our Discord server at https://discord.gg/qy4NXnWw
Random development quote: “Mää en oo kyl huomannu että oisin kännissä yhtää erilainen… Vähä tyhmempi vaan.”
This week our guest writer is Justus, our code guru and shader wizard. Take it away Justus!
Why bother making cool shaders? Why don’t you just go crazy with post-processing like everyone else?
Because we can’t. With Cave Digger 2 our first target platform is Oculus Quest. Quest is a standalone mobile device, and as such, it uses a rendering type called Tiled Rendering, which is really efficient for most rendering, but causes full screen effects like post-processing to be really slow. These effects will add significant fill-rate overhead and should almost always be avoided. Find out more about how Quest does Tiled Rendering here.
So in order to make fancy looking effects like custom fog, color grading or bloom, while maintaining stable 72 fps on Oculus Quest, we have to make the effects with shaders and particle effects.
But shaders are hard to make 🙁
It’s true that writing shaders can be annoying even if you’re an experience programmer. Cg/HLSL syntax is different from most programming languages. However there is a easier way. The trick is to use a node based editor like Amplify Shader or Shader Graph. You can find plenty of helpful guides and tutorials online. Also Amplify Shader has lots of good example shaders for you to learn from. This allows you to make shaders much faster, however the catch is that the shaders might not be as optimized as they would be if programmed by an experienced graphics programmer
Amplify Shader view of CD2 Gem shader. Cel Shaded lighting and Custom Fog are is done in a custom functions, which makes them more easy to reuse.
So what does it do?
*Slaps the roof of Cave Digger 2 Lit shader*
This bad boy has a custom fog that uses a cubemap for color. It uses a cell shaded lighting that’s similar to Breath of the Wild. It can do triplanar texturing and stochastic texturing.
Also we have a custom Gem Shader for making those loots look shiny and tasty.
How to make it work
To handle controlling the shader settings I created a scriptable object called Atmosphere and also created Atmosphere Manager to manage them
A scriptable object helps to quickly make different atmospheres for different areas. It currently controls the ambient lighting color and fog density.