Have you found the whole multi-target cross-platform support work as advertised? All VMs / engines / transpilers (Java, Mono, Unity, Adobe Air) - I’ve ever worked on always end up “write once, debug everywhere” instead of what they advertise (“write once, run everywhere”). So I’d suspect you leverage the individual target debugging pretty often no? If so, any big gotchas to look out for?
I agree, that there are risks in cross-platform development, that debugging will become more complicated.
Some features are platform-specific. Using a native extension on a mobile platform is a good example of this.
There are two big principles that will avoid these problems:
- Don’t use integers unless they’ve been initialized. Don’t expect uninitialized
Boolvalues to always be
The behavior on dynamic and static platforms are a bit different when values are uninitialized.
var number:Int on Flash Player will be
undefined. Neko is
You can avoid headache if you expect to initialize your value (like
number = 0) before you do
number + anotherValue or another kind of math. The platforms are pretty consistent from that point on.
Boolean values are similar, an unitialized
Bool while evaluate as false in an
if (!boolean) check on all platforms, but an exact check (like
if (boolean == false)) may fail on some of these platforms. Better to avoid that pattern or to initialize first if you want to work that way.
String, objects and other types that are default
null behave basically the same, except Haxe simplifies things to a basic
if (object == null) check, so you don’t need to bother with triple equal signs or various null/undefined types.
- Don’t use Dynamic code, or if you do, be aware that it will most likely be where your code breaks
Haxe will turn even untyped code into strictly typed code by default (such as
var int = 100; being typed as
Int automatically), which keeps things working well, nearly always if the compiler allows compilation.
However, you can use
:Dynamic explicitly, or
A few Haxe features will be dynamic under the hood on the C++ target, so there are some things you may choose to avoid for performance reasons, but these features are different than a true
Dynamic type because the compiler has a type for it during compilation, which guards against issues that could come up.
It helps to test different target types periodically, to be sure things are still compiling. Particularly, it helps to test the non-Flash targets, because that tests our open-source runtime instead of Adobe’s runtime in Flash Player
Works like a charm! (flash,html5,android,linux,windows - ios comes next)
Yes, sometimes(seldom) there is platform specific stuff to solve, but thats normal in a developing/growing environment.
Luckily i am old-school(C++) and do initialize by principal.
Same as i use Destructors to clean up, GC can do the stuff i overlook
Thanks so much Josh for the detailed break down. Seems reasonably straightforward!
Thankfully I only hire C++ game developers (even to do flash work!) so I have the same benefit.
One of my concerns is how as3hx handles dictionary / array conversion. Based on this nice looking GitBook (is this the official, most up to date one?) - it implies it attempts to figure it out automatically.
Thanks again for all the support guys!