Flutter Example App
Explore the complete Flutter example application that demonstrates all Game Framework features including engine initialization, bidirectional communication, lifecycle management, and UI patterns.
Overview
The example app showcases:
- Engine Initialization - Unity and Unreal Engine plugin setup
- Bidirectional Communication - Flutter ↔ Engine messaging
- Lifecycle Management - Pause/resume/destroy handling
- UI Overlay - Flutter UI on top of game view
- Event Logging - Real-time message stream monitoring
- Streaming Example - Content downloading and streaming
- Platform View Modes - Android platform view options
This is a complete, production-ready example you can use as a template for your own projects!
Getting Started
Clone the Repository
git clone https://github.com/xraph/gameframework.git
cd gameframework/exampleInstall Dependencies
flutter pub getRun the Example
# Run on connected device
flutter run
# Run on specific platform
flutter run -d android
flutter run -d ios
flutter run -d macosApp Structure
Main Entry Point
import 'package:flutter/material.dart';
import 'package:gameframework/gameframework.dart';
import 'package:gameframework_unity/gameframework_unity.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Initialize engine plugins
UnityEnginePlugin.initialize();
runApp(const MyApp());
}Home Screen
The home screen provides navigation to different examples:
- Unity Example - Interactive rotating cube demo
- Unreal Example - Unreal Engine integration (coming soon)
- Streaming Example - Content streaming demonstration
Unity Example Screen
Features Demonstrated
The Unity example screen includes:
-
Interactive Controls
- Speed slider (-180° to 180°/second)
- Axis selector (X, Y, Z, All)
- Control buttons (Reset, Get State, Random Color)
-
Real-Time Display
- Current speed and RPM
- Rotation axis
- Communication direction
- Event log
-
UI Patterns
- Expandable control panel
- Mini HUD for quick info
- Dark theme with transparency
- Smooth animations
Code Structure
class UnityExampleScreen extends StatefulWidget {
@override
State<UnityExampleScreen> createState() => _UnityExampleScreenState();
}
class _UnityExampleScreenState extends State<UnityExampleScreen> {
GameEngineController? _controller;
double _targetSpeed = 50.0;
String _rotationAxis = 'Y';
List<String> _logs = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// Unity view fills the entire screen
GameWidget(
engineType: GameEngineType.unity,
config: GameEngineConfig(
runImmediately: true,
),
onEngineCreated: _onEngineCreated,
onMessage: _onMessage,
),
// Flutter UI overlay
_buildControlPanel(),
_buildMiniHud(),
],
),
);
}
void _onEngineCreated(GameEngineController controller) {
setState(() {
_controller = controller;
_isReady = true;
});
_addLog('✓ Engine ready');
}
void _onMessage(GameEngineMessage message) {
_addLog('← ${message.method}: ${message.data}');
// Parse message and update UI
if (message.method == 'onStateUpdate') {
final state = jsonDecode(message.data);
setState(() {
_currentSpeed = state['speed'] ?? 0;
_currentRpm = state['rpm'] ?? 0;
});
}
}
}Control Panel UI
Expandable Panel
Widget _buildControlPanel() {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: AnimatedBuilder(
animation: _panelAnimation,
builder: (context, child) {
return Container(
height: _isPanelExpanded ? 400 : 80,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.8),
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Column(
children: [
// Panel header with toggle button
_buildPanelHeader(),
// Panel content (expanded)
if (_isPanelExpanded)
Expanded(child: _buildPanelContent()),
],
),
);
},
),
);
}Speed Control
Widget _buildSpeedControl() {
return Column(
children: [
Text('Speed: ${_targetSpeed.toStringAsFixed(0)}°/s'),
Slider(
value: _targetSpeed,
min: -180,
max: 180,
onChanged: (value) {
setState(() => _targetSpeed = value);
},
onChangeEnd: (value) {
_setSpeed(value);
},
),
],
);
}
void _setSpeed(double speed) {
_controller?.sendJsonMessage('GameFrameworkDemo', 'setSpeed', {
'speed': speed,
});
_addLog('→ setSpeed: $speed');
}Axis Selector
Widget _buildAxisSelector() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: ['X', 'Y', 'Z', 'All'].map((axis) {
return ElevatedButton(
onPressed: () => _setAxis(axis),
style: ElevatedButton.styleFrom(
backgroundColor: _rotationAxis == axis
? Colors.blue
: Colors.grey[800],
),
child: Text(axis),
);
}).toList(),
);
}
void _setAxis(String axis) {
setState(() => _rotationAxis = axis);
_controller?.sendJsonMessage('GameFrameworkDemo', 'setAxis', {
'axis': axis,
});
_addLog('→ setAxis: $axis');
}Event Logging
final List<String> _logs = [];
final int _maxLogs = 100;
void _addLog(String message) {
setState(() {
_logs.insert(0, '${_formatTime()} $message');
if (_logs.length > _maxLogs) {
_logs.removeLast();
}
});
}
Widget _buildEventLog() {
return Container(
height: 200,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.9),
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
reverse: true,
itemCount: _logs.length,
itemBuilder: (context, index) {
final log = _logs[index];
return Padding(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: Text(
log,
style: TextStyle(
fontFamily: 'monospace',
fontSize: 11,
color: _getLogColor(log),
),
),
);
},
),
);
}
Color _getLogColor(String log) {
if (log.contains('←')) return Colors.green;
if (log.contains('→')) return Colors.orange;
if (log.contains('✓')) return Colors.lightBlue;
if (log.contains('✗')) return Colors.red;
return Colors.grey;
}Mini HUD
Widget _buildMiniHud() {
if (_isPanelExpanded || !_showMiniHud) return SizedBox.shrink();
return Positioned(
top: 100,
right: 16,
child: Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.7),
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Speed: ${_currentSpeed.toStringAsFixed(0)}°/s',
style: TextStyle(color: Colors.white, fontSize: 12)),
Text('RPM: ${_currentRpm.toStringAsFixed(1)}',
style: TextStyle(color: Colors.white70, fontSize: 11)),
Text('Axis: $_rotationAxis',
style: TextStyle(color: Colors.white70, fontSize: 11)),
],
),
),
);
}Lifecycle Management
@override
void dispose() {
// Clean up controller when screen is disposed
_controller?.dispose();
_panelAnimationController.dispose();
super.dispose();
}
void _pauseEngine() {
_controller?.pause();
_addLog('⏸ Engine paused');
}
void _resumeEngine() {
_controller?.resume();
_addLog('▶ Engine resumed');
}Streaming Example
The streaming example demonstrates content downloading and asset streaming:
class StreamingExampleScreen extends StatefulWidget {
@override
State<StreamingExampleScreen> createState() => _StreamingExampleScreenState();
}
class _StreamingExampleScreenState extends State<StreamingExampleScreen> {
double _downloadProgress = 0.0;
bool _isDownloading = false;
Future<void> _downloadAsset(String assetUrl) async {
setState(() => _isDownloading = true);
try {
final response = await http.get(Uri.parse(assetUrl));
final bytes = response.bodyBytes;
// Send to Unity
await _controller?.sendBinaryMessage(
'AssetManager',
'loadAsset',
bytes,
);
setState(() => _isDownloading = false);
} catch (e) {
_showError('Download failed: $e');
setState(() => _isDownloading = false);
}
}
}Platform-Specific Features
Android Platform View Modes
// Hybrid Composition (default, better compatibility)
config: GameEngineConfig(
platformViewType: PlatformViewType.hybridComposition,
)
// Virtual Display (better performance)
config: GameEngineConfig(
platformViewType: PlatformViewType.virtualDisplay,
)What You'll Learn
From the example app, you'll learn:
- ✅ Complete app structure and organization
- ✅ Engine initialization and setup
- ✅ Bidirectional communication patterns
- ✅ UI overlay and interaction design
- ✅ Event logging and debugging
- ✅ Lifecycle management
- ✅ State management
- ✅ Error handling
- ✅ Platform-specific configurations
The example app uses production-ready patterns and best practices you can apply to your own projects.
Running on Different Platforms
Android
flutter run -d android
# Or build APK
flutter build apkiOS
flutter run -d ios
# Or build IPA
flutter build iosmacOS
flutter run -d macos
# Or build app
flutter build macosCustomization
Modify Unity Integration
- Open Unity project in
example/unity/demo/ - Edit
GameFrameworkDemo.csscript - Export and sync:
cd example
game export unity --platform android
game sync unity --platform androidExtend the Example
Add your own examples by:
- Creating a new screen widget
- Adding navigation from home screen
- Implementing your Unity integration
- Testing and iterating
Troubleshooting
Unity View Not Displaying
- Check Unity project is exported correctly
- Verify platform-specific setup (Android/iOS)
- Check console for initialization errors
No Communication
- Ensure
onEngineCreatedis called - Verify Unity script is attached
- Check message target names match
Performance Issues
- Enable message batching for high-frequency updates
- Use throttling for UI controls
- Profile with DevTools
The example app is a complete reference implementation - use it as a starting point for your own projects!