Terra Studio Wiki
  • Home
  • Scripting in Terra Studio Pro
    • Scripting Basics
    • Key Differences - T# versus C#
      • Syntax Differences - T# v/s C#
      • Multiplayer Support Differences
      • Restrictions on Unity APIs
      • Restrictions on Collections & Types
      • Restrictions on Input, UI, Async
      • Miscellaneous Restrictions
    • Creating & Using Scripts
    • ๐Ÿ“˜ Terra Studio Runtime Classes
    • ๐ŸŽจ Terra Studio UI Systems Overview
    • Animation Support
    • ๐ŸŽง Audio & SFX Support in Terra Studio
    • ๐Ÿ”ฅ VFX Support in Terra Studio
    • ๐Ÿ“Š Game Analytics & FTUE Tracking in Terra Studio
    • ๐ŸŒ Multiplayer in Terra Studio
Powered by GitBook
On this page
  • ๐ŸŽฎ Using PlayerPrefs with Analytics
  • โœ… What You Can Store
  • ๐Ÿง  Why PlayerPrefs Matters in Analytics
  • โœ๏ธ Quick Example
  • ๐ŸŽฏ How Game Analytics Work in Terra Studio
  • ๐Ÿงญ Step-by-Step Implementation
  • ๐Ÿงช Example: Combat Stats
  • ๐Ÿš€ FTUE (First-Time User Experience) Tracking
  • ๐Ÿงช FTUE Tracking Examples
  • ๐Ÿ“Œ Best Practices
  1. Scripting in Terra Studio Pro

๐Ÿ“Š Game Analytics & FTUE Tracking in Terra Studio

Understanding how players interact with your game is essential to improving design, retention, and progression. Terra Studio supports in-game analytics out of the box via built-in methods integrated with Mixpanel. You donโ€™t need to do any setup โ€” just call the APIs as needed, and your data will automatically be sent to Mixpanel as structured events.

This guide helps you track game events (like combat stats, level progress) and FTUE (First-Time User Experience) milestones using Terraโ€™s analytics system.


๐ŸŽฎ Using PlayerPrefs with Analytics

Terra Studio fully supports Unity's PlayerPrefs system for persistent local storage โ€” and this becomes especially powerful when combined with analytics tracking.

In your analytics implementation, PlayerPrefs acts as the local cache for all analytics strings before theyโ€™re sent to Mixpanel via Terraโ€™s SetGameAnalyticsPrefs() methods.

This ensures:

  • Your data is saved even if the game is closed unexpectedly

  • You can build up longer strings across sessions

  • You always retain a fallback before transmitting events

โœ… What You Can Store

You can store any stringified version of game data using:

csharpCopyEditPlayerPrefs.SetString("Key", value);
PlayerPrefs.GetString("Key");
PlayerPrefs.Save(); // Optional, but ensures immediate persistence

Terra Studio internally uses PlayerPrefs to store:

  • Game value strings for progression, combat, sessions, FTUE, and more

  • FTUE milestone arrays (in JSON format)

  • Any transient data that you want to log incrementally over time

๐Ÿง  Why PlayerPrefs Matters in Analytics

When you call:

csharpCopyEditTerraScene.SetGameAnalyticsPrefs(...);

It pulls data from your locally maintained strings โ€” most of which are stored and updated using PlayerPrefs. Without PlayerPrefs, youโ€™d lose tracking progress on app restarts or session reloads.


โœ๏ธ Quick Example

Hereโ€™s how youโ€™d log a gameplay event and ensure it's retained:

csharpCopyEditPlayerPrefs.SetString("LevelProgressionData", levelProgressionData);
PlayerPrefs.Save(); // Ensures it's saved before calling analytics
TerraScene.SetGameAnalyticsPrefs(...);

By integrating PlayerPrefs with your analytics logic, you make sure your event data is always:

  • Persisted across sessions

  • Trimmed properly to meet limits

  • Sent when ready

Use it as your local data log and rely on Terra Studioโ€™s analytics API to push it live when the time is right.

๐ŸŽฏ How Game Analytics Work in Terra Studio

Terra Studio provides 12 game values to log analytics data. You have access to two built-in methods:

  • TerraScene.SetGameAnalyticsPrefs()

  • TerraScene.SetGameAnalyticsPrefs_2()

Each accepts 6 values (strings, up to 256 characters each), allowing you to track up to 12 types of game data simultaneously.

The 12th game value is reserved exclusively for FTUE tracking.

You can think of these values as containers โ€” use them to store data like level completions, deaths, power-up usage, etc.


๐Ÿงญ Step-by-Step Implementation

โœ… Step 1: Decide What to Track

Here are examples of what you might want to track:

Game Value
What to Track

1

Level progression

2

Combat statistics

3

Resource collection

4

Power-up or item usage

5

Session info

6

Player customization

7โ€“11

Economy, multiplayer stats, UI, etc.

12

FTUE tracking (fixed)


๐Ÿงฉ Step 2: Design a Compact Format

Each value is limited to 256 characters โ€” use compact formats with delimiters. Examples:

  • Level Completion: levelNumber_completionTime_exitType

  • Combat Stats: levelNumber_enemyType_killCount

Multiple entries can be chained using ||:

perlCopyEdit1_45.3_exit||2_30.1_death

๐Ÿ’พ Step 3: Store Analytics Variables in Code

public static class GameAnalytics
{
    private static string levelProgressionData;
    private static string combatStatisticsData;
    private static string resourceCollectionData;
    private static string featureUsageData;
    private static string sessionData;
    private static string customizationData;

    private static string purchaseData;
    private static string socialInteractionData;
    private static string errorData;
    private static string performanceData;
    private static string advertisingData;
    private static string ftueData; // Always for FTUE
}

๐Ÿง  Step 4: Initialize Variables on Startup

public static void Initialize()
{
    levelProgressionData = PlayerPrefs.GetString("LevelProgressionData", "");
    combatStatisticsData = PlayerPrefs.GetString("CombatStatisticsData", "");
    // ...continue for all
    ftueData = PlayerPrefs.GetString("FTUEData", "");
}

๐Ÿ› ๏ธ Step 5: Record Game Events

Here's how to record level completion data:

public static void RecordLevelCompletion(int levelNumber, float completionTime, string exitType)
{
    string newEntry = $"{levelNumber}_{completionTime}_{exitType}";
    if (levelProgressionData.Length > 0) newEntry = "||" + newEntry;

    if (levelProgressionData.Length + newEntry.Length > 256)
    {
        int trimIndex = levelProgressionData.IndexOf("||") + 2;
        while (levelProgressionData.Length - trimIndex + newEntry.Length > 256)
        {
            int nextDelimiter = levelProgressionData.IndexOf("||", trimIndex);
            if (nextDelimiter == -1)
            {
                levelProgressionData = newEntry.Substring(2);
                SaveAndSendLevelProgressionData();
                return;
            }
            trimIndex = nextDelimiter + 2;
        }
        levelProgressionData = levelProgressionData.Substring(trimIndex) + newEntry;
    }
    else
    {
        levelProgressionData += newEntry;
    }

    SaveAndSendLevelProgressionData();
}
private static void SaveAndSendLevelProgressionData()
{
    PlayerPrefs.SetString("LevelProgressionData", levelProgressionData);
    SendFirstSetOfGameValues();
}

๐Ÿ“ก Step 6: Send Data to Mixpanel

public static void SendFirstSetOfGameValues()
{
    TerraScene.SetGameAnalyticsPrefs(
        levelProgressionData,
        combatStatisticsData,
        resourceCollectionData,
        featureUsageData,
        sessionData,
        customizationData
    );
}

public static void SendSecondSetOfGameValues()
{
    TerraScene.SetGameAnalyticsPrefs_2(
        purchaseData,
        socialInteractionData,
        errorData,
        performanceData,
        advertisingData,
        ftueData
    );
}

public static void SendAllAnalyticsData()
{
    SendFirstSetOfGameValues();
    SendSecondSetOfGameValues();
}

๐Ÿงช Example: Combat Stats

public static void RecordEnemyKills(int levelNumber, string enemyType, int killCount)
{
    string newEntry = $"{levelNumber}_{enemyType}_{killCount}";
    if (combatStatisticsData.Length > 0) newEntry = "||" + newEntry;

    if (combatStatisticsData.Length + newEntry.Length > 256)
    {
        int trimIndex = combatStatisticsData.IndexOf("||") + 2;
        while (combatStatisticsData.Length - trimIndex + newEntry.Length > 256)
        {
            int nextDelimiter = combatStatisticsData.IndexOf("||", trimIndex);
            if (nextDelimiter == -1)
            {
                combatStatisticsData = newEntry.Substring(2);
                SaveAndSendCombatStatisticsData();
                return;
            }
            trimIndex = nextDelimiter + 2;
        }

        combatStatisticsData = combatStatisticsData.Substring(trimIndex) + newEntry;
    }
    else
    {
        combatStatisticsData += newEntry;
    }

    SaveAndSendCombatStatisticsData();
}

private static void SaveAndSendCombatStatisticsData()
{
    PlayerPrefs.SetString("CombatStatisticsData", combatStatisticsData);
    SendFirstSetOfGameValues();
}

๐Ÿš€ FTUE (First-Time User Experience) Tracking

FTUE tracks key player milestones during onboarding (e.g., first level completed, first weapon upgrade).

๐Ÿ’ก How It Works

  • Store FTUE milestones in an integer array

  • 1 = completed, 0 = not completed

  • Stored in game_value12 (last value in SetGameAnalyticsPrefs_2)

๐Ÿง  Initialize FTUE Data

public int[] ftueData;

private void InitializeFtueData()
{
    int totalFtueData = 20;
    ftueData = new int[totalFtueData];

    if (PlayerPrefs.HasKey("fTUEData")) {
        ftueData = JsonConvert.DeserializeObject<int[]>(PlayerPrefs.GetString("fTUEData"));
        // Resize if version changed
        int currentLength = ftueData.Length;
        if (currentLength != totalFtueData) {
            int[] newFtueData = new int[totalFtueData];
            for (int i = 0; i < Math.Min(currentLength, totalFtueData); i++) {
                newFtueData[i] = ftueData[i];
            }
            ftueData = newFtueData;
        }
    }
}

๐Ÿ“จ Log FTUE Data

public void LogFtueAnalytics()
{
    string ftueString = JsonConvert.SerializeObject(ftueData);
    PlayerPrefs.SetString("fTUEData", ftueString);

    string analyticsFormat = ftueString.TrimStart('[').TrimEnd(']');
    TerraScene.SetGameAnalyticsPrefs_2(
        PlayerPrefs.GetString("value6"),
        PlayerPrefs.GetString("value7"),
        PlayerPrefs.GetString("value8"),
        PlayerPrefs.GetString("value9"),
        "",
        analyticsFormat
    );
}

โš™๏ธ Optional Helper

public void SetFtueTrue(int index)
{
    if (index >= 0 && index < ftueData.Length) {
        ftueData[index] = 1;
        LogFtueAnalytics();
    }
}

๐Ÿงช FTUE Tracking Examples

// Level 1 completion
if (currentLevelIndex == 1 && isLevelCompleted) {
    LevelManager._Instance.ftueData[6] = 1;
    LevelManager._Instance.LogFtueAnalytics();
}

// First coin
if (currentCoin == 1 && !coin1st) {
    LevelManager._Instance.SetFtueTrue(4);
    coin1st = true;
}

// First weapon upgrade
if (weaponLevel == 2 && GameplayScreen._Instance.uiLevelIndex == 2) {
    LevelManager._Instance.ftueData[10] = 1;
    LevelManager._Instance.LogFtueAnalytics();
}

๐Ÿ“Œ Best Practices

  • Use clear constants for FTUE milestone indices

  • Avoid tracking unrelated data in FTUE

  • Always call LogFtueAnalytics() after setting data

  • Handle FTUE versioning with array resizing

  • Keep event strings short and meaningful (within 256 chars)

Previous๐Ÿ”ฅ VFX Support in Terra StudioNext๐ŸŒ Multiplayer in Terra Studio

Last updated 2 months ago