I’m working on creating a bike fitness app that can be used on iOS (but eventually any other device).
This isn’t a new topic, there are apps and games out there like Zwift, Rouvy, and FulGaz, and I’ve researched about how these work from a high level, but I can’t even decide on the best approach for my version.
There are tradeoffs and I could use expert opinions.
Build directly into Xcode using SpriteKit:
There is well-established code connecting apps to bike trainers, and I’ve reproduced this code already.
I don’t know how to connect a bike trainer to UE4 or Unity. Probably a way to do it, but then do you have to build the solution in C++ or Objective C? Can that be executed by a Swift-written app?
Will the C++ or Objective C approach have the same supported Bluetooth services already available in the Swift implementation?
Having the code be close to platform (e.g., iOS) seems like better performance
No requirement to provide 5% of revenue to UE for use of their game engine
Building in UE4 or Unity:
More features, an already-built game engine, more powerful animation with Unreal Engine and Unity.
More documentation on coding physics, game mechanics, etc.
Even though I can connect my bike trainer via Bluetooth using Swift, if I build a Swift-based app I don’t know if there’s a way to then relay that Bluetooth connection/data to whatever game/app I build in Unreal Engine or Unity. Is there a way to do that? Or do I have to pick 100% in Swift v. 100% not Swift?
Will Swift be usable on non-Apple platforms? This seems like a strength for UE or Unity.
Honestly, if you are doing this just for iOS, then I’d do this one in Swift. If you’re building something that can be done with just SpriteKit… then do it with just SpriteKit. It’ll be lower-overhead, and I strongly suspect you will have much less of a pain point in dealing with CoreBluetooth when using Swift directly.
I say this as someone who works in embedded firmware (and extensively with Bluetooth) for her day job, and thus has sometimes-painful familiarity with the guts of both the iOS and Android Bluetooth implementations.
Now, if you’re trying to do it on multiple platforms, that’s a horse of a different color; Swift, SpriteKit, and CoreBluetooth itself are all pretty heavily tied to the Apple ecosystem. If you don’t want to write two versions of your app, you’re not going to be using Swift.
Unreal can certainly help there, though you’d be writing all your stuff in C++… and while I suspect there are plugins that give support for Bluetooth on Android or iOS, I strongly suspect those plugins use different APIs. So you’d be writing two sets of Bluetooth code anyway. In which case, I’d just write my own “Bluetooth” plugin for Unreal using a single standardized API, and then have versions of it for Android or iOS that do all the platform-specific glue behind the scenes. All of which feels like a lot of work to duplicate features available far more readily in other forms.
Honestly, depending on how complicated your game framework is, I might stick with a (semi-)simple cross-platform toolkit like Xamarin. Because if you’re looking to do a fairly simple sprite-based mobile game that integrates heavily with some external Bluetooth device, using Unreal feels to me a little like going after a mosquito with an Abrams tank; it’s both excessive firepower for the job, and you might not hit the target anyway.
When you say “I’d just write my own “Bluetooth” plugin for Unreal using a single standardized API”, is there documentation out there (or examples) that you would look to in order to figure that stuff out?
Main reason for Unreal or Unity is because I want to produce high quality graphics/animations. Probably won’t require anything super advanced gameplay wise at this stage (but that’s a possibility for down the road projects). But if there’s a way to create great visual scenes a virtual biker can ride through, and some added bike-physics, that’s the goal. Current offerings are very basic graphics and I think there’s so much potential for dramatic landscapes.
Unfortunately, no. I mean, at my day job, I am the Bluetooth domain expert – I know it well enough to read packet frames from a wireless sniffer, which is a thing that horrifies me on some level – so I have to admit I’ve got no clue offhand where to look for a good tutorial on such.
If I were doing it, honestly, what I’d do would be like:
Design what I’d want an Unreal-ish Bluetooth API to look like when used from inside Unreal. (Including what it would expose to Blueprints.)
Implement that overall API, backed by a “mock” layer that can run anywhere and just returned made-up devices with expected behavior. (Very useful both for initial code and testing!)
Implement a version of the API that is only compiled for the macOS and iOS targets, and ensure that when compiling for one of those, that’s what backs the API. Yeah, you don’t need macOS for this particular use case, but I like to be thorough… and more to the point, like 98% of the macOS code would be identical to the iOS code, so why not.
Implement a version of the API for Android. This… would get potentially irksome, as a surprising amount of the Bluetooth functionality is not available in any meaningful way to userspace processes in JNI, especially if supporting older versions of Android. So you’d probably be calling back from C++ code into the Java/Kotlin layer of Android. Still, once done, now you can use the same in-engine code to access Bluetooth on iOS, macOS, and Android.
If I had lost my mind entirely by this point, write implementations of the backing Bluetooth code for Linux (atop BlueZ) and Windows (probably atop the UWP Bluetooth API, which is marginally less painful than other Windows options).
It would not be a small project. It’s the sort of “well, that was a lot of work” that I would want to toss onto Github or into the Marketplace afterwards so that other people didn’t have to suffer the same process.
Whereas if you’re using an existing cross-platform application framework like Xamarin or whatever, it’s more “just include the Bluetooth library and go”. But you also don’t have a high-octane 3D gaming engine in Xamarin.
I’d say it comes down to “do you need the sort of engine that can power a AAA gaming title more than you need easy Bluetooth support?” If the answer is yes, go with Unreal and write a Bluetooth library for it. If the answer is no, go for a cross-platform application toolkit.
It’s totally possible to write your own additional C++ code in Xcode (or visual studio, or vim) and link it into your Unreal project. There’s no difference in “power” in whether you go one way or another.
However, if you are making a 2D game, the overhead and higher system demands of Unreal may not be worth it. It depends on how good you are with 2D animation/graphics programming in general. If you’re going to be building a lot of UMG GUI animations, pull in 3D particle systems, render animated 3D assets to 2D surfaces, and so on, then, yeah, Unreal may help you out there. But if it’s all sprites and SVGs and sliding them across the screen, I’d probably suggest just going straight for native code.
I would recommend against Swift or Objective C if you want to port it to other platforms, though. Native C++ is the “lingua franca” of code-that-runs-everywhere, and the more you can stay there, the less problems you’ll have.
Basically this. (And the same is true in reverse, for Kotlin and Android.)
The only thing I’d add to this is that – as I mentioned earlier in the thread – if you want the most portable code between the two mobile platforms, just write it using a cross-platform toolkit from the beginning and you’ll save yourself a lot of work and headache later.
Want to do it all in C++? Use Qt if you want an entire application framework, or SDL2 if not. (If you don’t, graphics in C++ on Android can be an adventure at times.)
Prefer C#? Xamarin.
Javascript more your speed? I question your life choices, but React Native or something. (I have a deep and perhaps borderline-irrational dislike of Javascript.)
Dart? …Flutter. (Honestly, if you’re not using Flutter, why on earth are you using Dart? It has basically no other widespread use I’ve ever seen.)
Etc.
I mostly tend to suggest C# and Xamarin to people because it seems one of the more approachable options; C# is a friendlier language than C++ to folks who aren’t experienced software developers.
What do you mean? Javascript is a perfectly fine bootloader for a WASM binary which is produced by a Rust program. Disliking Javascript is like disliking the power button.