codeAPI Reference
PlayerData Component for Stats and Respawn
PlayerData Component
Persistent player data component tracking stats (kills, deaths), respawn state, and providing connection lookup.
Key Properties
CSHARP
[Property] public Guid PlayerId { get; set; }
[Property] public long SteamId { get; set; } = -1L;
[Property] public string DisplayName { get; set; }
[Sync] public int Kills { get; set; }
[Sync] public int Deaths { get; set; }
[Sync] public bool IsGodMode { get; set; }Connection Lookup
CSHARP
public Connection Connection => Connection.Find(PlayerId);
public bool IsMe => PlayerId == Connection.Local.Id;
public float Ping => Connection?.Ping ?? 0;
/// <summary>
/// Data for all players.
/// </summary>
public static IEnumerable<PlayerData> All => Game.ActiveScene.GetAll<PlayerData>();
/// <summary>
/// Get player data for a connection.
/// </summary>
public static PlayerData For(Connection connection) =>
connection == null ? default : For(connection.Id);
/// <summary>
/// Get player data for a player ID.
/// </summary>
public static PlayerData For(Guid playerId) =>
All.FirstOrDefault(x => x.PlayerId == playerId);Respawn System
CSHARP
private bool _needsRespawn;
private RealTimeSince _timeSinceDied;
/// <summary>
/// Called on host when player dies. Starts respawn countdown.
/// </summary>
public void MarkForRespawn()
{
_needsRespawn = true;
_timeSinceDied = 0;
}
/// <summary>
/// Single entry point for all respawn logic. Called by PlayerObserver or timeout.
/// </summary>
[Rpc.Host(NetFlags.OwnerOnly | NetFlags.Reliable)]
public void RequestRespawn()
{
_needsRespawn = false;
// Clean up any lingering observer for this connection.
foreach (var observer in Scene.GetAllComponents<PlayerObserver>()
.Where(x => x.Network.Owner?.Id == PlayerId).ToArray())
{
observer.GameObject.Destroy();
}
GameManager.Current?.SpawnPlayer(this);
}
protected override void OnUpdate()
{
if (!Networking.IsHost) return;
if (!_needsRespawn) return;
if (_timeSinceDied < 4f) return;
RequestRespawn(); // Auto-respawn after 4 seconds
}Stats System
CSHARP
/// <summary>
/// Called on host, calls RPC on player to increment stats.
/// </summary>
public void AddStat(string identifier, int amount = 1)
{
if (Application.CheatsEnabled) return;
Assert.True(Networking.IsHost, "PlayerData.AddStat is host-only!");
using (Rpc.FilterInclude(Connection))
{
RpcAddStat(identifier, amount);
}
}
[Rpc.Broadcast]
private void RpcAddStat(string identifier, int amount = 1)
{
Sandbox.Services.Stats.Increment(identifier, amount);
}Save/Load Events
CSHARP
void Global.ISaveEvents.AfterLoad(string filename)
{
var connection = Connection;
if (connection == null)
{
// Get new PlayerId from SteamId if this is a new session
PlayerId = Connection.All.FirstOrDefault(x => x.SteamId == SteamId)?.Id ?? Guid.Empty;
}
}Usage Examples
CSHARP
// Get all player data ordered by kills
var topPlayers = PlayerData.All.OrderByDescending(x => x.Kills);
// Find player data for connection
var data = PlayerData.For(connection);
// Check if this is local player
if (data.IsMe) { /* ... */ }
// Get ping
var ping = data.Ping;
// Add stats (host only)
data.AddStat("deaths");
data.AddStat("kills.players", 1);
Was this helpful?