Achievements

← All Community Games topics

DavidnetSDK.unlockAchievement({ id, name, description?, icon?, progress?, target? })

Unlocks (or advances) an achievement for the current player. id is a stable string YOU choose (letters, numbers, - / _ , up to 100 chars) — unique within your game, not globally, so keep it short and stable (e.g. "first_win" , not something you'll rename later). name is what's shown to the player; description and icon (an emoji works well) are optional. Resolves to: { isNew, achievement: { id, name, description, icon, progress, target, unlockedAt } }

Classic instant unlock

Without progress / target : first call wins — if the player already has this id , the stored name/description/icon don't change. Repeat calls are cheap no-ops server-side, but still call this ONCE when the condition first becomes true, not in a loop that re-checks the condition every frame — each call is still a network round trip that counts against your rate limit .

achievement-instant.js
javascript
// Call this from the "boss defeated" event handler, not from your update loop.
async function onBossDefeated() {
  try {
    const { isNew } = await window.DavidnetSDK.unlockAchievement({
      id: "first_boss_kill",
      name: "Giant Slayer",
      description: "Defeat the first boss",
      icon: "⚔️"
    });
    if (isNew) showMessage("Achievement unlocked: Giant Slayer!");
  } catch (e) {
    console.warn("Could not unlock achievement", e);
  }
}

// A "collect all the things" style achievement - fine to call every time an
// item is picked up, since the unlock condition is only true once.
async function onItemCollected(totalCollected, totalItems) {
  if (totalCollected !== totalItems) return; // not done yet, don't call at all
  await window.DavidnetSDK.unlockAchievement({
    id: "collector",
    name: "Completionist",
    description: "Collect every item in the game",
    icon: "🏆"
  });
}

Progress-bar achievements

With progress + target (both positive integers): tracks a progress bar instead of unlocking instantly — call this every time progress changes (e.g. { progress: 12, target: 50 } for "12 of 50 enemies defeated"). The server remembers the HIGHEST progress seen; isNew only flips true the moment progress reaches target (the achievement completes), after which it's immutable, same as a classic achievement.

achievement-progress.js
javascript
// Call with the current/target progress whenever it changes - "isNew" only
// flips true the moment it actually completes, so this is safe to call often
// (e.g. once per enemy kill, not once per frame).
async function onEnemyDefeated(totalDefeated) {
  try {
    const { isNew, achievement } = await window.DavidnetSDK.unlockAchievement({
      id: "monster_hunter",
      name: "Monster Hunter",
      description: "Defeat 50 enemies",
      icon: "🗡️",
      progress: totalDefeated,
      target: 50
    });

    updateProgressBar(achievement.progress, achievement.target); // e.g. 23 / 50

    if (isNew) showMessage("Achievement unlocked: Monster Hunter!");
  } catch (e) {
    console.warn("Could not update achievement progress", e);
  }
}

DavidnetSDK.getAchievements()

Every achievement the current player has unlocked OR made progress on in THIS game. unlockedAt is null for an in-progress (not yet completed) achievement — use this to rebuild a progress bar on load without tracking it yourself. unlockedPercentage (0-100) is the share of players who have fully unlocked that achievement id — handy for a rarity badge like "3% of players have this". Resolves to: { achievements: [{ id, name, description, icon, progress, target, unlockedAt, unlockedPercentage }, ...] }

achievement-list.js
javascript
async function showAchievementsScreen() {
  const { achievements } = await window.DavidnetSDK.getAchievements();

  for (const a of achievements) {
    const isDone = a.unlockedAt !== null;
    renderAchievementRow({
      icon: a.icon,
      name: a.name,
      description: a.description,
      done: isDone,
      progressText: a.target ? `${a.progress} / ${a.target}` : null,
      rarity: a.unlockedPercentage + "% of players have this"
    });
  }
}