Krotox Engine › Docs › Scripting API › Systems & Utilities

Application, screen, device & network

Platform-aware code: detecting the platform and the editor, frame rate and v-sync, pause, focus and low-memory events, saving on background, screen size, DPI, safe areas and orientation, display settings on desktop, vibration, battery, locale, sharing, and checking for an internet connection.

Application

string platform = Application.Platform;      // "Windows", "macOS", "Linux", "Android", "iOS"
bool mobile     = Application.IsMobile;
bool inEditor   = Application.IsEditor;      // false in a built game
string version  = Application.Version;       // the product version from Build Settings
string saveDir  = Application.PersistentDataPath;

Application.TargetFrameRate = 30;            // 0 = uncapped (v-sync still applies)
Application.VSync = true;
Application.OpenURL("https://example.com/privacy");
Application.Quit();                          // ignored in the editor and on iOS

PersistentDataPath is never empty: <Project>/Saved in the editor, <exe>/Saved in a Windows build, the app's private files folder on Android.

Lifecycle events

Application.OnPause        += paused => { if (paused) SaveProgress(); };   // Android, iOS
Application.OnFocusChanged += focused => { };                              // an ad, a dialog, alt-tab
Application.OnLowMemory    += () => Assets.Unload(m_BigTexture);

Or declare the methods on any script; they are called on every active script that has them, with nothing to subscribe:

void OnApplicationPause(bool paused) { if (paused) SaveProgress(); }
void OnApplicationQuit()             { SaveProgress(); }      // not called when you stop Play in the editor
Save when paused is true. Phones can close a backgrounded game without any further warning, so the pause event is your last reliable chance.

All lifecycle events are cleared when Play stops.

Screen

float w = Screen.Width, h = Screen.Height;     // the game's pixels
Vector2 size = Screen.Size;
float dpi = Screen.DPI;
ScreenOrientation orientation = Screen.Orientation;
Screen.SetOrientationLock(OrientationLock.Landscape);   // Android only

Vector4 safe = Screen.SafeAreaInsets;          // left, right, top, bottom, in pixels

Screen.SafeAreaInsets is zero on desktop and on Android for now; use the UI Safe Area component there, which handles notches and cut-outs.

Desktop display settings

On a built Windows (or Linux, macOS) game you can offer a graphics menu. In the editor and on Android CanChangeDisplay is false and the setters do nothing.

if (Screen.CanChangeDisplay)
{
    Screen.FullScreen = true;                                  // borderless; false returns to the window
    Screen.FullScreenMode = FullScreenMode.Windowed;           // Windowed, Borderless, ExclusiveFullScreen
    Screen.SetResolution(1920, 1080, FullScreenMode.ExclusiveFullScreen);
    Resolution desktop = Screen.DesktopResolution;             // Width, Height, RefreshRate
    foreach (Resolution r in Screen.Resolutions)               // one per size, smallest first
        Log.Info(r.ToString());                                // "1920 x 1080 @ 144Hz"
}

// Render at a share of the window and scale up, for frame rate on 4K screens
Screen.RenderScale = 0.75f;      // 0.1 to 1; -1 returns to the project setting

Device

Device.Vibrate(40);                            // milliseconds; no permission prompt needed
float battery = Device.BatteryLevel;           // 0 to 1, or -1 when unknown (desktop)
string locale = Device.Locale;                 // "en-US", "de-DE", ...
Device.ClipboardText = inviteCode;
Device.ShareText(quot;I scored {score}!", subject: "My score");   // share sheet; clipboard on desktop
Vector3 gyro = Device.GyroRotation;
NetworkReachability net = Device.NetworkReachability;

Haptics on impact

public override void OnCollisionEnter2D(Collision2D c)
{
    if (c.NormalImpulse > 5.0f && Application.IsMobile)
        Device.Vibrate(20);
}

Network

Network tells you whether the player is online, so features that need the internet (leaderboards, cloud saves, remote config, ads) can say "no connection" instead of failing quietly.

if (!Network.IsConnected) { ShowOfflineBanner(); return; }     // instant: is there a network link?

if (Network.IsMetered) AskBeforeLargeDownload();               // on mobile data
bool wifi = Network.IsOnLocalNetwork;

Network.CheckInternet(online =>                                // asks the internet itself
{
    if (online) SyncSave(); else ShowOfflineBanner();
});

Network.CheckInternet(online => { }, timeoutMs: 3000, url: "https://api.mygame.example/ping");
MemberMeaning
ReachabilityLocalNetwork (Wi-Fi, Ethernet), CarrierNetwork (mobile data), NotReachable or Unknown.
IsConnectedA network link exists. true when the platform cannot tell, so players are never locked out on a guess.
IsMeteredOn mobile data.
IsOnLocalNetworkOn Wi-Fi or Ethernet.
CheckInternet(onResult, timeoutMs = 5000, url = null)Checks that the internet really answers (catches routers with no uplink and captive portals) and calls onResult exactly once, a frame or more later.

CheckInternet makes a real request on Windows; on other platforms it currently answers with IsConnected.

The back button

Application.OnBackPressed takes over Android's back button and back gesture. See Input: the Android back button.

Platform services

The KrotoxEngine.Services namespace covers Google Play billing (Billing), ads and consent (Mediation), analytics (Analytics: Firebase, GameAnalytics, Meta), remote config (RemoteConfig), Play Games sign-in (PlayGames), and Firebase auth and data (FirebaseAuth, FirebaseData). Results always arrive through events or callbacks. In the editor and on Windows, ads, billing and Play Games are simulated, and Window ▸ Live Services Simulation lets you force failures (no fill, cancelled purchase, network error) to test those paths without a device.

using KrotoxEngine.Services;

Billing.OnPurchaseSuccess += purchase => GrantItem(purchase.ProductId);
Billing.Initialize();
Billing.Purchase("remove_ads", isConsumable: false);

Analytics.LogEvent("level_start", "level", 3);
RemoteConfig.FetchAndActivate(ok => { int lives = RemoteConfig.GetInt("lives", 3); });

Service events and callbacks are cleared when Play stops, so subscribe again in OnAwake or OnCreate each session.