Learn how to detect mobile devices, tablets, browsers, and operating systems to create platform-specific experiences
Learn how to detect what device, platform, or browser your users are on to create optimized experiences.
Needle Engine provides the DeviceUtilities namespace with functions to detect:
Device types: Mobile phones, tablets, desktops, XR headsets
Operating systems: iOS, Android, macOS, VisionOS
Browsers: Safari, Chrome, specialized XR browsers
Capabilities: AR support, microphone permissions, version info
Use these utilities to adapt your app's behavior, optimize performance, or enable platform-specific features.
:::tip Cross-Platform by Default Needle Engine works seamlessly across all platforms! Use these utilities only when you need platform-specific features or optimizations. Your app should work everywhere by default, with progressive enhancement for capable devices. :::
Built-In Components (No Code Required!)
For many use cases, you don't need to write any code! Use these built-in components directly in Unity or Blender.
DeviceFlag Component
Automatically show or hide GameObjects based on device type (mobile vs desktop).
In Unity/Blender:
Add the DeviceFlag component to any GameObject
Set Visible On to:
Desktop - Only visible on desktop/laptop computers
Mobile - Only visible on phones and tablets
Desktop + Mobile - Visible on all devices
Use Cases:
Show high-quality models only on desktop
Display simplified UI for mobile devices
Hide complex effects on lower-powered devices
XRFlag Component
Show or hide objects based on XR state (VR/AR mode, first/third person view).
In Unity/Blender:
Add the XRFlag component to any GameObject
Set Visible In to combinations of:
Browser - Normal web browser mode
AR - When in AR session
VR - When in VR session
FirstPerson - First-person camera view
ThirdPerson - Third-person camera view
Use Cases:
Show UI only in browser mode, hide in VR/AR
Display different models for VR vs AR
Switch between first-person and third-person controls
:::tip Perfect for Non-Programmers These components work automatically when added in your editor - no scripting needed! They're perfect for artists and designers who want device-specific content without writing code. :::
Quick Start (Code)
:::tip Recommended Approach Use the DeviceUtilities namespace for all device detection - it keeps imports clean and organized. :::
Device Type Detection
Mobile vs Desktop
Specific Device Types
Operating System Detection
iOS Detection
Android Detection
macOS Detection
Browser Detection
Safari
Chrome
Specialized Browsers
XR and AR Capabilities
AR Support
VR Devices
Practical Examples
Platform-Specific Quality Settings
Adaptive UI
Control Scheme Selection
Feature Detection with Permissions
Available Detection Functions
All functions are available under the DeviceUtilities namespace. See the complete API documentation for more details.
Device Types
DeviceUtilities.isMobileDevice() - Any phone or tablet
import { Behaviour, DeviceUtilities } from "@needle-tools/engine";
export class PlatformDetection extends Behaviour {
start() {
if (DeviceUtilities.isMobileDevice()) {
console.log("Running on mobile device!");
if (DeviceUtilities.isiOS()) {
console.log("Specifically on iOS");
} else if (DeviceUtilities.isAndroidDevice()) {
console.log("Specifically on Android");
}
}
}
}
import { DeviceUtilities } from "@needle-tools/engine";
// Check if on phone or tablet
if (DeviceUtilities.isMobileDevice()) {
// Reduce particle effects for mobile
particleCount = 100;
} else if (DeviceUtilities.isDesktop()) {
// Use higher quality settings on desktop
particleCount = 1000;
}
import { DeviceUtilities } from "@needle-tools/engine";
if (DeviceUtilities.isiPad()) {
console.log("Running on iPad");
}
if (DeviceUtilities.isQuest()) {
console.log("Running on Meta Quest");
}
if (DeviceUtilities.isVisionOS()) {
console.log("Running on Apple Vision Pro");
}
import { DeviceUtilities } from "@needle-tools/engine";
// Check for any iOS device (iPhone, iPad, iPod, Vision Pro)
if (DeviceUtilities.isiOS()) {
console.log("iOS device detected");
// Get specific iOS version
const version = DeviceUtilities.getiOSVersion();
if (version) {
console.log("iOS version:", version);
}
}
// Specific iPad detection
if (DeviceUtilities.isiPad()) {
// iPad-specific UI layout
}
import { DeviceUtilities } from "@needle-tools/engine";
if (DeviceUtilities.isAndroidDevice()) {
console.log("Android device detected");
// Use Android-specific features
}
import { DeviceUtilities } from "@needle-tools/engine";
if (DeviceUtilities.isMacOS()) {
console.log("Running on macOS");
// Show Command key shortcuts instead of Ctrl
}
import { DeviceUtilities } from "@needle-tools/engine";
if (DeviceUtilities.isSafari()) {
console.log("Safari browser detected");
// Get Safari version
const version = DeviceUtilities.getSafariVersion();
if (version) {
console.log("Safari version:", version);
}
// Apply Safari-specific workarounds if needed
}
import { DeviceUtilities } from "@needle-tools/engine";
const chromeVersion = DeviceUtilities.getChromeVersion();
if (chromeVersion) {
console.log("Chrome version:", chromeVersion);
}
import { DeviceUtilities } from "@needle-tools/engine";
// Mozilla XR Viewer (iOS AR browser)
if (DeviceUtilities.isMozillaXR()) {
console.log("Running in Mozilla XR Viewer");
}
// Needle App Clip
if (DeviceUtilities.isNeedleAppClip()) {
console.log("Running in Needle App Clip");
}
import { DeviceUtilities } from "@needle-tools/engine";
// Check if device supports AR QuickLook (iOS AR)
if (DeviceUtilities.isiOS() && DeviceUtilities.supportsQuickLookAR()) {
console.log("Device supports AR QuickLook");
// Show AR button
}
import { DeviceUtilities } from "@needle-tools/engine";
if (DeviceUtilities.isQuest()) {
// Optimize for Quest rendering capabilities
enableFoveatedRendering();
}
if (DeviceUtilities.isVisionOS()) {
// Enable immersive space features
enableVisionProMode();
}
import { Behaviour, DeviceUtilities } from "@needle-tools/engine";
export class QualitySettings extends Behaviour {
start() {
const renderer = this.context.renderer;
if (DeviceUtilities.isMobileDevice()) {
// Lower quality on mobile
renderer.setPixelRatio(1);
renderer.shadowMap.enabled = false;
if (DeviceUtilities.isiOS()) {
// iOS-specific optimizations
renderer.powerPreference = "low-power";
}
} else {
// High quality on desktop
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
}
}
}
import { Behaviour, DeviceUtilities } from "@needle-tools/engine";
export class ResponsiveUI extends Behaviour {
start() {
if (DeviceUtilities.isiPad()) {
// Larger touch targets for iPad
this.buttonSize = 60;
} else if (DeviceUtilities.isMobileDevice()) {
// Medium size for phones
this.buttonSize = 50;
} else {
// Smaller size for desktop with mouse
this.buttonSize = 40;
}
this.updateButtonSizes();
}
private buttonSize: number = 40;
private updateButtonSizes() {
// Update UI button sizes based on device
console.log("Setting button size to", this.buttonSize);
}
}
import { Behaviour, DeviceUtilities } from "@needle-tools/engine";
export class MicrophoneSetup extends Behaviour {
async start() {
// Check if microphone permission is granted
const hasPermission = await DeviceUtilities.microphonePermissionsGranted();
if (hasPermission) {
console.log("Microphone access granted");
// Enable voice features
} else {
console.log("Microphone access denied or not requested");
// Show fallback UI
}
}
}
import { DeviceUtilities } from "@needle-tools/engine";
// ✅ Good: Works everywhere, enhanced on capable devices
if (DeviceUtilities.isMobileDevice()) {
// Simplified mobile experience
} else {
// Enhanced desktop experience with extra features
}
// ❌ Bad: Blocks users on certain platforms
if (!DeviceUtilities.isMobileDevice()) {
throw new Error("Desktop only!");
}
// Check for actual WebXR support
if ('xr' in navigator) {
// Enable VR/AR features
}
// Check for touch support
if ('ontouchstart' in window) {
// Enable touch-specific UI
}