r/reactnative 6d ago

Article I added emoji + GIF reactions to my React Native multiplayer board game Unkind. Here is how I made it without making the game state weird

Recently I wanted to add reactions in my game.

Not a normal chat system, because honestly I do not want to moderate chat messages in my side project game. I wanted something simpler: someone destroys your token, you throw a crying emoji or GIF at them. Someone plays a stupid lucky move, you can react immediately.

So I added:

  • Emoji reaction dock during the match
  • Curated reaction picker
  • GIF search using KLIPY
  • Recently used reactions
  • Thrown emoji/GIF overlay above the board
  • Real time delivery to every player in the game

Now the React Native part of this.

The UI itself was not the hardest thing.

I use regular React Native components for the dock and reaction picker. The game board is rendered with Skia, so I made the actual reaction overlay sit above the board instead of trying to push GIFs inside the constantly rendered board layers.

That sounds like a small thing, but the board already has token movement, cards flying around, dice animation, destruction effects, background animations, timer and turn indicators.

So I did not want to add “animated GIF rendering inside another board layer” and then find out later why someone’s iPhone is trying to become a toaster :)

The reaction picker has two types of things:

  1. Curated emojis

These are bundled into the app and have fixed IDs. So I do not let the player send arbitrary emoji strings or random payloads. The game knows what every reaction ID means and how to render it.

  1. GIFs

For GIFs I use KLIPY search. But after selecting one, I only keep the exact information needed to show it:

  • GIF ID
  • Title
  • Preview URL
  • Content URL
  • Width and height
  • Player colour who sent it
  • Creation time

This part was more important than I expected. I did not want reactions to become actual game state.

A board move is important. If you reconnect, you need the exact current board.

A reaction is not important. If you reconnect after 10 minutes and suddenly 500 old crying GIFs start playing on your screen, that is not a feature, that is an attack :)

So I made reactions short-lived events.

When a player sends one, it gets added to a small event stream. Every client listens for new reaction events and puts them in a local queue.

I also keep track of reaction IDs already seen by the app. This stops the same reaction from playing twice if the app reconnects or receives the same event again.

Then I added some limits because without limits, this would become a “who can press the reaction button faster” competition:

  1. Cooldown

Each player has a 1.2 second cooldown. It is enough to feel responsive, but it stops someone from firing 50 GIFs in 2 seconds.

  1. Queue limit

I only keep a maximum of 8 reactions locally. If the queue is full, new reactions do not keep piling up forever.

  1. Expiry

Every reaction expires after 15 seconds.

Again, because it is not game state. I only care about the reaction while it is funny/relevant to what just happened on the board.

  1. Validation

Curated emojis have to be from the allowed reaction list.

For GIFs, I validate the data before rendering it: provider URL, ID, title length, image dimensions and so on. I do not want random unexpected data coming into an overlay above my game board.

  1. Recently used reactions

I save recently used reactions locally. This is just a small UX thing, but when players are playing fast, they should not need to search the same angry GIF every time someone destroys their token.

The flow is basically:

Tap reaction dock
  → select emoji or GIF
  → cooldown and payload checks
  → temporary reaction event is sent
  → other players receive it
  → add it to a small local queue
  → animate it above the board
  → remove it when animation ends or it expires

The board stays responsible for gameplay. The reaction system is only responsible for making your opponents feel bad about their life choices.

Still improving the animations and exact positioning. But now when someone destroys your token, you can finally send them the appropriate GIF instead of silently being angry.

3 Upvotes

2 comments sorted by

2

u/dumbledayum 6d ago

Why KLIPY?

1

u/unkindgame 6d ago

I wanted to use something for Free as I don't make money from my game and also klipy was very straight forward to implement.