Apparently, if our infrastructure team leader’s pregnant wife can’t sleep, that means he also shouldn’t. Little did he know it will lead to an extremely productive night.


As all good stories start, this story also starts on a late Friday night.
All day long I was thinking about how to reduce the cost of our current logging stack, and at the same time improve the system.


Just to clarify, our previous stack included:

  • Redshift—as logs data warehouse
  • Custom self-made web dashboard—to view the logs
  • SQS—Async logs processing queue
  • S3—Saves the body of the log and its stacktrace
  • EC2 Instances * 5—Read the messages from SQS and save the data to redshift (meta fields: loglevel, short log description, timestamp and more) and S3 (error body).


So at 3am I launched a Linux EC2 instance and installed the classic log architecture: Logstash, Elasticsearch and Kibana, also known as ELK, with a few “wiring” configurations. An hour later I had a working logging system.


Now I only had to think of how to recreate the architecture in scale for a production environment while trying to stay as “AWS managed” as possible and with minimum custom code. So I combined the following services:

  • AWS ElasticSearch—managed ElasticSearch that comes with kibana built in
  • Kinesis Firehoselogstash replacement which allows me to stay async to the flow and has built in support to elasticsearch (and a few more tricks).


A few minutes later I had a running EKK stack that was fully AWS managed, but I found out that I need to solve a few issues before it’s fully production ready:

  1. Firehose, doesn’t support datetime field mapping. As a result kibana did not display dates and couldn’t do timestamp queries.
  2. Retire old data in ElasticSearch (TTL)
  3. Support Login Authentication to kibana
  4. Alert support in case something fails in the stack
  5. Analyze logs and create custom alerts.


That’s when the fun part started..

  1. Datetime field mapping—the fix is simple. I added a field named “timestamp” to the json that contains the value of epoch milliseconds. I defined a template in elasticsearch that maps all indexes named “logs-*” and predefined the field named “timestamp” as “datetime – epochms”. Problem solved.
  2. ElasticSearch Old data retire—Firehose insert the data to elasticsearch with daily index with the following name pattern: {indexname}-yyyy-MM-dd. For example: logs-2017-06-13. In order to keep N days all I needed to do is delete indexes bigger than N days. That can be done using simple Lambda that sends a http request to delete a retire index (method: DELETE url: {elasticsearch-url}/{full-index-name}. And a simple cloudwatch daily trigger rule that runs the Lambda and the data is retired as wanted.
  3. Kibana Login Authentication—Launched a linux EC2 instance and installed nginx and created a user. Defined a reverse proxy that all requests coming to the nginx will be redirected to kibana url but before nginx will ask for basic authentication. Next I assigned an ElasticIP to the instance and added the ElasticIP to elasticsearch access policy.
  4. Defined basic alerts using Firehose monitoring and S3 bucket to alert whenever a failed Firehose creates file (Firehose dump log files to S3 when he fail to insert ElasticSearch)
  5. Analyzing logs and custom alerts—Added Kinesis analytics to analyze the stream and give real-time stream analyses and defined alerts based on this.


That’s it for now… doing all I have written got me a scalable logging system that is fully manageable by AWS. To conclude, here’s a diagram of the system:




Leave a Reply

How a 520% Increase in Players Sparked Online Gaming Platform Pirate Kings Migration to MongoDB Professional and Cloud Manager

Pirate Kings is a fully realized world where over 80 million pirates battle it out to conquer exotic islands in a quest of gold, artifacts and revenge. Most players notice the palm trees, glimmers of gold, and the quality of the animation, but few think about the tools working behind the scenes to make the game operate seamlessly.

After upgrading to MongoDB Professional and Cloud Manager, we have scaled to easily manage 80 million users with 60% cost savings compared to our previous MongoDB hosting provider. While today everything is running smoothly, the path to success wasn’t always nicely paved – we had to fight our own battles to win the day.


Challenges of a third party database hosting service

Our team originally had experience with relational database technologies. However, we knew that a relational database would not provide the scale, agility and performance needed to make a game like Pirate Kings successful. MongoDB was the clear choice, though at the time, we didn’t know much about the operational aspects of running it. In the end we decide to work with a third party MongoDB hosting service to manage our database.

In the early days Jelly Button had a million daily unique users and, for a while, all was going well.

Suddenly, the game went viral and there was a 520% increase in users in just two weeks. The business was excited by this increase in popularity, though the engineering team got a little nervous about the latency spikes impacting the user experience.

Despite the challenges we faced, we initially did not want to migrate from our existing hosting service because of the amount of time and money we had already invested in the platform.


The final straw

Fast forward to February of 2016 when our existing third party MongoDB hosting service began to strangle our ability to scale and expand the game. We were constantly facing issues with performance, and the third party service was not able to help us address the problem.

At that point, it was necessary to move beyond a third party and instead work directly with the team that develops the database. We needed to find ways to better manage our data and scale to meet our growing number of users. We tried to make the transition on our own, but quickly realized we could accelerate the upgrade and transition by working directly with MongoDB Professional Services.

How MongoDB helped replatform our database and grow the business

Before the migration, we were facing exorbitant costs and had very little insight into how the database was performing.

MongoDB Professional Services worked alongside our team to successfully migrate Pirate Kings from the third party hosting service to MongoDB 3.2 configured with the WiredTiger storage engine in under two months. Together we were able to migrate, fix and optimize our database with little downtime. Our consultant was focused on teaching and mentoring the team, and the amount of know-how and technical discussions we had during this time were truly empowering. Working with professional services felt like working with true MongoDB masters.

Once upgraded, we saw a 60% cost savings and we were able to compress 18 shards down to one single replica set. With the transition to WiredTiger, the data size on disk dropped by 60% due to its native compression libraries.

MongoDB Cloud Manager, a platform for managing MongoDB, was also instrumental in giving us full insight into the database for the first time. With Cloud Manager we had much higher levels of data protection and lower operational complexity with managed backups. We were finally able to dig deep into database telemetry to understand the pitfalls that were inherent in our previous service. With MongoDB Professional, we were able to get direct access to 24×7 support.

Overall, the complexity of our database significantly decreased and our database administrators are able to sleep much better.

What’s Next

While the main motivation for migrating away from a third party hosted service was to better manage Pirate Kings data, MongoDB provided us the promise of a better life for our developers and a better future for our company. Today Pirate Kings easily manages 10 million unique players per month. Better yet, our team now feels very comfortable and confident with the technology.

Moving forward, you can expect to see Jelly Button develop two new games per year.

Leave a Reply

The story of  an event that Board Kings’ community participated in, that quickly built up into something that went over the top… Above… and beyond… everyone’s expectations!
(These puns will make sense soon)

Good board games are always a special treat. As anyone who ever played with friends anything from Monopoly to Settlers of Catan and Pandemic, knows how exciting and heated things can get.

That’s why for our second game we decided to take on the challenge of bringing board games to the app market, with Board Kings. We incorporated our unique Mingle-Play experience in it – mixing singleplayer with multiplayer, in a way that still keeps the excitement of playing it with your friends, without requiring all of them to be logged in at the same time in order to play this board game.

But what we’ll tell you about this time is about a pretty whimsical Community+In-game event we held for our player community: Tower Day.

It was inspired by a few screenshots our players posted on social media, showcasing the fact that once two game pieces (We call them Idolz) are simultaneously on the same tile, they stack up on each other. So the idea of holding a “Build the biggest idol tower” event was pretty inevitable at this point.

We expected a few real life friends will coordinate in a team effort via Facebook/Whatsapp, then choose which of them will be the host and the rest of the team will travel to his board to start stacking up.

But then this happened…

Mason Spink was among the first to comment, but his true genius was that he invited EVERYONE to come to his board. And it worked.

From there it quickly built up into a tower that went over the top and above and beyond anyone’s expectations! Very fast! At least 234 new buddies traveled to Mason’s board and stacked up to erect this Frankentower monstrosity! Reaching for the sky and ending up going through the roof! (Sorry, couldn’t resist the puns)

Then they commented on his thread with screenshots of them joining the tower. These screenshot unfold the rapid growth and amazement they shared seeing it happening.


This goes on like that for over 300 comments – see all here.

It was awesome to watch this thread becoming a kind of forum for all involved in this epic tower and how perfect strangers had a common topic to talk, laugh and be amazed about.
You can see it became a passion project they all were very proud to contribute to.

In terms of interesting effects on the game during the event –
The obvious metric which showed significant growth is the amount friends approved:

  • Friends approved per user – up by 120% (!)
  • Average session count – up by 15%
  • Average duration in game – up by 25%

We can already tease that we have more where that came from – hoping our players will be into it as much as they were this time. This inspired us to come up with similar events and next up we will focus around creating the most creative idol combos (Also influenced by a player’s screenshot of a Polar Bear idol with the swagger diamond idol on top) and also to fill all the tiles on the board with idolz… 

Stay tuned!


1 Comment

  1. Jinny S.

    I play the pirate kings game. Have several islands because I love it so much❤ When boardkings came out I was quick to sign up, but then I realized I needed to dedicate play time to my Pirates. After reading this page (the story on the idol tower build) I feel very curious…I may try it!

Leave a Reply

As a data-driven company, we understand that data insights are essential to optimize and improve our games’ potential. There are a myriad of aspects to incorporate when designing and implementing a Business Intelligence system and anticipating major viral growth.

As the founder of the BI department in Jelly, I will shed some light in this post on the entire design process and share valuable industry insights which have guided me throughout these implementations.


Define and prioritize your BI system requirements

Prior to writing any scripts you must define and prioritize the requirements.
Every system aspires to leverage the most value to its company.

Many startup companies face the challenges of minimal manpower and budget constraints which often slow down the implementation process. Moving forward while making decisions can be tricky, especially since endless products saturate the market these days. With that in mind, we’ve defined specific elements for our Analytics Data Warehouse which we refuse to compromise on.


Here are our non-negotiables:

  1. Database in the Cloud – The data warehouse must be in the cloud as it saves all the administration and maintenance tasks. Column-Oriented technology has huge advantages over the Relational Database method. Namely, that it improves the overall performance and is infinitely more cost-effective within the Big Data domain.
  2. Scalability – A successful game can lead to tremendous growth in the number of users who generate massive amounts of data. Therefore, the system must be adaptable in order to handle this challenge.
  3. Usability & Operation – Using “SQL Like” language is common. Vast operational opportunities, such as API scripts, allow developers to execute queries or schedule jobs. Web Console access and command-line (CLI) help us manage the database more easily.
  4. Cost – “Pay-as-you-go model” is typically most economical. This way, we only pay for the queries we execute and the data we store.
  5. Security & Support – Data security is one of the most important features for any given database. The product should not only be secure and supportive but continuously improve and adapt to technological progress.



Design your Data Structure & System Architecture

Virtually all companies are using Big Data. We live in a day and age where we want to know everything about our users. We generate large-scale events and logs which creates a major challenge: How to process and store ALL this data? I believe the solution is hidden in the Data Structure and System Architecture. To make data usage more efficient for end-users (Data Scientists) the data-structure must be well-defined.

In addition to saving our original raw data, we decided to reduce the data dimensions by generating periodical Aggregation Panels which provide answers to 95% of the most common queries (KPIs and such). The Lifetime, Yearly, Monthly and Daily Panels are agile which enables analysts to perform fast and efficient data-mining.

Our System Architecture is based on the following components:

  • BI server
  • Querying jobs
  • Data Warehouse
  • Logging & Alerting jobs
  • Dashboards and reporting


The advantages of these solutions are that they all require simple implementation, reduce maintenance time, are easy to operate and are widely accessible even via smartphone.
System’s Data flow – Collecting the events from the client via ETL into the Analytics Data Warehouse then distribute the aggregated and processed data to the client via reports or Dashboards.


It is not enough to develop and implement all the components of this independent system from scratch. The next challenge is to synchronize all the jobs, set all the backup scripts which validate the performance of the BI system and reconcile the data. One must be meticulous, see the whole picture and expect the unexpected. This way one can best prepare for any hazards that emerge creating system instability and quickly remedy them. Fluent operation is required, whether it be spotting new trends, discovering and reporting new bugs or spreading the processed data to various departments.


How Jelly Button Conquered and Adapted to the Viral Growth Challenge

In our games we encourage players to connect to Facebook to maximize engagement and fun. When a player progresses in the game it is satisfying in and of itself, but it is even more enjoyable to compete with your friends and directly affect their progress in real-time. This mingle-play format motivates players to invite their friends to play while helping us spread the game virally.

On February 2015, we faced a viral growth. A huge amount of Daily installations and high retention increased the DAU from 1M to 4M.



Growing with the Data

Due to the viral nature of our games, we spread in rapid spurts which created a huge spike in the number of installation leading to massive growth in our Daily Active Users. This scenario was evident in multiple countries in Southeast Asia. So how exactly did we deal with this complex challenge?


Aggregation – Big Data Solution

Tremendous growth in the number of events forced us to stick to data-streaming solutions which regulates the volume of events and simplifies the ETL processes. Instead of querying billions of raw data events again and again daily, we stick to reducing the dimensions by aggregation solutions. In doing so, we process the data only once then store it in our Daily Panel. Aggregating data this way is optimal and once again reduces cost and increases performance levels with minimal maintenance. It is very easy to adjust and modify the panel which stores every KPI an analyst would ever need.

Aggregate all the daily events from the FACT table into single row which summarize each user activity per the Date he played


Summary & Tips

There are many tasks to implement, analyses to perform and scripts to develop but unfortunately we cannot do it all. Before executing, be sure to prioritize and ask yourself these three simple questions:

  1. Is the solution simple?
  2. Is it efficient?
  3. Will it be sustainable in the long-term?

Remember: good planning will reduce the tasks ROI in the aspects of endurance, stability and reliability and will save you ample time in the future. Well-planned scripts can last for years to come.

1 Comment

  1. Roey S

    Great writing!
    Glad to see the “user panel” approach implemented here. This is a great way to support quick analytics and insights and to support performant reporting.

Leave a Reply

Free of business responsibilities, our team lets loose for 2 days and builds 3 small games. Here are the tips and stories behind what happened.

Last week was Global Game Jam! For all of you who don’t know, it’s an amazing world-wide experience where small teams of all different backgrounds, skills, and experiences create games in 48 hours. It’s not a competition–it’s a collaboration. For us at Jelly, it’s a break from the norm, and an opportunity to imagine. This is a space where we could purely be creators and experimenters. We sat down with 3 team leaders–Ron (our CTO), Moti (our Chief Creative Officer), and Barak (our Game Designer)–who explained what the experience was like.



Top: First brainstorm meeting for all teams. Left: Every idea was written on the whiteboard. Right: The whiteboard after the group brainstorm session.


How did you break down the 48 hours?

Barak: We arrived at 10am and waited until GGJ revealed the theme of the game we were supposed to build around. Once we heard the theme was “ritual,” the whole company gathered at a white board, and people wrote down their ideas. Then, people just joined which game sounded most interesting to them. My team sat together for 2 hours to talk about the basic idea of “We Are Bound” and tried to condense the scope. The idea was really ambitious and we needed to scale it down. It was also amorphous, so we needed to refine it into something playable because it wasn’t really a game. We thought about what we wanted to achieve and the basic mechanics. Then we started to break it down, and created small tasks assigned to each teammate: development, art, animation, balancing the game, sound, etc.

Ron: So we spent 30 minutes talking about how we wanted the game to be, and then moved forward. I learned a strategy last year that I tried to apply this year. The first day is to complete the basic R&D. It might be the ugliest thing in the world, but at least it works. Then on day 2, we refine it and integrate art, sound, etc. and that way at least the pyramid won’t topple.



Top: Task breakdown for team-members. Below: Environment layout with interactions.

What steps were essential in these 48 hours?

Barak: Finding something that can be scaled down and being honest about it.

Ron: Choose an idea, develop it, break it into components, and then assign tasks to each person who can work on them in parallel. Basically, make sure that everyone can run as fast as possible without blocking anyone. Last year, we kept stepping on each other’s toes and working on the same things. This year, we spent 30 minutes talking about it (how it should look, feel and behave), then we broke it into the critical paths so we knew what we absolutely needed to finish and made parallel schedules so we didn’t get blocked. If someone is blocking, it’s always bad.

Moti: Making sure you have a product that suits the team members. Build the product around the qualities of your core team. In my game, we decided not to have a lot of user interface, but to be very 3D-oriented experience because we had solid 3D artists to build it.


When I make a game throughout a year, I have very specific business plans and thoughts involved in every step. Here, I am free to do anything. That’s what’s special about this event. I’m not bound by any conventional methods of creating something that should bring revenue or change the world. I just play.


Is there a different kind of satisfaction in making a game in 48 hours rather than over the course of a long period?

Barak: To create a game in such a short period of time is fulfilling. It’s better to have a game than a grandiose idea, and to finish it is immediately gratifying.

Moti: You’re trying to achieve different things. I don’t have to justify this game making money. So automatically I’m free of all of these things and I can try to do whatever I want. It’s very easy to get carried away because you aren’t bound by anything, and that’s where time gets lost. You’re so passionate about doing this thing you are free to imagine, but it’s hard to cram it down in 48 hours. Every year we make the same mistakes, but also learn about them. It’s really hard to build a work timetable for such an abstract project usually. Either you’re trying to cram in too many features and you won’t make them and half a half-baked product, or you’re trying to do something technologically advanced and you don’t know how much time it will take you to do it.

Ron: Without thinking about monetization and whether people will like it, it’s a lot easier. You are more faithful to the product, but it’s more of a proof of concept or a toy rather than a game.

The 3 games that were made here at Jelly are totally different. We could have realized that we all made something similar, but we didn’t. What do you think that says about us?

Ron: I think it shows that we have different imaginations and want to try new things. We aren’t all brainwashed into doing the same thing.

Barak: It makes perfect sense to me. We are good at what we do and love games and there are always things you want to try to do outside of your immediate responsibilities. If we all ended up making the same game at the end it would be awful.

Did you sense that people you worked with expressed themselves differently during the GGJ than during regular work days?

Moti: As a company we are very collaborative so it makes sense that people worked together the same during these 48 hours as usual. I think it does something in the long term for us, because people have a moment to see possibilities of what else can be created.

Barak: It’s great to feel you can experiment beyond your normal tasks. Marketing people or CRM people get a chance to see the micro-process of making a game in a nutshell, and really experience hands-on gamemaking. People also get to work with others they don’t usually work with.

Ron: It’s training the creativity muscle. It’s the one place where it’s totally acceptable to fail and make a mistake. You might be bummed, but nothing bad will happen. It’s a safe environment for people to do different stuff, even for a totally different medium (Xbox, boardgame, etc.).


Top: Kids are the best judges. Left: Presenting the final product. Right: Screenshot from Moti’s game.

What were some lessons you learned?

Ron: Finalize an idea as quick as possible. Choose your path, and then never change specs in the middle. Maybe 1% or 2% can change, but any more change will result in something that doesn’t work. I want my basic concept to be playable even if it looks terrible. You really need to know how to choose your scope and quickly think of what’s feasible to achieve in such a short period of time. There’s always editing and separating what’s important from what’s nice-to-have.

Moti: Yeah we wanted all the drawers to open and close in our game. We spent 5 hours modeling and texturing things that could be opened and closed. In the end, our developer didn’t have time to implement this function so all this work wasn’t seen by the players. It’s hard to see what will be in the game or what will be left out, and this is why it’s such a good test of our prioritization. Also, on the first day we had a really great art reference for what we wanted to make, but in retrospect it was impossible to do in this amount of time. By the end of the 1st day, we had accomplished maybe 10% of the goal, so on the 2nd day, we cut if off and did something more simple, and that’s learning to adjust with the situation.

Barak: We spent our first day only on AI, which was a big scope but the result was amazing for us. It was a huge time blocker even though it was just a small amount of the whole game, and it got us really stuck. But, our initial purpose was just to experiment. We didn’t really care to finish the game so it was a success.

What kind of experimenting did you do?

Ron: It’s the first time we built a game with levels…or at least an abstract level progression. But it was based on sound. As the beat increased, the level difficulty increased too. Yoni, who does QA for Pirate Kings and is also a drummer, recorded bars of 4 or 8 seconds that got increasingly more complex and essentially built a level. We designed the code to match the complexity of the beat, and would drag and drop them as either “simple” “medium-simple” “medium-hard” or “hard” and that’s how we built it. I think he really enjoyed it too because he was a part of this experimentation process.

Barak: Focusing on AI was really fun and something I’ve wanted to do.

MotiWhen I make a game throughout a year, I have very specific business plans and thoughts involved in every step. Here, I am free to do anything. That’s what’s special about this event. I’m not bound by any conventional methods of creating something that should bring revenue or change the world. I just play.


game_1The List

“People with OCD feel they can control their anxiety only by performing the ritual. The game puts you in the shoes of a person with an OCD for order and repetitive habits. You wake up in the the morning ready go to work. But before you can exit the door, there a couple of things you “must” do first. The game mixes “Hidden Objects” mechanics with an “Escape the Room” game style.



VooDO or Die

“For this project we recorded a drummer who gave us a beat, then used DSP algorithm (Using FFT) to read the beats into a JSON file, where later it was played on the actual game. Playable on a PC, and controlled by players either by console controllers (XBox/PS), or by using the dedicated Android application on mobile.”




We Are Bound

“The god and his disciples are bound to each other, you need their prayers and they need your divine help. On the holy day they will pray to you thus replenish your power, use your power during the week to help your disciples and make their belief stronger.”




Stay tuned! Next month, we are recreating this experience in the company for the first annual Jelly Jam! More exciting stories and behind-the-scenes to come 🙂

1 Comment

  1. April M

    AKA sourgrapes I just wanted to let you know that I love pirate kings and I enjoyed your blog it was very interesting keep on creating love the team

Leave a Reply

What I see most in all the game design tutorials/articles I’ve read is a list of what my game should include. I’m a game designer, so this is my bread and butter. Most of the bullets are very straightforward and very understandable, but there is always this one element that slips away like it’s just another factor to consider lightly:  “Make your game fun.”

This is a big deal! Finding out what that “fun” factor everybody is talking is about can’t possibly be that easy. That’s what this blog is about.

Let’s start with the definition of fun:

Not that helpful. It’s short, very abstract, and subjective. For instance, the idea of fun for one of my friends is to go on long hikes; for me, the idea of hiking sounds like a torture. Alternatively, shooter games could be fun for one person, whereas puzzle games are fun for someone else.

I didn’t like Candy Crush Saga that much, but it’s one of the most successful games ever made. Of course, people can say that King uses clever psychology to access the pressure points of the player, and that their level design is built out of difficulty peaks to control the player’s pacing, satisfaction and frustration. But again, none of these “tricks” would’ve worked if the core mechanic wasn’t good or “fun.” So we are back to deconstructing what fun is.

Does my lack of connection to Match 3 genre games make them not “fun?” No, it just means that fun is interpreted differently by different people.


MDA framework

The MDA framework was written and defined by Robin Hunicke, Marc LeBlanc and Robert Zubek back in 2001. It stands for Mechanics, Dynamics and Aesthetics

Even though I didn’t invent this framework, this is something I modified and use on a daily basis with my own personal agenda, and which I tweak according to what I imagine, or when I try to explain features I’ve designed. I think it’s one of  the best tools I’ve come across, and even though there have been countless attempts to rewrite and modify this framework, the fundamentals are worth studying:


This defines the set of rules of the game. Basically, a set of rules that define the boundaries of the game.

A particular component of the game, at the level of data representation and algorithms.
Mechanics are the various actions, behaviors and control mechanisms afforded to the player within a game context.

Crossy Road’s mechanics includes: moving forward, backwards sideways, automatic screen scrolling, moving platforms and objects etc…



How the player can “function” within these rules. Basically, what we as game designers can do within the very rules we created, in order to enhance the player experience.

Describes the run-time behavior of the mechanics acting on player inputs and each other’s outputs over time.

Crossy Road (again) are using the Gacha machine in order to create curiosity anticipation for the player.

Mario Kart uses the Blue shell, AKA  “The Great Equalizer,”  making it both the most hated (frustration) and most desired (anticipation) item of the Mario Kart series.



They help us define what the players’ feedback (or feelings) are from our game, or from a specific in-game feature.

Describes the desirable emotional responses evoked in the player, when he interacts with the game system.

Common sense would suggest that aesthetics are a visual aspect. In my opinion, it represents feelings and how they correspond with the game flow–they are emotions.

In the paper, they mapped the word “fun” into 8 different meanings to make it easier to grasp:

  • Sensation – Game as sense-pleasure
  • Fantasy – Game as make-believe
  • Narrative – Game as drama
  • Challenge – Game as obstacle course
  • Fellowship – Game as social framework
  • Discovery – Game as uncharted territory
  • Expression – Game as self-discovery
  • Submission – Game as pastime

I liked the general idea of breaking down
fun into feelings, but here is how I broke it down even more to help better understand the process:

  • Excitement
  • Anticipation
  • Completion
  • Anger
  • Curiosity
  • Satisfaction
  • Frustration


*And of course, any other feelings that I find relevant according to the game vision.


Here are some examples of aesthetics in some selected games:

Clash of Clans: Fellowship, Expression, Challenge.

Pirate Kings : Anger, Sensation, Competition, Progression.

Don’t Starve: Discovery, Fantasy, Expression, Frustration.

Candy Crush: Fantasy, Progression, Competition,Challenge, Submission.

Another point that the MDA framework helps us understand is the difference in perspectives between ourselves (the game designers) and the players.

As developers, we tend to think about the mechanics first, and how they will lead the player to the dynamics and eventually to the aesthetic feel. Players, on the other hand, tend to talk about a game in reverse: discussions will usually begin by describing the aesthetic side of the game, then the dynamics, and maybe the mechanics (depending on what kind of gamer they are).


MDA Framework Tested With Pirate Kings


As you can see, I used a different set of emotions than what they defined, but I believe that every framework should be modified to fit your system.


How To Test Your Framework

  • After defining your game by using a workflow, you should try to reach a playable version as soon as possible (even using placeholders for art).
  • Play it and try to be as honest and objective as you can be about what it makes you feel and if it matches your intention.
  • Let people play your game as soon as possible. Try not to help or guide them, and see what their reactions are. I did this by creating a detailed survey.
    Start with your inner circle–people you trust both ethically and professionally, and as time goes by, expand that circle.
  • Even if the reactions weren’t what you expected, always ask why, and always keep in mind that maybe your game just didn’t fit that type of gamer (which is cool).


In Conclusion

All this is just my opinion, and the sharing of my intimate workflow, so you can feel free to agree or disagree. This framework doesn’t replace game core loops, game flows or a creative process, because it comes as a layer on top of all that. It helps roughly define what will be fun for your players, and what reaction you should expect to get from your game features. You don’t have to use it in the same drilled-down way that I just showed. You can approach it from a more high level aspect to help you and your team better define the meaning of the word fun for your game.

I hope it’s useful for you, and that you are able to take the basic elements of what I’ve written and modify it in the most convenient way for your purposes.

If you have any comments or questions, please write them here!



Our team is hiring! Check out our open positions here.



  1. fedor

    Although true at every point the article doesn’t present a systematic approach to the concept of “fun”.

    Books I recommend to read if not done so already:

    Raph Koster, “The theory of fun”
    Steve Swink, “Game feel – a game designer’s guide to virtual sensation”.
    Daniel Cook’s insignt on loops and arcs:

    if you’re interested in something mindblowing then:
    Chris Crawford, “the dragon speech” given in 1991 still to come true.

    • Barak

      Thanks for the leads Fedor.
      I have red “Game feel – a game designer’s guide to virtual sensation”, i’ll check the rest of them.

  2. Enjoyed the post!
    Much as you guys say; fun is a poor word for use in game development. It’s a linguistic catch-all for all kinds of things.

    The MDA Framework seems a move in the right direction! Though I’m sure it’s not the end of story. It doesn’t seem to cover things like the joy of discovery or mastery which are core experiences in many games.

  3. Thanks for sharing great tips and its really such a nice post!

Leave a Reply

We’ve recently hosted a meet-up at our offices and presented a lecture about the development of real-time multiplayer games using Unity3d. To keep sharing the knowledge, we’ve linked the presentation and the GitHub project here so you can get a small taste of what it takes to develop a multiplayer game, with direct focus on the FPS client model and authoritative server model.

In the slideshow we explain a bit about:

  • The progress of real-time multiplayer games over the years
  • The authoritative server model
  • A few common lag-compensation techniques and how they work
  • The new UNet framework for developing multiplayer games



1 Comment

  1. I couldn’t resist commenting. Very well written!

Leave a Reply

Branding your company at an event is creative positioning. It is the opportunity to have someone
experience you the way you want. It’s about aligning an interaction with your company values and brand.

Why is this important? Because branding is not pure marketing. It is a feeling and a memory which can galvanize people. This can make all the difference sometimes, because if you can be approachable and likable, and not just a salesperson, people will want to remember you. Shoving your logo in their face just doesn’t do it, even though it might be easy.

This blog post explains how we leveraged a small opportunity into a big success by being creative, and very specific in our branding efforts. In the end, you’ll see 7 tips on how to tackle it yourself.

Our Story

Israel’s first ever Casual Connect conference was scheduled in Tel Aviv between October 19-21. This was very exciting here because it focused world attention on our emerging industry, and because it was our opportunity to familiarize people with our company. Until now, most people knew us by Pirate Kings, our game. We wanted them to know us as a company.

Just for some background, the way it usually goes with conferences is you can spend a lot of money for big exposure with a sprawling booth space, banners, and your logo smacked all over the place. This doesn’t work so much for us for 3 reasons:

  1. It’s expensive and not very controllable (in terms of scope and presentation)
  2. It’s a very forceful, loud kind of branding, which isn’t like us
  3. There’s got to be a more creative way of getting exposure

We accomplished this by 2 forms of brand awareness: we did all the graphic design for the entire event, and built one of the most approached, and talked about booths of the entire conference even though we had the smallest and cheapest booth space available. For 3 days, 10 hours a day, our booth had a long line, and everyone walked around showing off their prize (our logo). Here’s how we did it.


The Start

We started this process three months before the event with a big meeting to toss around what we wanted to accomplish with our presence. The conclusion was brand awareness. What does that really mean? In our first meeting we discussed a creative approach to positioning. This is where we reiterated the company values/pillars, where we chose to focus on the company brand rather than our game title, and where we first started talking about what we wanted people to feel. It’s also where we solidified the intent of the conference, and what we wanted to get out of it.

Laying the Groundwork

Everything gets further broken down into tones and emotions:

  • How to demonstrate what we’re all about through characteristics like: growing, different, agile, cool, creative, thoughtful, playful, humble, successful, confident.
  • A lot of discussion about how to show our logo/name, or not. How to express ourselves noticeably without just boring logo placement.
  • How do we want to appear? What do we want them to think about us? What do we want them to feel?
  • How do we remain approachable and fun while also professional and serious?

For about 4 more weeks we designed, redesigned, brainstormed, and kept checking if we were remaining true to our values, and trying to provoke the right emotion. You can see the outcome after a series of about 30-40 booth renderings we designed.




The final design

The Outcome

What we had in the end was a custom-designed toy claw machine inside which were plush toys we had custom-made in China. Each toy had a designed tag with our catch-phrase and our website. All this stood within the context of a booth space.

Everyone from security guards to employees of other companies wanted to come to our booth, wait in line, get one of our toys for free, and show it off at their booths. All over the event, you could see our toys and stickers floating around, and people gathering around us. It was a Jelly Invasion, in the most friendly, generous way.



Here is the booth, the toy machine, and the toys all over the conference.


Hilarious Grunt Work

It’s hard to do all of this with a team of 2-5 without any solid experience. You’ve read the conceptual challenges, and now here are just a few of the real-life challenges we faced:

  • driving an hour north to a man’s house (+ his three baby daughters) to bargain for an arcade claw-machine to  rent and alter
  • 2 months, 106 emails, and 8 production samples with a woman named Alice, from China, whom we met through Alibaba, to produce 2,000 plush toys in the shape of a jellyfish
  • hiring an import agent and processing Israeli customs for our shipment
  • befriending a local neighbor who is an art director/set designer for commercials and music videos to build the booth we designed
  • working around 4 weeks of national holidays and vacation schedules
  • producing business cards/special stickers for the event

Maximizing Exposure and Minimizing Costs

Aside from our own booth space, we had another secret weapon for increasing exposure without paying lots of money. Since we are a company full of designers, we offered the conference to let us brand the entire event. We had already been asked to brand their Singapore event, which we did using Pirate Kings as the theme. They wanted this time to be different from Singapore. We asked ourselves: how can we twist this to our advantage for brand awareness, while providing them with an exciting design for free?

This was the outcome:



This cover was printed on each pamphlet for every attendee, providing maps, lecture information, etc. We also provided a Powerpoint template on which every speaker’s presentation would be based, an email signature, and name tag.


How You Can Do It:

Effective branding is not always about being loud and broad. At its best, it creates an enjoyable experience which leaves someone with a nice memory. As an example, we continue to receive pictures from people whose kids are sleeping with them in bed, or from employees of other companies who have them on their desks. This is success!

Here are some pointers for tackling something like this yourself:

  1. Answer the big questions first: What are we trying to accomplish? What will they walk away thinking about us? How will we look in comparison to the other players there?
  2. Who is the audience? Business people? Gamers? Creative people? And, what is the best way to reach them and make a memorable impact?
  3. Next, dig deeper to a more creative level to which attributes, characteristics, and tones you are trying to encapsulate.
  4. Sketch out the space you have available (preferably in a room so you see what you’re working with, and preferably also a 3D rendering), and outline your budget. Spend the next few weeks letting all different ideas come out on paper/computer.
  5. Always be asking yourself “What does it say about us?” when you’re playing with ideas, colors, and themes. Make sure it aligns with the original objective.
  6. Face complex, sensitive concepts but walk around them finely. Example: mysterious yet approachable; small yet not too small; creative but not childish.
  7. Try to imagine yourself “seeing” your idea as your target audience. Will you be excited? (Try to be honest with the answer.)


"If you build it they will come"

“If you build it they will come”


See more pictures





  1. Thanks for the jellyfish! It really was a brilliant idea. I brought the toy home, and my 2-year-old loves it, so it’s always somewhere around the house.

  2. Yes, the plushies were a lot of fun.
    Yes, I visited your booth, more than once. First taking some stickers hoping for a shorter line, then to play the game and get myself a plushie, and when I lost my plushie somewhere between the show and the party, to get myself another of these jellyfish (this one made it home safe.)

    Not once was I approached by anyone manning the booth, to try to figure out why I was at the show.
    I find it difficult to approach strangers, even though the number one reason I go to these events is to network, and I feel like there was a missed opportunity there.

    It wasn’t just Jelly Button though. I felt like there were a lot more instances where I grabbed a freebie from a booth, gave a little nod a walked away without a word then at some of the other developer conference / trade shows of been to.

  3. JP

    Greetings Mate’s!

    I have been playing Pirate Kings for some time and was hoping you would be able to send me a Jelly Button plush to enjoy and promote your brand! Please advise.

    Thank you!


  4. Alisha Hough

    How can I purchase your toy brand?

Leave a Reply

In order for us to reach the broadest audience, we need to support as many devices as possible, and in order to do that we are constantly thinking about optimization. We try to optimize our drawcalls, textures, models, code, servers and everything else we can, plus we try to find new ways and ideas to improve our visuals while trying to use minimum of the devices’ resources.

One of the solutions we found was vertex color.

In a 3D model, each vertex can be assigned with an RGBA value that is saved with the model without the need of texture. That way, it is possible to save memory for basic coloring of an object. It is also possible to create gradients between vertices with vertex color (for more info click the ref links at the end).

We discovered a few tricks which, when combined together, can have great results.



Faking Light With Vertex Color

We don’t have dynamic lights in our game. We only use one ambient light in the scene where all the shadows are baked. So, when we used vertex color on the bucket asset, we had to add fake lighting.

We first started by selecting the colors for the asset in Photoshop since it’s much faster to make final tweaks and adjustments. Afterward, we sampled the colors and applied them to the model with vertex color.

Vertex colors can only give you limited coloring options, and we needed to add textures, so we found that we can combine three grayscale images into one RGB image. We decided to give the model coloring and lighting using vertex color, so all the wood and metal textures would come from one single file. You can see at the result in the Sketchfab viewer below*. In Unity, we created a custom shader that could tell the mesh which texture (channel) to multiply on what polygons.

Here are a couple examples of different approaches for texturing models. Each has its advantages (+) and disadvantages (-).

Classic Approach (used by most games): 
no vertex color, just RGB texture

The classic way to work on it is to UV the bucket and paint the highlights, shadows, colors and texture directly on it. The disadvantage of this way is that the texture will be a lot bigger, and require too much from the device memory.

+ Creative freedom for the model’s texture
+ Ability to bake lightmaps on top of it
+ Straightforward workflow for UVs/texturing
+ Supported by all 3D software
– Waste of texture space (and device memory)
– Hardly reusable for other assets


Hybrid Approach: 
vertex color as grayscale light + RGB texture

We haven’t used this method for ourselves, but another thing you can do is to use vertex colors in order to create highlights and shadows and use an image to give the bucket the flat colors and textures. It is also possible to bake AO into the vertex color values (requires a more high poly mesh).

+ Reusable texture
+ Ability to bake lightmaps
+ Straightforward workflow for UVs/texturing
+ Smaller texture size
– Not supported by all 3D software|
– More technically complicated workflow


Super Hybrid Approach:  
vertex color as light and color + grayscale texture

For this, we painted the bucket with vertex color and used one image which had the textures side by side. The resolution of the texture was 256×512 which was too big for what we wanted.

We found out that Unity converted grayscale textures to RGB**, resulting in more memory waste than in grayscale (three channels vs. one).
** other game engines may support one channel grayscale textures.

+ Reusable texture
+ More creative freedom than previous method
+ Smaller texture size
+ straightforward workflow for UVs/texturing
– Not supported by all 3D software
– Even more technically complicated workflow


Ultra Super Hybrid Deluxe Approach:
Vertex Color as Light and Color + RGB per channel texture

By combining the two grayscale images into one RGB texture, we used less memory with only one texture of 256×256 and still maintained our wanted creative freedom. We even got an unused channel (B) for future needs.

+ Smallest texture size
+ Reusable texture
+ Same creative freedom as previous methods
+ Not supported by all 3D software
– Much more complex UV/texturing workflow
– Needs a more complicated custom shader



*The gold pile/coins in the model use a different texture in our project.
*For other reasons, we decided to simulate the final outcome with texture, and not use Sketchfab’s vertex colors.


In conclusion, vertex colors can help you optimize the game and get great results, and you can also use them to control shaders and blend different textures, but that’s for a different post 🙂
We recommend you try this method but make sure the software you’re using can support it. Below is a list of some software and what they support (as of the date of this post):

  • Maya has full support for RGB for colors, and A for alpha
  • 3DS Max has full support for RGB for colors, and A for alpha
  • Blender only supports RGB. There is no alpha channel
  • Cinema4D only supports black and white using the weight maps when exporting FBX

* It’s important to mention that this technique may not be usable if you’re planning to bake lightmap on top of your model.


  1. Thank you very much for this one, Eran. I’ve never really got into the vertex color thing as there was no need in it for me, but always was curious about it. Now this post is just made it clear. Much appreciated.

  2. Hey! nice post, open my eyes to study more about vertex colors. I did some experiences in Blender and Unity.
    and find some cool ways to use vertex colors.
    But I didn’t find a way to achieve the last example, divide the mesh to load just one channel of the texture ( one area load the channel with the wood texture, other load the iron texture) i just find documentation about using the RGB from vertex colors like its being used commonly for terrain mixing of rocks.. grass.. sand.

    I imagine the idea is to use only one material. and use one UV mapping. leaving a second one to the lightmap bake. any tips about that will be very useful and thanks for the inspiring post.

    • Eran Caspi

      Hey Victor,
      I’m glad to see this post helped you. I’m not sure I understand the question, but if you need some help
      with the shader I think you should ask in the unity forums since I don’t know how to code shaders :\
      Anyway you should also check Andrew Maximov Site, he has some examples in Unreal engine about similar
      technique and maybe it can help you to understand the logic behind the shader.

Leave a Reply

My intent in this post is to share my perspective on the subject of “Clean Code” and promote the understanding about the need for this practice. There is an old adage: “If you want to learn a subject, write a book on it.” While I’m not writing a book, this is still is a learning experience for me, and, hopefully, for you too.

Most of the inspiration on this subject is taken from Robert C. Martin (aka Uncle Bob) and his books about clean code (Clean Code and The Clean Coder). If you haven’t read these books or don’t know who Uncle Bob is, I suggest you do so as soon as possible (right after reading this post ;)). Also, check out his blog, which has really interesting topics.


Clean code is about how easy it is to read the code that you write. The known joke: “It was hard to write it, it should be hard to read it,” constitutes the main problem of code in general: it is hard to read code. So, our main concern is to make the code readable by people. To make your code more understandable, you’ll need skill, practice and, most importantly, the understanding of how clean code looks.


I won’t tell you that variables and functions should have meaningful names–that’s obvious. I will tell you, though, that the name of a function should convey its intent, meaning that when you read the implementation of a function you should say “well, of course it does that.” And, while conveying the method’s purpose is important, don’t use very long names, because even with today’s 23-inch wide screens, a long method name is distracting. Besides, if you do have a long method name, it usually means that the method does too much (see “Small Methods” section later in this post). As for the variable names, they should be short and to the point, but without losing their meaning.

If Statements:

“If” statements should be as simple as possible. Don’t put too many or’s and and’s into it. Try to put the most simple bool variables. If there are a couple of check variables, move them into methods that encapsulate the boolean logic. Reduce the nesting of the “if” to the bare minimum by setting breaks and return statements where possible.

Small Methods:

It can’t be overemphasized enough that all the methods you write should be as small as possible, and should follow the single responsibility principle (Solid). Small methods contribute not only to readability, but to good design practices and code structure in general. It’s easier to understand smaller methods because the smaller it is, the less complexity there is to see. Therefore, it has less cyclomatic complexity.


Everyone loves a well documented API, and everyone suffers when it isn’t well documented ( Unity3D developers suffer a lot). But, comments should be used sparingly. A redundant comment hurts readability and, therefore, the understanding of the code. Another reason for writing less comments is the fact that they introduce duplication. As the life of a project progresses, many of the classes and methods change behavior, but the comments accompanying them are often left behind to the point where they become inaccurate, or worse, plain wrong. I’m not against commenting, though. There are times when it is absolutely mandatory, such as: a complex algorithm or other computation of things, a design decision and reasons for it or a public API that will be used by other people. Just use it with caution, because sometimes a well named method or variable is better.


The most important thing about conventions is that everyone on your team should follow the same ones. It is helpful, however, that you follow the standard convention of your language and have tools to enforce it. One of the major reasons is that it promotes clearer communication between developers and removes a “context switch” in your mind when looking at your teammates’ code. Standard conventions also helps new team members integrate more easily into an ongoing project.


To summarize this post, let’s review the following example (taken from a real world project). It is written in C# in the context of Unity3D, however the ideas behind them are universal and language-agnostic. Consider the following:

private List<OneShotEffect> _effectPrefabs = new List<OneShotEffect>();

public void PlayEffect(Effect effectToPlay, Vector3 worldPosition, float? duration = null)
    foreach (var oneShotEffect in _effectPrefabs)
		var effectToPlayName = effectToPlay.ToString();
		var checkEffectName =;

		if (string.Compare(checkEffectName, effectToPlayName, StringComparison.InvariantCultureIgnoreCase) == 0)
			var instance = (OneShotEffect)Instantiate(oneShotEffect, worldPosition, Quaternion.identity);


At a first glance, this method is not that bad because it is relatively short and readable.Taking a closer look, we can see that the name of the method is pretty straightforward and it conveys its intent. Same goes with the name of the parameters (Effect is an enum if you’re wondering.) The foreach loop iterates through all the effect prefabs, so no problem there. Next, two name variables: they could have been passed as they were to the string.Compare, but are left this way for debugging purposes. Now the if statement: what it does is clear, but when you read the code you need to stop the reading flow and start analyzing: “Ok, we have a string comparison of the two names, and this is a special case of the comparison(StringComparison.InvariantCultureIgnoreCase), oh and equal to zero is probably when the strings are equal (if you don’t remember strcmp from C).” This is a lot of thinking for one single if statement, and while it only takes a second and a half to get, it breaks your flow and interferes with your attempt to understand how the method accomplishes its task. So let’s clean it by extracting a method from the if statement:

private bool AreEffectNamesEqual(string firstEffectName, string secondEffectName)
    return string.Compare(firstEffectName, secondEffectName, StringComparison.InvariantCultureIgnoreCase) == 0;

Now the if statement looks like this:

if (AreEffectNamesEqual(effectPrefabName, effectToPlayName))

Let’s move on. Here we have the core of this method, the instantiation and init of the found effect, and, like before, we’re going to extract a method from it:

private OneShotEffect CreateAndSetupEffect(OneShotEffect effectPrefab, Vector3 worldPosition, float? duration)
    var effectInstance = (OneShotEffect)Instantiate(effectPrefab, worldPosition, Quaternion.identity);

	return effectInstance;

I’ve also changed the AreEffectNamesEqual method to a more sensible string comparison, the name of the Vector3 parameter (to effectWorldPosition) and the name of the foreach loop variable (to effectPrefab). So, the final version looks like this:

private List<OneShotEffect> _effectPrefabs = new List<OneShotEffect>();
public void PlayEffect(Effect effectToPlay, Vector3 effectWorldPosition, float? duration = null)
    foreach (var effectPrefab in _effectPrefabs)
		var effectToPlayName = effectToPlay.ToString();
		var effectPrefabName =;

		if (AreEffectNamesEqual(effectPrefabName, effectToPlayName))
			var effectInstance = CreateAndSetupEffect(effectPrefab, effectWorldPosition, duration);

private bool AreEffectNamesEqual(string firstEffectName, string secondEffectName)
	return firstEffectName.Equals(secondEffectName, StringComparison.InvariantCultureIgnoreCase);

private OneShotEffect CreateAndSetupEffect(OneShotEffect effectPrefab, Vector3 effectWorldPosition, float? duration)
	var effectInstance = (OneShotEffect)Instantiate(effectPrefab, effectWorldPosition, Quaternion.identity);

	return effectInstance;

Overall, the method looks cleaner. When you read the implementation of “PlayEffect”, you can understand more quickly how it works without going into the nitty gritty details. By removing the extra responsibility of this method (instantiating and initializing the effect instance), we promoted the single responsibility principle of this method. Can we improve this code further? Sure. Should we? Not only should we, but we are obliged to do so because we are professionals, and we always check in code in better shape than we checked it out. Don’t take this too far though, as it’s more of a guideline than a rule, and I’m not inferring here that one should sit and improve every bit of code that he finds, but if you find a name for a method, for example, that suits better, you should change it.


Do you have ideas of how to improve this code further? Write it in the comments.



  1. Iliya.e

    Congratulations for your first post, will read it tomorrow 😉

  2. Zorkman

    Nice article man. Regarding the naming and readability I think that you’ve did a great job. Regarding the functionality I see a couple of areas to improve, note that these opinions are solely based on my own experience, and do not represent any general standard or such like.

    – Instead of instantiating/destroying these effect, you could pool them instead to avoid unneccessary garbage and performance breaking, still though this is more beneficial when developing for mobile.

    – Personally I try to use Enums as little as possible.

    – Insert a break statement when the correct effect is found to remove inneccessary looping after that. Since I presume that because the name of the method is in singularis, only one effect should be played with that name.

    – String comparisons can be quite hard to debug sometime and do not endorce a type-safe code. Instead I would recommend that you make an interface called IOneShotEffect, which holds the necessary public functions and properties to be used. Then for each new effect you create you make, make them inherit the interface. Then make your PlayEffect method generic, where the inputed type must inherit IOneShotEffect. In this way you don’t have to rely on strings and/or enums, and you can be sure that whenever you call PlayEffect() you must input a class which inherits the IOneShotEffect. I guess this should work 🙂
    This could also work by using a class instead of IOneShotEffect, which I think you done.

    It might be that my comments went out of this articles scope, but I just think it’s fun to discuss these things. And as you said, you learn more when you write down what you already know 🙂

    • Alex Adonin

      First of thank you for the very constructive comment.
      1. About the instantiating: I couldn’t agree more. Object pooling is the way to go here. Note that by extracting the method of creation of the effect, this change will affect only this method;the rest of the code stays the same.
      2. Enums are really convenient, but I see your point: string consts could’ve been used here as well.
      3. For the break statement: you’re correct, it is missing.
      4. The main concern in the “PlayEffect” method is ease of use, and being part of EffectsManager class all of its inner workings are hidden. In my opinion, you can’t run away from the use of strings/enums in this case.

  3. Andrei Popa

    Use .Any() and .Single() from LINQ to find the effect?

    • Alex Adonin

      When using Unity3D engine, it is recommended to use LINQ as little as possible (I try to avoid it completely) , due to some limitation of iOS platform (AOT compilation).

  4. Anton Trohsin

    A bit late maybe, but here goes, about the most beaten topic in the world, string comparison 🙂
    Few years ago I’ve been also using InvariantCultureIgnoreCase a lot, until one day I’ve set a goal for myself, to finally understand the difference and use cases for each of the options.
    Since then, I’ve used InvariantCultureIgnoreCase only in cases when I was not in control of string that being passed to application/server.
    Meaning the user input from Desktop/Web/Mobile UI into backend.
    For most of the time, working with strings that are well known, and are in English, like: DB column names, field names, consts, enums, etc… OrdinalIgnoreCase or Ordinal, if case sensitivity is important, will be much faster.

    Just simple test in LINQPad or simple console app should show the result.
    Here’s also an article that may help to get into details of how each comparison works.
    It’s old, very, but seems like it still applies 🙂

Leave a Reply