In the previous article 🤖 Adding Game Center Plugin to Your Project , I explained how to add the Game Center plugin from the official Godot iOS plugins to your project. In this article, I’ll guide you on implementing the functionalities of Apple’s Game Center using the added plugin.

If you’re wondering what Game Center is all about, I briefly explained it in the beginning of the previous article, so you might want to check that out first.

Broadly, I’ll explain in two main sections:

  1. Setting Up Game Center in App Store Connect
  2. Implementing Game Center in GDScript

By the way, the basic usage of plugins is documented in Godot Docs / iOS plugins / iOS plugins , so it would be reasonable to start there.

Also, you can find the code for the Game Center plugin on GitHub at Godot iOS GameCenter plugin . If you want to delve into the details, you can check it out. Personally, I found it a bit challenging at first.

Environment at the Time of Writing
Godot Version: 4.2.1
Computer Model: MacBook Air M1, 2020
OS: macOS 14.4.1



Uploading Build from Xcode to App Store Connect

First and foremost, you need to upload the project exported from Godot to App Store Connect via Xcode. For specific steps, refer to another article 🤖 Distributing Your Game to the App Store from Xcode . It explains how to enable Game Center features in Xcode as well.


Setting Up Game Center in App Store Connect

Start by accessing App Store Connect and selecting the app you want to link with Game Center. Then, navigate to the Game Center section in the sidebar to open the Game Center editing page. From there, you can easily add Leaderboards and Achievements. It’s quite straightforward.

Below is a screenshot with Leaderboards and Achievements already added. Initially, they will be empty.
Game Center editing page in App Store Connect


Setting Up Leaderboards

Leaderboards allow players from around the world to compete with each other through scores shared via Apple’s Game Center. Follow these steps to set up Leaderboards:

  1. Click the (+) button for Leaderboard.
  2. Decide on a Reference Name and Leaderboard ID. Keeping them the same is advisable.
  3. Choose between Standard Leaderboard and Periodic Leaderboard. The former retains scores indefinitely until the Leaderboard is deleted, while the latter resets scores periodically. You can set the reset interval later.
  4. Set the score format, score range, score submission type, and order. For clarity, it’s recommended to format scores as integers, set the score range from a minimum of 0 to a generous maximum, and arrange them in descending order if higher scores are better.

Continue adding as many Leaderboards as needed. It’s easy. For example, setting up scores for shortest clear time or number of defeated enemies can motivate players. Feel free to brainstorm and add whatever comes to mind. You can reorder them anytime.
Editing order of Leaderboards

Editing panel for Leaderboard order


Setting Up Achievements

Achievements allow players to set goals during gameplay and prove their accomplishments. For instance, you can prepare achievements for defeating mid-bosses or reaching milestones in character growth, encouraging players to continue playing. Adding elements like item collection achievements or defeating a certain number of enemies can enhance the game’s longevity.

To add Achievements, follow these steps:

  1. Click the (+) button for Achievement.
  2. Input a Reference Name and Achievement ID in the opened panel, then click Create. It’s recommended to keep them consistent for clarity.
  3. Once the editing screen opens, set “Points,” “Hidden,” and “Can Be Earned Multiple Times” in order. Click the (?) button if you’re unsure about any settings. If you plan to create multiple achievements, remember to distribute a total of 1,000 points among them, allocating them wisely.

Continue by adding localizations for each language your game supports. You don’t need different images for each language; one image per achievement is enough, meeting the specified requirements.

Once you’ve added localizations, it will look something like this.
Achievements with added localizations

Possible achievements could include “Number of Clears,” “Playtime,” “Rare Items Obtained,” or “Skills Unlocked.” It’s advisable to list all achievements first, determine point allocations, and then proceed with the setup. Adding achievements later might require reallocating points, which can be tedious.



Coding with the Game Center Plugin

Now let’s explain how to code the Game Center features in GDScript.

First, let’s create a script in the project with a name like game_center.gd. You can add it by right-clicking in the file system dock.

Add script to project

You’d want to load this script as soon as the game starts. To do that, go to Project > Project Settings… > Autoload tab, and add the script you created. This way, the script will be loaded when the game starts.

Add script to Autoload

Next is the implementation of the crucial script. In the game_center.gd script, we’ll implement the Game Center functionality. Initially, let’s declare a variable for the Game Center plugin, for example, game_center.

extends Node

# Game Center plugin
var game_center = null

Next, within the _ready() function, let’s add the part for getting and authenticating the plugin right after the game starts. The code would look something like this:

func _ready():
    if OS.get_name() == "iOS":
        if Engine.has_singleton("GameCenter"):
            print("Found GameCenter plugin")
            game_center = Engine.get_singleton("GameCenter")
            var res = game_center.authenticate()
            print("Authentication: ", res)
        else:
            print("There is no GameCenter plugin")
  1. First, we check if the OS is iOS using OS.get_name() to retrieve the OS name.
  2. If the OS is iOS, we also check if the GameCenter plugin exists using Engine.has_singleton("GameCenter").
  3. If the plugin is found, we retrieve it using Engine.get_singleton("GameCenter") and assign it to the variable game_center.
  4. Then, we proceed with authentication by calling the built-in authenticate() function of the Game Center plugin. This function returns the authentication result, which we store in the variable res for easier debugging.

So far, this sets up the groundwork for implementing Game Center functionality. Next, we’ll explain the implementation of Leaderboards and Achievements functionalities, each in order.



Implementing Leaderboards

Let’s start with Leaderboards. We’ll explain with a straightforward example.

First, define a function to update the leaderboard. Let’s name it update_leaderboard().

func update_leaderboard(score:int, category:String):
    print("call update_leaderboard()")
    if not game_center:
        print("No Game Center plugin")
        return

    if not game_center.is_authenticated():
        print("not authenticated, authenticating again")
        game_center.authenticate()

    var data = {"score": score, "category": category}
    print("New Leaderboard data: ", data)
    var res = game_center.post_score(data)
    print("Update Leaderboard response: " + str(res))
  1. The function takes two arguments: score:int and category:String.
  2. First, we check if the game_center variable is empty (null). If so, we exit the function.
  3. Next, if authentication hasn’t been done, we authenticate again.
  4. We prepare the data to update the leaderboard. This data includes the score and the category of the leaderboard.
  5. Then, we call the plugin’s post_score() function with the data. This updates the leaderboard. The function returns the result, which we print for debugging purposes.

With update_leaderboard() defined, you can call this function at the appropriate time in your game to reflect the score.

var current_score : int = 0
var highscore : int = 0

func update_highscore(current_score: int):
    if high_score < current_score:
        high_score = current_score
        update_leaderboard(high_score, "highscore")

For instance, in a simple shooting game:

  1. Declare a variable current_score to increment whenever an enemy is shot.
  2. Also declare highscore to store the highest score achieved, which will be reflected on the leaderboard.
  3. Then, consolidate the logic in the update_highscore function, which you can call at game over to handle updating both the high score and the leaderboard.

These specifics will vary based on your game.

Finally, you’d probably want to navigate to the Game Center screen within your game to check the leaderboard. Here’s a function to do just that:

func show_leaderboard():
    if not game_center:
        print("No Game Center plugin")
        return

    if not game_center.is_authenticated():
        print("not authenticated, authenticating again")
        game_center.authenticate()

    var param := {"view": "leaderboards", "leaderboard_name": "highscore"}
    var res = game_center.show_game_center(param)
    print("Show Leaderboard response: ", res)

When a Button node is pressed, you can call this function to transition to the Game Center leaderboard screen.

  1. The function name is show_leaderboard(), and it takes no arguments.
  2. We first check if the game_center variable is empty (null). If so, we exit the function.
  3. If authentication hasn’t been done, we authenticate again.
  4. We prepare the parameters for the Game Center screen navigation. "view" should be set to "leaderboards", and "leaderboard_name" should be set to the name you defined in App Store Connect.
  5. Then, we call the plugin’s show_game_center() function with the parameters. The function returns the result, which we print for debugging.


Implementing Achievements

Next, let’s code the program related to Achievements. It’s quite similar to Leaderboards, so if you’ve grasped that, you’re good. We’ll keep this example simple too.

func update_achievement(item_name:String, progress:float):
    print("called report_achievement()")
    if not game_center:
        print("No Game Center plugin")
        return

    if not game_center.is_authenticated():
        print("not authenticated, authenticating again")
        game_center.authenticate()

    var data = {"name": item_name, "progress": progress}
    print("New Achievement data: ", data)
    var res = game_center.award_achievement(data)
    print("Update Achievement response: " + str(res))
  1. The function, for example update_achievement(), takes two arguments: item_name:String and progress:float.
  2. First, we check if the game_center variable is empty (null). If so, we exit the function.
  3. If authentication hasn’t been done, we authenticate again.
  4. We prepare the data to update the achievement, including the achievement’s name and the progress (in percentage).
  5. Then, we call the plugin’s award_achievement() function with the data. This updates the achievement. The function returns the result, which we print for debugging.

Then, for instance, for an achievement that requires reaching a certain play count:

var play_count := 0
var play_count_100 := false

func update_play_count_100():
    if not play_count_100:
        var progress = play_count / 100 * 100.0
        update_achievement("play_count_100", progress)
        if progress == 100.0:
            play_count_100 = true
  1. Declare a variable play_count to increment with each play.
  2. Also declare play_count_100 to track whether the achievement has been reached.
  3. Define the update_play_count_100() function to incrementally update the achievement progress each time it’s called, and if it reaches 100%, mark the achievement as completed.

Achievement implementation should be good with this.



Conclusion

That’s it for implementing Game Center functionality in iOS games with the Game Center plugin. Actually, the official Godot iOS plugin repository’s Readme explains how to implement, but the explanation is a bit limited and the plugin code is a bit complex, so it took me more time to implement than I anticipated. So, I hope this article serves as a helpful supplementary material.


Game Promotion

Finally, let me promote my games that actually use the Game Center plugin.

👹 Slashing Samurai

Test your reflexes and visual acuity! Can you skillfully slice various objects falling from the sky by controlling a samurai? An addictive casual timing game that you can play with simple one-handed controls!

🃏 Lovely Solitaire

When you hear “Solitaire (Klondike),” you know it’s the king of solo card games, but now, the mobile game “Lovely Solitaire” is available on the App Store!