Preferences Store

Persist user preferences for agent configuration.

Overview

The Preferences Store allows you to:

  • Save user's preferred settings

  • Restore settings across sessions

  • Sync preferences across devices (optional)

  • Provide personalized experiences

Basic Usage

Save Preferences

// Save individual preferences
PlayerPrefs.SetString("PreferredModel", agent.Model.Id);
PlayerPrefs.SetString("PreferredVoice", agent.Voice.Id);
PlayerPrefs.SetFloat("Temperature", agent.Temperature ?? 0.7f);
PlayerPrefs.SetInt("MaxTokens", agent.MaxTokens ?? 1000);
PlayerPrefs.Save();

Load Preferences

void Start()
{
    // Load saved preferences
    string model = PlayerPrefs.GetString("PreferredModel", "gpt-4o");
    string voice = PlayerPrefs.GetString("PreferredVoice", "alloy");
    float temperature = PlayerPrefs.GetFloat("Temperature", 0.7f);
    int maxTokens = PlayerPrefs.GetInt("MaxTokens", 1000);
    
    // Apply to agent
    agent.Model = new Model(model);
    agent.Voice = new Voice(voice);
    agent.Temperature = temperature;
    agent.MaxTokens = maxTokens;
}

Preference Manager

Complete Manager Class

[System.Serializable]
public class AgentPreferences
{
    public string Model = "gpt-4o";
    public string Voice = "alloy";
    public float Temperature = 0.7f;
    public int MaxTokens = 1000;
    public float SpeechSpeed = 1.0f;
    public bool EnableStreaming = true;
    public bool EnableAudio = true;
    public ConversationStoreType ConversationStore = ConversationStoreType.LocalFile;
}

public class PreferencesManager : MonoBehaviour
{
    private const string PREFS_KEY = "AgentPreferences";
    
    public static void Save(AgentPreferences prefs)
    {
        string json = JsonUtility.ToJson(prefs);
        PlayerPrefs.SetString(PREFS_KEY, json);
        PlayerPrefs.Save();
        
        Debug.Log("✓ Preferences saved");
    }
    
    public static AgentPreferences Load()
    {
        if (PlayerPrefs.HasKey(PREFS_KEY))
        {
            string json = PlayerPrefs.GetString(PREFS_KEY);
            return JsonUtility.FromJson<AgentPreferences>(json);
        }
        
        return new AgentPreferences(); // Defaults
    }
    
    public static void ApplyToAgent(AgentBehaviour agent, AgentPreferences prefs)
    {
        agent.Model = new Model(prefs.Model);
        agent.Voice = new Voice(prefs.Voice);
        agent.Temperature = prefs.Temperature;
        agent.MaxTokens = prefs.MaxTokens;
        agent.Stream = prefs.EnableStreaming;
        agent.EnableOutputAudio = prefs.EnableAudio;
        agent.ConversationStore = prefs.ConversationStore;
        
        if (agent.Settings.OutputAudioParameters != null)
        {
            agent.Settings.OutputAudioParameters.Speed = prefs.SpeechSpeed;
        }
        
        Debug.Log("✓ Preferences applied to agent");
    }
    
    public static AgentPreferences GetFromAgent(AgentBehaviour agent)
    {
        return new AgentPreferences
        {
            Model = agent.Model.Id,
            Voice = agent.Voice.Id,
            Temperature = agent.Temperature ?? 0.7f,
            MaxTokens = agent.MaxTokens ?? 1000,
            SpeechSpeed = agent.Settings.OutputAudioParameters?.Speed ?? 1.0f,
            EnableStreaming = agent.Stream,
            EnableAudio = agent.EnableOutputAudio,
            ConversationStore = agent.ConversationStore
        };
    }
}

Usage

public class AgentSetup : MonoBehaviour
{
    [SerializeField] private AgentBehaviour agent;
    
    void Start()
    {
        // Load and apply preferences
        var prefs = PreferencesManager.Load();
        PreferencesManager.ApplyToAgent(agent, prefs);
    }
    
    void OnApplicationQuit()
    {
        // Save current settings
        var prefs = PreferencesManager.GetFromAgent(agent);
        PreferencesManager.Save(prefs);
    }
}

Settings UI

Preferences Panel

public class PreferencesPanel : MonoBehaviour
{
    [SerializeField] private AgentBehaviour agent;
    
    [Header("UI")]
    [SerializeField] private TMP_Dropdown modelDropdown;
    [SerializeField] private TMP_Dropdown voiceDropdown;
    [SerializeField] private Slider temperatureSlider;
    [SerializeField] private TMP_InputField maxTokensInput;
    [SerializeField] private Toggle streamingToggle;
    [SerializeField] private Toggle audioToggle;
    [SerializeField] private Button saveButton;
    [SerializeField] private Button resetButton;
    
    void Start()
    {
        LoadCurrentSettings();
        
        saveButton.onClick.AddListener(SavePreferences);
        resetButton.onClick.AddListener(ResetToDefaults);
    }
    
    void LoadCurrentSettings()
    {
        var prefs = PreferencesManager.Load();
        
        // Populate dropdowns
        SetDropdownValue(modelDropdown, prefs.Model);
        SetDropdownValue(voiceDropdown, prefs.Voice);
        
        // Set values
        temperatureSlider.value = prefs.Temperature;
        maxTokensInput.text = prefs.MaxTokens.ToString();
        streamingToggle.isOn = prefs.EnableStreaming;
        audioToggle.isOn = prefs.EnableAudio;
    }
    
    void SavePreferences()
    {
        var prefs = new AgentPreferences
        {
            Model = GetDropdownValue(modelDropdown),
            Voice = GetDropdownValue(voiceDropdown),
            Temperature = temperatureSlider.value,
            MaxTokens = int.Parse(maxTokensInput.text),
            EnableStreaming = streamingToggle.isOn,
            EnableAudio = audioToggle.isOn
        };
        
        PreferencesManager.Save(prefs);
        PreferencesManager.ApplyToAgent(agent, prefs);
        
        ShowMessage("Preferences saved!");
    }
    
    void ResetToDefaults()
    {
        var defaults = new AgentPreferences();
        PreferencesManager.Save(defaults);
        PreferencesManager.ApplyToAgent(agent, defaults);
        LoadCurrentSettings();
        
        ShowMessage("Reset to defaults");
    }
    
    void SetDropdownValue(TMP_Dropdown dropdown, string value)
    {
        for (int i = 0; i < dropdown.options.Count; i++)
        {
            if (dropdown.options[i].text == value)
            {
                dropdown.value = i;
                break;
            }
        }
    }
    
    string GetDropdownValue(TMP_Dropdown dropdown)
    {
        return dropdown.options[dropdown.value].text;
    }
    
    void ShowMessage(string message)
    {
        Debug.Log(message);
        // Show toast/notification
    }
}

Cloud Sync (Optional)

Save to Cloud

public class CloudPreferences : MonoBehaviour
{
    private const string CLOUD_ENDPOINT = "https://api.yourapp.com/preferences";
    
    public async UniTask SaveToCloud(string userId, AgentPreferences prefs)
    {
        string json = JsonUtility.ToJson(prefs);
        
        using (UnityWebRequest request = UnityWebRequest.Post(CLOUD_ENDPOINT, ""))
        {
            byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = new DownloadHandlerBuffer();
            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("User-Id", userId);
            
            await request.SendWebRequest();
            
            if (request.result == UnityWebRequest.Result.Success)
            {
                Debug.Log("✓ Preferences saved to cloud");
            }
            else
            {
                Debug.LogError($"Failed to save to cloud: {request.error}");
            }
        }
    }
    
    public async UniTask<AgentPreferences> LoadFromCloud(string userId)
    {
        using (UnityWebRequest request = UnityWebRequest.Get($"{CLOUD_ENDPOINT}?userId={userId}"))
        {
            await request.SendWebRequest();
            
            if (request.result == UnityWebRequest.Result.Success)
            {
                string json = request.downloadHandler.text;
                return JsonUtility.FromJson<AgentPreferences>(json);
            }
            else
            {
                Debug.LogWarning($"Failed to load from cloud: {request.error}");
                return new AgentPreferences();
            }
        }
    }
}

Sync Manager

public class PreferencesSyncManager : MonoBehaviour
{
    [SerializeField] private AgentBehaviour agent;
    [SerializeField] private bool enableCloudSync = false;
    
    private CloudPreferences cloudPrefs;
    private string userId;
    
    void Start()
    {
        cloudPrefs = new CloudPreferences();
        userId = GetUserId();
        
        LoadPreferences();
    }
    
    async void LoadPreferences()
    {
        AgentPreferences prefs;
        
        if (enableCloudSync)
        {
            // Try cloud first
            prefs = await cloudPrefs.LoadFromCloud(userId);
            
            if (prefs == null)
            {
                // Fallback to local
                prefs = PreferencesManager.Load();
            }
        }
        else
        {
            // Local only
            prefs = PreferencesManager.Load();
        }
        
        PreferencesManager.ApplyToAgent(agent, prefs);
    }
    
    public async void SavePreferences()
    {
        var prefs = PreferencesManager.GetFromAgent(agent);
        
        // Always save locally
        PreferencesManager.Save(prefs);
        
        // Optionally sync to cloud
        if (enableCloudSync)
        {
            await cloudPrefs.SaveToCloud(userId, prefs);
        }
    }
    
    string GetUserId()
    {
        string userId = PlayerPrefs.GetString("UserId");
        if (string.IsNullOrEmpty(userId))
        {
            userId = System.Guid.NewGuid().ToString();
            PlayerPrefs.SetString("UserId", userId);
        }
        return userId;
    }
}

Profile System

Multiple Profiles

public class ProfileManager : MonoBehaviour
{
    [System.Serializable]
    public class Profile
    {
        public string Name;
        public AgentPreferences Preferences;
    }
    
    private List<Profile> profiles = new List<Profile>();
    private string currentProfileName;
    
    public void CreateProfile(string profileName)
    {
        var profile = new Profile
        {
            Name = profileName,
            Preferences = new AgentPreferences()
        };
        
        profiles.Add(profile);
        SaveProfiles();
    }
    
    public void SwitchProfile(string profileName)
    {
        var profile = profiles.Find(p => p.Name == profileName);
        if (profile != null)
        {
            currentProfileName = profileName;
            PreferencesManager.ApplyToAgent(agent, profile.Preferences);
            PlayerPrefs.SetString("CurrentProfile", profileName);
        }
    }
    
    public void SaveCurrentProfile()
    {
        var profile = profiles.Find(p => p.Name == currentProfileName);
        if (profile != null)
        {
            profile.Preferences = PreferencesManager.GetFromAgent(agent);
            SaveProfiles();
        }
    }
    
    void SaveProfiles()
    {
        string json = JsonUtility.ToJson(new ProfileList { profiles = profiles });
        PlayerPrefs.SetString("Profiles", json);
    }
    
    void LoadProfiles()
    {
        if (PlayerPrefs.HasKey("Profiles"))
        {
            string json = PlayerPrefs.GetString("Profiles");
            profiles = JsonUtility.FromJson<ProfileList>(json).profiles;
        }
    }
    
    [System.Serializable]
    class ProfileList
    {
        public List<Profile> profiles;
    }
}

Best Practices

1. Auto-Save on Change

public class AutoSavePreferences : MonoBehaviour
{
    [SerializeField] private AgentBehaviour agent;
    [SerializeField] private float saveDelay = 1f;
    
    private float lastChangeTime;
    private bool hasUnsavedChanges;
    
    void Update()
    {
        if (hasUnsavedChanges && Time.time - lastChangeTime >= saveDelay)
        {
            SavePreferences();
            hasUnsavedChanges = false;
        }
    }
    
    public void OnSettingChanged()
    {
        lastChangeTime = Time.time;
        hasUnsavedChanges = true;
    }
    
    void SavePreferences()
    {
        var prefs = PreferencesManager.GetFromAgent(agent);
        PreferencesManager.Save(prefs);
        Debug.Log("Auto-saved preferences");
    }
}

2. Validate Preferences

public bool ValidatePreferences(AgentPreferences prefs)
{
    // Validate model
    string[] validModels = { "gpt-4o", "gpt-4-turbo", "gpt-3.5-turbo" };
    if (!validModels.Contains(prefs.Model))
    {
        Debug.LogWarning($"Invalid model: {prefs.Model}, using default");
        prefs.Model = "gpt-4o";
    }
    
    // Validate temperature
    if (prefs.Temperature < 0f || prefs.Temperature > 2f)
    {
        prefs.Temperature = Mathf.Clamp(prefs.Temperature, 0f, 2f);
    }
    
    // Validate max tokens
    if (prefs.MaxTokens < 1 || prefs.MaxTokens > 4096)
    {
        prefs.MaxTokens = Mathf.Clamp(prefs.MaxTokens, 1, 4096);
    }
    
    return true;
}

3. Provide Reset Option

public void ResetAllPreferences()
{
    if (ShowConfirmDialog("Reset all preferences to default?"))
    {
        PlayerPrefs.DeleteAll();
        var defaults = new AgentPreferences();
        PreferencesManager.Save(defaults);
        PreferencesManager.ApplyToAgent(agent, defaults);
        
        Debug.Log("✓ All preferences reset");
    }
}

Complete Example

using UnityEngine;
using Glitch9.AIDevKit.Agents;

public class CompletePreferencesSystem : MonoBehaviour
{
    [SerializeField] private AgentBehaviour agent;
    
    void Start()
    {
        LoadPreferences();
    }
    
    void LoadPreferences()
    {
        var prefs = PreferencesManager.Load();
        
        // Validate before applying
        ValidatePreferences(prefs);
        
        // Apply to agent
        PreferencesManager.ApplyToAgent(agent, prefs);
        
        Debug.Log("✓ Preferences loaded");
        Debug.Log($"  Model: {prefs.Model}");
        Debug.Log($"  Voice: {prefs.Voice}");
        Debug.Log($"  Temperature: {prefs.Temperature}");
    }
    
    public void SaveCurrentSettings()
    {
        var prefs = PreferencesManager.GetFromAgent(agent);
        PreferencesManager.Save(prefs);
        
        Debug.Log("✓ Preferences saved");
    }
    
    void OnApplicationQuit()
    {
        // Auto-save on quit
        SaveCurrentSettings();
    }
    
    void ValidatePreferences(AgentPreferences prefs)
    {
        prefs.Temperature = Mathf.Clamp(prefs.Temperature, 0f, 2f);
        prefs.MaxTokens = Mathf.Clamp(prefs.MaxTokens, 1, 4096);
        prefs.SpeechSpeed = Mathf.Clamp(prefs.SpeechSpeed, 0.25f, 4f);
    }
}

Next Steps

Last updated