// standalone, Unity-independent connection-quality algorithm & enum. // don't need to use this directly, it's built into Mirror's NetworkClient. using UnityEngine; namespace Mirror { public enum ConnectionQuality : byte { ESTIMATING, // still estimating POOR, // unplayable FAIR, // very noticeable latency, not very enjoyable anymore GOOD, // very playable for everyone but high level competitors EXCELLENT // ideal experience for high level competitors } public enum ConnectionQualityMethod : byte { Simple, // simple estimation based on rtt and jitter Pragmatic // based on snapshot interpolation adjustment } // provide different heuristics for users to choose from. // simple heuristics to get started. // this will be iterated on over time based on user feedback. public static class ConnectionQualityHeuristics { // convenience extension to color code Connection Quality public static Color ColorCode(this ConnectionQuality quality) { switch (quality) { case ConnectionQuality.POOR: return Color.red; case ConnectionQuality.FAIR: return new Color(1.0f, 0.647f, 0.0f); case ConnectionQuality.GOOD: return Color.yellow; case ConnectionQuality.EXCELLENT: return Color.green; default: return Color.gray; // ESTIMATING } } // straight forward estimation // rtt: average round trip time in seconds. // jitter: average latency variance. public static ConnectionQuality Simple(double rtt, double jitter) { if (rtt <= 0.100 && jitter <= 0.10) return ConnectionQuality.EXCELLENT; if (rtt <= 0.200 && jitter <= 0.20) return ConnectionQuality.GOOD; if (rtt <= 0.400 && jitter <= 0.50) return ConnectionQuality.FAIR; return ConnectionQuality.POOR; } // snapshot interpolation based estimation. // snap. interp. adjusts buffer time based on connection quality. // based on this, we can measure how far away we are from the ideal. // the returned quality will always directly correlate with gameplay. // => requires SnapshotInterpolation dynamicAdjustment to be enabled! public static ConnectionQuality Pragmatic(double targetBufferTime, double currentBufferTime) { // buffer time is set by the game developer. // estimating in multiples is a great way to be game independent. // for example, a fast paced shooter and a slow paced RTS will both // have poor connection if the multiplier is >10. double multiplier = currentBufferTime / targetBufferTime; // empirically measured with Tanks demo + LatencySimulation. // it's not obvious to estimate on paper. if (multiplier <= 1.15) return ConnectionQuality.EXCELLENT; if (multiplier <= 1.25) return ConnectionQuality.GOOD; if (multiplier <= 1.50) return ConnectionQuality.FAIR; // anything else is poor return ConnectionQuality.POOR; } } }