Upload
bemyapp
View
772
Download
0
Embed Size (px)
Citation preview
WebGL and Unity
Best Practices
Vincent Vergonjeanne
CEO - EVERYDAYiPLAY
Former CEO of Kobojo+50M registered users since 2009
$7.5M Serie A in april 2011Up to 90 employees
Who am I?
CEO of EVERYDAYiPLAYSelf-Funded
24 employees
Who am I?
WHY WEBGL WAS SOIMPORTANT FOR US?
Vikings Gone Wild
• Oct 2013: Vikings Gone Wild on Facebook
– Hybrid Flash/Unity WebPlayer
– 3M registered users
– Launched on iOS, Android 1 year later
Heroes of Paragon
• June 2014: Start of Heroes of Paragon
– Planned to launch with WebPlayer only
– iOS and Android supported from beginning
• April 2015: Chrome kills NAPI
– Strong impact on Vikings Gone Wild
– Heroes of Paragon’s plan for Web are
shutdown
– We become a mobile gaming company
OUR FIRST EXPERIENCEWITH WEBGL
Early days
• Jan 2015: We get access to Unity 5.0 beta
– The game exported properly
– We ran it …
• But early results were disastrous
• 32 bits browser crashes most of the time during JS
parsing phase
• 64 bits browser pass the parsing, but early fps was
terrible (2 fps in average).
• The project.js file for Heroes was 60Mb
uncompressed.
Early days
• April 2015: Another try with official release
• Same results
• We are officially a mobile-only company
Early days
THE BREAKTHROUGH
Breakthrough
• Oct 2015: Facebook team pushes us to re-
explore
– We try again with 5.2.1
– We ran it and WOW!
– Performances for the game was at 30 fps!
– One main issue -> Massive Memory Leak!
Seeking support
• Given early positive result we fully
engaged ourselves to the port and
connected with:
– Facebook dev team
– Mozilla WebGL team
– Unity WebGL team
FROM PROTOTYPE TO RELEASE
DEMO
Issues to solve
• Raw Socket
– WebGL doesn’t support Socket and our game
used Socket to connect over TCP-IP to our
server.
– We installed “Sockify” on our server and
adapted client side to it
Raw Sockets
• WebSocket
– Concept it simple -> Wrap your raw socket
around an HTTP call.
GameLogic(TCP)
WebSocket(HTTP)
GameServer (TCP)
WebSockify(HTTP)
Raw Sockets
#if UNITY_WEBGLWebSocket m_socket = null;#elseSocket m_socket = null;#endif
#if UNITY_WEBGLbyte[] tmpBuffer = m_socket.Recv();int count = tmpBuffer.Length;#elsebyte[] tmpBuffer = new byte[m_socket.Available];int count = m_socket.Receive(tmpBuffer, 0, tmpBuffer.Length, SocketFlags.None);#endif
Issues to solve
• No Thread Support
– Game logic: used to run on a thread at a tick
of 10 per second.
– We had to profile a couple performance
issues in Path Finding related to this
decoupling.
Threads
• Network Thread
– Chat and Server communication
– Trick is simple:
• Remove blocking Socket read
• Check every update for something to consume on
the WebSocket
Threads
• Bundle Loading Thread
– Simply removing the thread wasn’t enough:
Threads
• Bundle Loading Thread
– Trick:
• Spread each bundles on different frame to let the
browser “breathe”
• Spread custom files parsing of each file on a
different frame. to let the browser “breathe”
Issues to solve
• Rendering optimization
– Basic performance was already good.
– But large armies/villages struggled
– On lower PCs, game could drop at 10 fps
Rendering
• Custom Batching
– Dynamic batching wasn’t great for us
– Issues with Shadows, Buildings
– We knew what should be rendered and
when!
Custom Batching
• Solution
– We pre-compute a large mesh with everything static at the moment and re-compute only when needed
– You get the best of both worlds• Equivalent of static batching but with the freedom
to add or remove objects dynamically
• You save all CPU needed to batch at every frames!
Issue to solve
• Player Preferences
- Player Preferences were not working in
Firefox within an iFrame
- This is going to be fix in FF 43
Player Preferences
• Solution
- We wrote our own abstraction using
localStorage capacity
- Only issue with Chromium or some plugin
limiting access to it
Issue to solve
• Issue with Music• Music was speeding and slowing down as we were
scrolling.
• We have no music in game today because of it.
• Thought it might be fix today!
Issue to solve
• Pre-memory allocation
– You need to specify beforehand how much memory your game will need.
– Recommended value is 512Mb
Issue to solve
• Pre-memory allocation– This value was too short for some of our scenarios.
– We made it 718Mb -> FAIL. We started to have player having this:
The browser could not allocate enough memory for the webgl content
Issue to solve
• Pre-memory allocation
– The sweet spot for us was 600Mb
– Some 32bits browser might still cap it at 512Mb
Issue to solve
• Forget about resource folder
– Everything in this folder will be downloaded in
the initial download
– In order to keep our initial download as short as
possible, we removed *everything* from
resource folder and moved them to Bundles
Issue to solve
• Bundles Download
– Avoid for now WWW.LoadFromCacheOrDownload
– Current implementation uses too much memory and produces lags during bundle decompression
– We did not see this with normal WWW request.
Issue to solve
• Full Screen Button Issue
– We had a weird bug with Full Screen.
– Don’t trigger it on MouseUp. Unity swallow the
event and doesn’t pass it down to the browser.
– Worked for us on MouseDown.
Issue to solve
• Debugging
– This is a tough one
– At least you have the console that provides some
high level information
– Forget about breakpoint (js file is too big for that)
Debugging
• One ugly way:
– Open JS file with Sublime Text
– Search for the function you want to debug and
add alerts within the function.
– This helped us on really tricky issues.
TO CONCLUDE
First results
• Game was released 3rd of December
– Facebook with WebGL only
– iOS
– Android
First results
• Launch Day Results - Monetization
– WebGL: $0.6 ARPDU
– iOS: $0.44 ARPDU
– Android: $0.26 ARPDU
First results
• First results - Retention
– iOS: 45% D1
– Android: 36% D1
– WebGL: 27% D1
Future
• What’s next?
– Hybrid version WebGL/WebPlayer
– User Acquisition