### C# Download Manager Implementation Source: https://context7.com/ellanjiang/gameframework/llms.txt This C# script demonstrates how to use the GameFramework's IDownloadManager to handle file downloads. It includes configurations for timeouts and flush sizes, managing concurrent download agents, and subscribing to various download events like start, update, success, and failure. It provides methods for downloading single files, batch downloads, cancelling, pausing, resuming, and monitoring download progress and speed. Dependencies include the GameFramework assembly and Unity's MonoBehaviour. It handles network operations and file I/O. ```csharp using GameFramework; using GameFramework.Download; using UnityEngine; public class AssetDownloader : MonoBehaviour { private IDownloadManager m_DownloadManager; private int m_CurrentDownloadId; void Start() { m_DownloadManager = GameFrameworkEntry.GetModule(); // Configure download settings m_DownloadManager.Timeout = 30f; // 30 second timeout m_DownloadManager.FlushSize = 1024 * 1024; // Write to disk every 1MB // Add download agents (concurrent downloads) for (int i = 0; i < 3; i++) { m_DownloadManager.AddDownloadAgentHelper(downloadAgentHelper); } // Subscribe to download events m_DownloadManager.DownloadStart += OnDownloadStart; m_DownloadManager.DownloadUpdate += OnDownloadUpdate; m_DownloadManager.DownloadSuccess += OnDownloadSuccess; m_DownloadManager.DownloadFailure += OnDownloadFailure; } // Download single file public void DownloadAsset(string url, string savePath) { m_CurrentDownloadId = m_DownloadManager.AddDownload( savePath, url, tag: "assets", priority: 0, userData: null ); Debug.Log($"Started download: {url} -> {savePath}"); } // Download with custom options public void DownloadWithOptions(string url, string savePath, int priority) { // Higher priority downloads first int downloadId = m_DownloadManager.AddDownload( savePath, url, tag: "priority_assets", priority: priority, userData: new DownloadUserData { AssetName = "ImportantAsset" } ); } // Batch download public void DownloadAssetBundle(string[] urls, string downloadPath) { for (int i = 0; i < urls.Length; i++) { string fileName = System.IO.Path.GetFileName(urls[i]); string savePath = System.IO.Path.Combine(downloadPath, fileName); m_DownloadManager.AddDownload(savePath, urls[i], "asset_bundle", i); } } // Cancel download public void CancelDownload(int downloadId) { m_DownloadManager.RemoveDownload(downloadId); } // Pause/Resume all downloads public void PauseDownloads() { m_DownloadManager.Paused = true; } public void ResumeDownloads() { m_DownloadManager.Paused = false; } // Get download status public void ShowDownloadStatus(int downloadId) { DownloadInfo info = m_DownloadManager.GetDownloadInfo(downloadId); if (info != null) { float progress = info.Progress; long downloaded = info.DownloadedLength; long total = info.TotalLength; Debug.Log($"Download {downloadId}: {progress:P} ({downloaded}/{total} bytes)"); } } // Monitor download speed public void ShowDownloadSpeed() { float speed = m_DownloadManager.CurrentSpeed; // bytes/second float speedMB = speed / (1024f * 1024f); Debug.Log($"Download speed: {speedMB:F2} MB/s"); int working = m_DownloadManager.WorkingAgentCount; int waiting = m_DownloadManager.WaitingTaskCount; Debug.Log($"Active: {working}, Queued: {waiting}"); } private void OnDownloadStart(object sender, DownloadStartEventArgs e) { Debug.Log($"Download started: {e.DownloadUri}"); } private void OnDownloadUpdate(object sender, DownloadUpdateEventArgs e) { float progress = e.Progress; long downloaded = e.DownloadedLength; long total = e.TotalLength; // Update progress UI UpdateProgressBar(e.SerialId, progress); } private void OnDownloadSuccess(object sender, DownloadSuccessEventArgs e) { Debug.Log($"Download complete: {e.DownloadPath}, Size: {e.TotalLength} bytes"); DownloadUserData userData = e.UserData as DownloadUserData; if (userData != null) { Debug.Log($"Asset downloaded: {userData.AssetName}"); } // Load the downloaded asset LoadDownloadedAsset(e.DownloadPath); } private void OnDownloadFailure(object sender, DownloadFailureEventArgs e) { Debug.LogError($"Download failed: {e.DownloadUri}, Error: {e.ErrorMessage}"); // Retry logic if (e.DownloadAgainCount < 3) { Debug.Log("Retrying download..."); } else { Debug.LogError("Max retries exceeded"); } } } public class DownloadUserData { public string AssetName { get; set; } } ``` -------------------------------- ### Initialize and Control Game Audio Playback in C# Source: https://context7.com/ellanjiang/gameframework/llms.txt This C# code demonstrates how to use the GameFramework's ISoundManager to initialize sound groups, play background music, sound effects, and 3D spatial audio. It includes methods for stopping sounds, pausing/resuming all audio, and adjusting group volumes. Event handlers for sound playback success and failure are also shown. Dependencies include the GameFramework and Unity. ```csharp using GameFramework; using GameFramework.Sound; using UnityEngine; public class AudioController : MonoBehaviour { private ISoundManager m_SoundManager; private int m_BackgroundMusicId; void Start() { m_SoundManager = GameFrameworkEntry.GetModule(); // Subscribe to sound events m_SoundManager.PlaySoundSuccess += OnPlaySoundSuccess; m_SoundManager.PlaySoundFailure += OnPlaySoundFailure; // Create sound groups m_SoundManager.AddSoundGroup("Music", 1, false, 1f, musicGroupHelper); m_SoundManager.AddSoundGroup("SFX", 16, false, 1f, sfxGroupHelper); m_SoundManager.AddSoundGroup("Voice", 4, false, 1f, voiceGroupHelper); } // Play background music (2D, looping) public void PlayBackgroundMusic(string musicName) { PlaySoundParams soundParams = PlaySoundParams.Create(); soundParams.Priority = 128; soundParams.Loop = true; soundParams.VolumeInSoundGroup = 0.6f; soundParams.FadeInSeconds = 2f; soundParams.Spatial = false; // 2D sound m_BackgroundMusicId = m_SoundManager.PlaySound( $"Assets/Audio/Music/{musicName}.mp3", "Music", soundParams ); ReferencePool.Release(soundParams); } // Stop background music public void StopBackgroundMusic() { m_SoundManager.StopSound(m_BackgroundMusicId, 1f); // 1 second fade out } // Play sound effect (2D, one-shot) public void PlayButtonClick() { PlaySoundParams soundParams = PlaySoundParams.Create(); soundParams.Priority = 64; soundParams.VolumeInSoundGroup = 1f; soundParams.Spatial = false; m_SoundManager.PlaySound( "Assets/Audio/SFX/ButtonClick.wav", "SFX", soundParams ); ReferencePool.Release(soundParams); } // Play 3D sound at position public void PlayExplosion(Vector3 position) { PlaySoundParams soundParams = PlaySoundParams.Create(); soundParams.Priority = 100; soundParams.VolumeInSoundGroup = 1f; soundParams.Spatial = true; // 3D sound soundParams.Position = position; soundParams.MaxDistance = 50f; int explosionId = m_SoundManager.PlaySound( "Assets/Audio/SFX/Explosion.wav", "SFX", soundParams ); ReferencePool.Release(soundParams); } // Play sound attached to entity (follows entity) public void PlayEngineSound(int entityId) { IEntity entity = GameFrameworkEntry.GetModule().GetEntity(entityId); if (entity == null) return; PlaySoundParams soundParams = PlaySoundParams.Create(); soundParams.Priority = 80; soundParams.Loop = true; soundParams.VolumeInSoundGroup = 0.8f; soundParams.Spatial = true; soundParams.BindingEntity = entity; m_SoundManager.PlaySound( "Assets/Audio/SFX/Engine.wav", "SFX", soundParams ); ReferencePool.Release(soundParams); } // Pause/Resume sounds public void PauseAllSounds() { m_SoundManager.PauseAllLoadedSounds(); } public void ResumeAllSounds() { m_SoundManager.ResumeAllLoadedSounds(); } // Volume control public void SetMusicVolume(float volume) { ISoundGroup musicGroup = m_SoundManager.GetSoundGroup("Music"); if (musicGroup != null) { musicGroup.Volume = Mathf.Clamp01(volume); } } // Mute sound group public void MuteSFX(bool mute) { ISoundGroup sfxGroup = m_SoundManager.GetSoundGroup("SFX"); if (sfxGroup != null) { sfxGroup.Mute = mute; } } private void OnPlaySoundSuccess(object sender, PlaySoundSuccessEventArgs e) { Debug.Log($"Sound started: {e.SoundAssetName}, Serial: {e.SerialId}"); } private void OnPlaySoundFailure(object sender, PlaySoundFailureEventArgs e) { Debug.LogError($"Failed to play sound {e.SoundAssetName}: {e.ErrorMessage}"); } } ``` -------------------------------- ### Initialize, Update, and Shutdown GameFrameworkEntry in Unity Source: https://context7.com/ellanjiang/gameframework/llms.txt Demonstrates how to use the GameFrameworkEntry class to initialize, update, and shut down framework modules within a Unity project's lifecycle. It accesses modules like IEventManager and IFsmManager and handles delta time updates and application quitting. ```csharp using GameFramework; using GameFramework.Event; using GameFramework.Fsm; // Initialize framework in game startup void Start() { // Get modules (auto-creates if needed) IEventManager eventManager = GameFrameworkEntry.GetModule(); IFsmManager fsmManager = GameFrameworkEntry.GetModule(); // All modules are automatically registered and ready to use } // Update all modules in game loop void Update() { float deltaTime = Time.deltaTime; float unscaledDeltaTime = Time.unscaledDeltaTime; // Updates all registered modules in priority order GameFrameworkEntry.Update(deltaTime, unscaledDeltaTime); } // Cleanup on application quit void OnApplicationQuit() { // Shuts down all modules and clears reference pools GameFrameworkEntry.Shutdown(); } ``` -------------------------------- ### Object Pooling with ReferencePool in Unity Source: https://context7.com/ellanjiang/gameframework/llms.txt Illustrates the use of the ReferencePool system for high-performance object pooling in Unity. It shows how to define a poolable class implementing IReference, acquire and release objects, preload pools, and clear them, with an option for strict type checking in debug builds. ```csharp using GameFramework; // Define a poolable class public class PlayerData : IReference { public int PlayerId { get; set; } public string PlayerName { get; set; } public int Level { get; set; } // Required: Clear method called when returned to pool public void Clear() { PlayerId = 0; PlayerName = null; Level = 0; } } // Usage example public class PlayerManager { public void LoadPlayer(int playerId) { // Acquire from pool (reuses existing or creates new) PlayerData data = ReferencePool.Acquire(); try { data.PlayerId = playerId; data.PlayerName = "TestPlayer"; data.Level = 10; // Use the data... ProcessPlayerData(data); } finally { // Always release back to pool ReferencePool.Release(data); } } // Pre-allocate objects for better performance public void PreloadPlayerPool(int count) { ReferencePool.Add(count); } // Clear pool when changing scenes public void ClearPlayerPool() { ReferencePool.RemoveAll(); } } // Enable strict type checking in debug builds #if DEBUG ReferencePool.EnableStrictCheck = true; #endif ``` -------------------------------- ### C# Localization Controller for Multi-Language Game Support Source: https://context7.com/ellanjiang/gameframework/llms.txt Manages localization for a game, allowing developers to set languages, load dictionaries, add raw strings, and retrieve formatted localized strings. It handles UI localization, language switching, and provides helper methods for checking string existence and localizing UI components. ```csharp using GameFramework; using GameFramework.Localization; using UnityEngine; using UnityEngine.UI; public class LocalizationController : MonoBehaviour { private ILocalizationManager m_Localization; void Start() { m_Localization = GameFrameworkEntry.GetModule(); // Set language (defaults to system language) m_Localization.Language = Language.English; // Load localization dictionary (via resource system) // m_Localization.ReadData("Localization/English"); // Or add strings manually m_Localization.AddRawString("UI.Welcome", "Welcome to the game!"); m_Localization.AddRawString("UI.Start", "Start Game"); m_Localization.AddRawString("UI.Settings", "Settings"); m_Localization.AddRawString("UI.PlayerLevel", "Level {0}"); m_Localization.AddRawString("UI.PlayerInfo", "{0} - Level {1} - HP: {2}"); m_Localization.AddRawString("UI.QuestProgress", "Quest: {0}/{1} ({2:P})"); } // Get localized string public void ShowWelcomeMessage() { string message = m_Localization.GetString("UI.Welcome"); Debug.Log(message); // "Welcome to the game!" } // Get formatted string (single parameter) public void ShowPlayerLevel(int level) { string text = m_Localization.GetString("UI.PlayerLevel", level); Debug.Log(text); // "Level 10" } // Get formatted string (multiple parameters) public void ShowPlayerInfo(string name, int level, float health) { string info = m_Localization.GetString("UI.PlayerInfo", name, level, health); Debug.Log(info); // "Hero - Level 10 - HP: 100" } // Complex formatting public void ShowQuestProgress(int current, int total) { float progress = (float)current / total; string text = m_Localization.GetString("UI.QuestProgress", current, total, progress); Debug.Log(text); // "Quest: 5/10 (50.00%)" } // Change language at runtime public void SwitchLanguage(Language language) { m_Localization.Language = language; // Reload UI with new language RefreshAllUIText(); } // Get available languages public void ShowLanguageOptions() { Language current = m_Localization.Language; Language system = m_Localization.SystemLanguage; Debug.Log($"Current: {current}, System: {system}"); } // Check if translation exists public string GetStringOrDefault(string key, string defaultValue) { if (m_Localization.HasRawString(key)) { return m_Localization.GetString(key); } return defaultValue; } // Localize UI components public void LocalizeButton(Button button, string key) { Text buttonText = button.GetComponentInChildren(); if (buttonText != null) { buttonText.text = m_Localization.GetString(key); } } // Batch localize UI public void LocalizeUI(GameObject uiRoot) { // Find all LocalizableText components and update them LocalizableText[] texts = uiRoot.GetComponentsInChildren(); foreach (LocalizableText text in texts) { text.Text = m_Localization.GetString(text.LocalizationKey); } } // Language selection menu public void CreateLanguageMenu() { Language[] languages = new Language[] { Language.English, Language.ChineseSimplified, Language.ChineseTraditional, Language.Japanese, Language.Korean, Language.French, Language.German, Language.Spanish }; foreach (Language lang in languages) { // Create menu button for each language CreateLanguageButton(lang); } } private void CreateLanguageButton(Language language) { // Implementation would create UI button } private void RefreshAllUIText() { // Re-localize all active UI } } // Helper component for auto-localization public class LocalizableText : MonoBehaviour { public string LocalizationKey; private Text m_Text; void Awake() { m_Text = GetComponent(); } void Start() { UpdateText(); } public void UpdateText() { ILocalizationManager localization = GameFrameworkEntry.GetModule(); m_Text.text = localization.GetString(LocalizationKey); } } ``` -------------------------------- ### C# Entity Logic and Data Definitions Source: https://context7.com/ellanjiang/gameframework/llms.txt Defines the core logic for a player entity, including initialization, showing, hiding, updating, and attachment. It also includes a data class to hold player-specific properties like position and speed. This code relies on the GameFramework and UnityEngine namespaces. ```csharp using GameFramework; using GameFramework.Entity; using UnityEngine; // Define entity logic public class PlayerEntity : EntityLogic { public float Speed { get; set; } protected override void OnInit(object userData) { base.OnInit(userData); Debug.Log($"Player entity {Id} initialized"); } protected override void OnShow(object userData) { base.OnShow(userData); PlayerEntityData data = userData as PlayerEntityData; if (data != null) { Speed = data.Speed; transform.position = data.Position; Debug.Log($"Player shown at {data.Position}"); } } protected override void OnHide(bool isShutdown, object userData) { base.OnHide(isShutdown, userData); Debug.Log("Player entity hidden"); } protected override void OnUpdate(float elapseSeconds, float realElapseSeconds) { base.OnUpdate(elapseSeconds, realElapseSeconds); // Update entity logic } protected override void OnAttached(EntityLogic parentEntity, object userData) { base.OnAttached(parentEntity, userData); Debug.Log($"Attached to entity {parentEntity.Id}"); } } public class PlayerEntityData { public Vector3 Position { get; set; } public float Speed { get; set; } } ``` -------------------------------- ### C# EventManager: Custom Event Args and Subscription Source: https://context7.com/ellanjiang/gameframework/llms.txt Defines custom event arguments (PlayerLevelUpEventArgs) and demonstrates how to subscribe to, handle, and unsubscribe from events using the IEventManager. It also shows how to set a default handler for unhandled events. This is useful for game-wide communication. ```csharp using GameFramework; using GameFramework.Event; // Define custom event args public sealed class PlayerLevelUpEventArgs : GameEventArgs { public static readonly int EventId = typeof(PlayerLevelUpEventArgs).GetHashCode(); public int PlayerId { get; private set; } public int OldLevel { get; private set; } public int NewLevel { get; private set; } public override int Id { get { return EventId; } } public static PlayerLevelUpEventArgs Create(int playerId, int oldLevel, int newLevel) { PlayerLevelUpEventArgs e = ReferencePool.Acquire(); e.PlayerId = playerId; e.OldLevel = oldLevel; e.NewLevel = newLevel; return e; } public override void Clear() { PlayerId = 0; OldLevel = 0; NewLevel = 0; } } // Subscribe and fire events public class GameManager { private IEventManager m_EventManager; void Start() { m_EventManager = GameFrameworkEntry.GetModule(); // Subscribe to events m_EventManager.Subscribe(PlayerLevelUpEventArgs.EventId, OnPlayerLevelUp); // Set default handler for unhandled events m_EventManager.SetDefaultHandler(OnUnhandledEvent); } void OnDestroy() { // Unsubscribe when done m_EventManager.Unsubscribe(PlayerLevelUpEventArgs.EventId, OnPlayerLevelUp); } private void OnPlayerLevelUp(object sender, GameEventArgs e) { PlayerLevelUpEventArgs args = (PlayerLevelUpEventArgs)e; Debug.Log($"Player {args.PlayerId} leveled up from {args.OldLevel} to {args.NewLevel}"); // Show level up UI, grant rewards, etc. ShowLevelUpReward(args.NewLevel); } private void OnUnhandledEvent(object sender, GameEventArgs e) { Debug.LogWarning($"Unhandled event: {e.Id}"); } // Fire event (queued, distributed next frame, thread-safe) public void PlayerGainedExperience(int playerId, int currentLevel) { int newLevel = currentLevel + 1; m_EventManager.Fire(this, PlayerLevelUpEventArgs.Create(playerId, currentLevel, newLevel)); } // Fire immediately (not thread-safe, processes now) public void CriticalGameEvent(int playerId) { m_EventManager.FireNow(this, PlayerLevelUpEventArgs.Create(playerId, 10, 11)); } } ``` -------------------------------- ### C# Game Entity Manager for Object Lifecycle and Relationships Source: https://context7.com/ellanjiang/gameframework/llms.txt Manages the lifecycle of game entities, including creation, destruction, grouping, and attachment. It utilizes the IEntityManager interface and subscribes to entity events. This class depends on GameFrameworkEntry and IEntityManager. It handles spawning entities from prefabs, attaching them to specific points, and querying existing entities. ```csharp using GameFramework; using GameFramework.Entity; using UnityEngine; // Manage entities public class GameEntityManager : MonoBehaviour { private IEntityManager m_EntityManager; private int m_PlayerEntityId = 1000; void Start() { m_EntityManager = GameFrameworkEntry.GetModule(); // Subscribe to entity events m_EntityManager.ShowEntitySuccess += OnShowEntitySuccess; m_EntityManager.ShowEntityFailure += OnShowEntityFailure; m_EntityManager.HideEntityComplete += OnHideEntityComplete; // Create entity groups m_EntityManager.AddEntityGroup("Players", 60f, 16, 60f, 0, entityGroupHelper); m_EntityManager.AddEntityGroup("Enemies", 60f, 32, 60f, 0, entityGroupHelper); m_EntityManager.AddEntityGroup("Items", 30f, 100, 30f, 0, entityGroupHelper); } // Show entity public void SpawnPlayer(Vector3 position, float speed) { PlayerEntityData data = new PlayerEntityData { Position = position, Speed = speed }; // Show entity (async loading via resource system) m_EntityManager.ShowEntity(m_PlayerEntityId++, "Assets/Entities/Player.prefab", "Players", data); } // Hide entity public void DespawnEntity(int entityId) { if (m_EntityManager.HasEntity(entityId)) { m_EntityManager.HideEntity(entityId); } } // Attach entities (weapon to player, rider to mount) public void AttachWeapon(int playerId, int weaponId) { IEntity player = m_EntityManager.GetEntity(playerId); IEntity weapon = m_EntityManager.GetEntity(weaponId); if (player != null && weapon != null) { // Attach weapon to player's hand transform Transform attachPoint = player.Logic.transform.Find("RightHand"); m_EntityManager.AttachEntity(weapon, player, attachPoint); } } // Detach entity public void DetachWeapon(int weaponId) { IEntity weapon = m_EntityManager.GetEntity(weaponId); if (weapon != null) { m_EntityManager.DetachEntity(weapon); } } // Query entities public void ShowAllPlayers() { IEntity[] players = m_EntityManager.GetAllEntities("Players"); foreach (IEntity player in players) { Debug.Log($"Player {player.Id} at {player.Logic.transform.position}"); } } private void OnShowEntitySuccess(object sender, ShowEntitySuccessEventArgs e) { Debug.Log($"Entity {e.Entity.Id} shown successfully"); } private void OnShowEntityFailure(object sender, ShowEntityFailureEventArgs e) { Debug.LogError($"Failed to show entity {e.EntityId}: {e.ErrorMessage}"); } private void OnHideEntityComplete(object sender, HideEntityCompleteEventArgs e) { Debug.Log($"Entity {e.EntityId} hidden and recycled"); } } ``` -------------------------------- ### C# FSM Implementation for Player Behavior Source: https://context7.com/ellanjiang/gameframework/llms.txt This C# code defines a type-safe finite state machine for a 'Player' entity. It includes states for Idle, Move, and Dead, managing player properties like Health, Speed, and Position. The FSM transitions based on player input and health status, utilizing the GameFramework FSM manager. Dependencies include the GameFramework library. It takes a Player object as owner and transitions between defined FSM states. ```csharp using GameFramework; using GameFramework.Fsm; // Define state owner public class Player { public float Health { get; set; } public float Speed { get; set; } public Vector3 Position { get; set; } } // Define states public class PlayerIdleState : FsmState { protected override void OnInit(IFsm fsm) { base.OnInit(fsm); // Initialize state resources } protected override void OnEnter(IFsm fsm) { base.OnEnter(fsm); Debug.Log("Player entered idle state"); fsm.Owner.Speed = 0f; } protected override void OnUpdate(IFsm fsm, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(fsm, elapseSeconds, realElapseSeconds); // Check for input if (Input.GetKey(KeyCode.W)) { ChangeState(fsm); } // Check health if (fsm.Owner.Health <= 0) { ChangeState(fsm); } } protected override void OnLeave(IFsm fsm, bool isShutdown) { base.OnLeave(fsm, isShutdown); Debug.Log("Player left idle state"); } } public class PlayerMoveState : FsmState { protected override void OnEnter(IFsm fsm) { base.OnEnter(fsm); fsm.Owner.Speed = 5f; // Store data in FSM fsm.SetData("MoveStartTime", Time.time); } protected override void OnUpdate(IFsm fsm, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(fsm, elapseSeconds, realElapseSeconds); // Move player fsm.Owner.Position += Vector3.forward * fsm.Owner.Speed * elapseSeconds; // Return to idle if (!Input.GetKey(KeyCode.W)) { float moveTime = Time.time - fsm.GetData("MoveStartTime").Value; Debug.Log($"Moved for {moveTime} seconds"); ChangeState(fsm); } } } public class PlayerDeadState : FsmState { protected override void OnEnter(IFsm fsm) { base.OnEnter(fsm); Debug.Log("Player died"); fsm.Owner.Speed = 0f; } protected override void OnDestroy(IFsm fsm) { base.OnDestroy(fsm); // Cleanup state resources } } // Create and use FSM public class PlayerController : MonoBehaviour { private IFsmManager m_FsmManager; private IFsm m_PlayerFsm; private Player m_Player; void Start() { m_FsmManager = GameFrameworkEntry.GetModule(); m_Player = new Player { Health = 100f, Position = transform.position }; // Create FSM with all states m_PlayerFsm = m_FsmManager.CreateFsm("PlayerFsm", m_Player, new PlayerIdleState(), new PlayerMoveState(), new PlayerDeadState() ); // Start with idle state m_PlayerFsm.Start(); } void OnDestroy() { // Cleanup FSM if (m_PlayerFsm != null) { m_FsmManager.DestroyFsm(m_PlayerFsm); } } public void TakeDamage(float damage) { m_Player.Health -= damage; } } ``` -------------------------------- ### C# DataNode Manager for Game State Source: https://context7.com/ellanjiang/gameframework/llms.txt Demonstrates using the IDataNodeManager to store and retrieve hierarchical game data. It covers setting various data types (int, float, string) with path notation, reading data with type conversion, navigating nodes, updating values, and clearing data. Assumes the GameFramework is initialized. ```csharp using GameFramework; using GameFramework.DataNode; public class PlayerDataManager : MonoBehaviour { private IDataNodeManager m_DataNodeManager; void Start() { m_DataNodeManager = GameFrameworkEntry.GetModule(); // Set player data with path notation m_DataNodeManager.SetData("Player/Stats/Level", VarInt32.Create(10)); m_DataNodeManager.SetData("Player/Stats/Health", VarFloat.Create(100f)); m_DataNodeManager.SetData("Player/Stats/Mana", VarFloat.Create(50f)); m_DataNodeManager.SetData("Player/Info/Name", VarString.Create("Hero")); m_DataNodeManager.SetData("Player/Inventory/Gold", VarInt32.Create(1000)); // Create quest data structure m_DataNodeManager.SetData("Quests/Active/Quest_001/Progress", VarInt32.Create(5)); m_DataNodeManager.SetData("Quests/Active/Quest_001/Target", VarInt32.Create(10)); m_DataNodeManager.SetData("Quests/Completed/Quest_000/Reward", VarInt32.Create(500)); } // Read data public void DisplayPlayerInfo() { // Get values with type conversion int level = m_DataNodeManager.GetData("Player/Stats/Level").Value; float health = m_DataNodeManager.GetData("Player/Stats/Health").Value; string name = m_DataNodeManager.GetData("Player/Info/Name").Value; int gold = m_DataNodeManager.GetData("Player/Inventory/Gold").Value; Debug.Log($"{name} - Level {level} - HP: {health} - Gold: {gold}"); } // Navigate nodes public void ListActiveQuests() { IDataNode questsNode = m_DataNodeManager.GetNode("Quests/Active"); if (questsNode != null) { foreach (IDataNode questNode in questsNode) { string questId = questNode.Name; int progress = questNode.GetData("Progress").Value; int target = questNode.GetData("Target").Value; Debug.Log($"Quest {questId}: {progress}/{target}"); } } } // Update data public void AddGold(int amount) { var goldNode = m_DataNodeManager.GetData("Player/Inventory/Gold"); int newGold = goldNode.Value + amount; m_DataNodeManager.SetData("Player/Inventory/Gold", VarInt32.Create(newGold)); } // Get or create node public void EnsurePlayerDataExists() { IDataNode playerNode = m_DataNodeManager.GetOrAddNode("Player/Settings"); // Node is created if it doesn't exist } // Remove data public void ClearCompletedQuests() { m_DataNodeManager.RemoveNode("Quests/Completed"); } // Clear all data public void ResetAllData() { m_DataNodeManager.Clear(); } } ``` -------------------------------- ### TCP Socket Communication with C# Network Manager Source: https://context7.com/ellanjiang/gameframework/llms.txt Implements TCP socket communication for a game using C#. It defines custom packet structures for different game events (Login, PlayerMove, ChatMessage) and a NetworkClient class to manage connections, send data, and handle network events. Requires the GameFramework library and Unity's MonoBehaviour. ```csharp using GameFramework; using GameFramework.Network; using System; // Define packet types public enum PacketType : ushort { Login = 1, LoginResponse = 2, PlayerMove = 3, ChatMessage = 4 } // Define packet public class LoginPacket : Packet { public override int Id { get { return (int)PacketType.Login; } } public string Username { get; set; } public string Password { get; set; } public override void Clear() { base.Clear(); Username = null; Password = null; } } public class LoginResponsePacket : Packet { public override int Id { get { return (int)PacketType.LoginResponse; } } public bool Success { get; set; } public int PlayerId { get; set; } public string Message { get; set; } public override void Clear() { base.Clear(); Success = false; PlayerId = 0; Message = null; } } // Network client public class NetworkClient : MonoBehaviour { private INetworkManager m_NetworkManager; private INetworkChannel m_NetworkChannel; void Start() { m_NetworkManager = GameFrameworkEntry.GetModule(); // Subscribe to network events m_NetworkManager.NetworkConnected += OnNetworkConnected; m_NetworkManager.NetworkClosed += OnNetworkClosed; m_NetworkManager.NetworkError += OnNetworkError; m_NetworkManager.NetworkCustomError += OnNetworkCustomError; // Create network channel m_NetworkChannel = m_NetworkManager.CreateNetworkChannel( "GameServer", ServiceType.Tcp, networkChannelHelper ); } // Connect to server public void ConnectToServer(string host, int port) { Debug.Log($"Connecting to {host}:{port}..."); m_NetworkChannel.Connect(host, port); } // Disconnect public void Disconnect() { if (m_NetworkChannel.Connected) { m_NetworkChannel.Close(); } } // Send login packet public void Login(string username, string password) { if (!m_NetworkChannel.Connected) { Debug.LogError("Not connected to server"); return; } LoginPacket packet = ReferencePool.Acquire(); packet.Username = username; packet.Password = password; m_NetworkChannel.Send(packet); ReferencePool.Release(packet); } // Send player move packet public void SendPlayerMove(Vector3 position, Vector3 direction) { if (!m_NetworkChannel.Connected) return; PlayerMovePacket packet = ReferencePool.Acquire(); packet.Position = position; packet.Direction = direction; m_NetworkChannel.Send(packet); ReferencePool.Release(packet); } // Handle received packets (in NetworkChannelHelper) public void OnReceiveLoginResponse(LoginResponsePacket packet) { if (packet.Success) { Debug.Log($"Login successful! Player ID: {packet.PlayerId}"); OnLoginSuccess(packet.PlayerId); } else { Debug.LogError($"Login failed: {packet.Message}"); OnLoginFailed(packet.Message); } } // Network status public bool IsConnected { get { return m_NetworkChannel != null && m_NetworkChannel.Connected; } } public int SendQueueLength { get { return m_NetworkChannel != null ? m_NetworkChannel.SendPacketCount : 0; } } public int ReceiveQueueLength { get { return m_NetworkChannel != null ? m_NetworkChannel.ReceivePacketCount : 0; } } private void OnNetworkConnected(object sender, NetworkConnectedEventArgs e) { Debug.Log($"Connected to server at {e.NetworkChannel.Name}"); // Auto-login or show login UI } private void OnNetworkClosed(object sender, NetworkClosedEventArgs e) { Debug.Log("Disconnected from server"); // Show reconnect UI } private void OnNetworkError(object sender, NetworkErrorEventArgs e) { Debug.LogError($"Network error: {e.ErrorMessage}"); } private void OnNetworkCustomError(object sender, NetworkCustomErrorEventArgs e) { Debug.LogError($"Custom network error: {e.CustomErrorData}"); } void OnDestroy() { if (m_NetworkChannel != null) { m_NetworkChannel.Close(); m_NetworkManager.DestroyNetworkChannel(m_NetworkChannel.Name); } } } ``` -------------------------------- ### C# DataTable Manager for Game Data Source: https://context7.com/ellanjiang/gameframework/llms.txt Demonstrates how to define a data row structure (ItemDataRow) and use the DataTable Manager to load, query, and manage game data. Supports CSV parsing and manual data row addition, with methods for single item retrieval, type-based filtering, and complex conditional queries. Includes data table cleanup. ```csharp using GameFramework; using GameFramework.DataTable; // Define data row public class ItemDataRow : IDataRow { private int m_Id; public int Id { get { return m_Id; } } public string Name { get; private set; } public int ItemType { get; private set; } public int Level { get; private set; } public int Price { get; private set; } public string Description { get; private set; } public bool ParseDataRow(string dataRowString, object userData) { // Parse CSV format: Id,Name,Type,Level,Price,Description string[] fields = dataRowString.Split(','); if (fields.Length < 6) return false; m_Id = int.Parse(fields[0]); Name = fields[1]; ItemType = int.Parse(fields[2]); Level = int.Parse(fields[3]); Price = int.Parse(fields[4]); Description = fields[5]; return true; } public bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData) { // Parse binary format // Implementation depends on binary structure return false; } } // Use data tables public class ItemManager : MonoBehaviour { private IDataTableManager m_DataTableManager; private IDataTable m_ItemTable; void Start() { m_DataTableManager = GameFrameworkEntry.GetModule(); // Create data table m_ItemTable = m_DataTableManager.CreateDataTable("Items"); // Load from resource (requires resource manager integration) // m_ItemTable.ReadData("DataTables/Items"); // Or add rows manually m_ItemTable.AddDataRow("1001,Iron Sword,1,5,100,A basic iron sword"); m_ItemTable.AddDataRow("1002,Steel Armor,2,10,500,Protective steel armor"); m_ItemTable.AddDataRow("1003,Health Potion,3,1,50,Restores 50 HP"); } // Query single item public ItemDataRow GetItem(int itemId) { return m_ItemTable.GetDataRow(itemId); } // Query with predicate public ItemDataRow[] GetItemsByType(int itemType) { return m_ItemTable.GetDataRows(row => row.ItemType == itemType); } // Complex queries public ItemDataRow[] GetAffordableItems(int playerGold, int minLevel) { return m_ItemTable.GetDataRows(row => row.Price <= playerGold && row.Level >= minLevel ); } // Get all items public ItemDataRow[] GetAllItems() { return m_ItemTable.GetAllDataRows(); } // Display item info public void ShowItemInfo(int itemId) { ItemDataRow item = GetItem(itemId); if (item != null) { Debug.Log($"Item: {item.Name} (Lv.{item.Level}) - {item.Description} - Price: {item.Price}"); } else { Debug.LogWarning($"Item {itemId} not found"); } } void OnDestroy() { // Cleanup if (m_ItemTable != null) { m_DataTableManager.DestroyDataTable(); } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.