Starling was built with 2D in mind, and that's where it really shines. For 3D games, there are other powerful alternatives – like Away3D.
However, even a 3D games needs a 2D menu, and other 2D overlays. What if you could use Starling for the 2D parts of those games? Actually, you can do that: you just need to have both engines use the same Stage3D rendering context.
Here's how it works in a nutshell.
I'll show you the principle not with a 3D engine, but simply with two Starling instances. Any 3D engine (or your custom Stage3D code) can be added just the same way.
Sharing a context between different Starling instances means that Starling doesn't have control over the context any longer. In a set-up like this, Starling won't make any changes to the context. You are responsible for setting it up correctly, and for updating it each frame.
That's why there's a little more boiler-plate code present than in a usual Starling project. Still, everything is rather straight-forward.
Here's the start-up class of the project:
package { import flash.display.Sprite; import flash.display.Stage3D; import flash.events.Event; import starling.core.Starling; [SWF(width="640", height="480", fps="30", backgroundColor="#000"] public class SharedContextTest extends Sprite { private var mStarling1:Starling; private var mStarling2:Starling; private var mStage3D:Stage3D; public function SharedContextTest() { var isApple:Boolean = Capabilities.manufacturer.match(/(iOS)|(Macintosh)/) != null; Starling.handleLostContext = !isApple; // not required on Apple devices // save a reference to the stage3D instance we're using mStage3D = stage.stage3Ds[0]; // create the 3D context mStage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated, false, 0, true); mStage3D.requestContext3D(); } private function onContextCreated(event:Event):void { // Manually configure the context. Important: if you use a different // size than "stage.stageWidth x stage.stageHeight", you have to update // Starling's viewPort property accordingly. mStage3D.context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0, false); // Create our two Starling instances with the preconfigured stage3D. // Starling will recognize that the context is being shared, and // will not modify it. if (mStarling1 == null) { mStarling1 = new Starling(Game1, stage, null, mStage3D); mStarling1.enableErrorChecking = true; mStarling1.start(); mStarling2 = new Starling(Game2, stage, null, mStage3D); mStarling2.enableErrorChecking = true; mStarling2.start(); addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true); } } private function onEnterFrame(event:Event):void { // The back buffer needs to be cleared once per frame mStage3D.context3D.clear(); // Advance both Starling instances mStarling1.nextFrame(); mStarling2.nextFrame(); // This moves the active back buffer into the foreground. mStage3D.context3D.present(); } } }
That's all that is to it! The classes 'Game1' and 'Game2' are omitted here: those classes would be the two root objects of the Starling objects.
The principle is the same when you exchange the second Starling instance with another stage3D framework. When you're combining Starling with Away3D, there is even a special tutorial available that will show you all the details: Away3D-Starling Interoperation.
The code above also handles lost context situations (where required). The 'onContextCreated' callback will be executed whenever the context is restored. Thus, the context will be re-configured after each context loss. The Starling instances are of course only created once.
If other frameworks can recover as well depends on the framework. Have a look at their documentation, or just give it a try!