Bridal Bouquet Builder 42020-03-09
Bridal Bouquet Builder (BBB) is an app that allows brides-to-be to design their own custom bouquets in 3d.
BBB is an ad-supported, in-app-purchse app on Android and iOS for a client in the midwest. The goal is to allow brides to design their own bouquets in 3d by selecting bouquet styles, variants, flowers, and colors.
The styles and variants of the bouquets are not programmatically generated, they are painstakingly built by hand from the client’s own real bouquet designs. Those styles and variants are integral to making a bouquet look good and realistic, and algorithmic approaches are completely inadequate, because they fail to relate in any way to how a florist will actually construct the bouquet. Therefore, the bouquets in the app must come from a real florist.
To accomplish this, I needed to build an elaborate content management system that could handle the bouquet templates and allow the user to replace parts of the bouquet, as well as save that data to the device.
During earlier versions of this app, we learned that using it on a computer, on the web, or on an in-store kiosk was not feasible, so we moved to a mobile app solution. We of course target both major platforms.
The app is built in Unity, which allows us to publish to both iOS devices and Android devices.
Early on in this version of the project, I implemented a MVC pattern in hopes that it would help organize things, but the techniques for connecting the frontend with the UI were not very conducive to this. The codebase is broken up into the following regions:
- Model handles the data of the app
- AppData contains things like model bootstrapping, IO startup, initializing ads, and other initialization tasks
- UserData contains dictionaries for all app content, including flowers, colors, bouquets, packs, and enhacements. It is the single source of truth about the user’s content.
- Navigation handles moving between the different screens of the app
- View handles showing the model to the user
- BouquetManager handles translating the user’s change requests to operations on the SlotBouquet, as well as selecting and instantiating the correct template.
- SlotBouquet is the core 3d component for building bouquets. It keeps the bouquet organized and maintains references to all its flowers, stems, and intended contents.
- ListManager handles the contents of the GUI lists, such as the user’s bouquet list or lists of variant bouquets
- ModalManager assists in displaying the right content in the flower/color selection modals
- Various ad components also live here
- Controller translates the user’s input to operations on the model
- Editor contains a number of tools for building the app, such as bouquet editors and thumbnail generation systems
- Edit Mode contains tests that can be run outside the runtime, largely unit tests on individual classes
- Play Mode contains tests that must be done in runtime, including complex, interrelated classes, integrations, and entire workflows.
The artwork generally fell into the following categories:
- 3d Assets built in blender and exported via FBX for use in Unity
- GUI assets mostly built using Affinity Designer and Photo
- Generated Icons that are generated by the app’s build process by taking generating thumbnails of the 3d content in the app
This is the fourth iteration of Bridal Bouquet Builder. I was originally brought on to build the second iteration for the client when the original developer faded into the ether. Version 2 was a desktop-based solution that worked well, but at the time the client and I disagreed about the best course for the app that would be financially viable. After I delivered version 2, the client hired another developer some time later, who tried to build an allegorithmic solution and packed it into a mobile app. Some years later, the client approached me again to fix version 3, which couldn’t produce anything that looked like a bouquet and had only a handful of flowers and options compared to the hundreds in version 2. So began version 4, where I set out to make use of the techniques in version 2 and recent developments in graphics technology to build a mobile app that would acutally fulfill the client’s needs.
As mentioned above, because I knew the design of the app by heart, I was able to start by creating a very detailed design doc from the outset and use that to estimate big portions of the project for the client. Of course, things changed a lot between the beginning and the end of the project, and the estimates were inaccurate, but it gave us a very good roadmap.
The Slog Bouquet system was first. When desiging a bouquet, the developer can use dummy flowers to duplicate and place flower slots. Each bouquet has a certain number of groups of identical flowers. Each group controls a number of the slots. By telling the
SlotBouquet component what group should be what flower and color, it can instantiate the right assets with a series of resource lookups.
Next was the editing UI, where the user actually makes their selections by choosing flowers and colors for each group. This was my first interaction with the new (at the time) unity gui system, so I learned a lot here.
Next was a large batch of flowers and other 3d assets. As the sole developer, the 3d assets were also my responsibility, so I took reference images given by the client, designed 3d models for each, and generally hand-painted the flower petals and leaves to avoid copyright issues.
Next was the application-level UI, including moving from page to page in the app.
Then it was time to save and load the bouquet. To keep our costs low and avoid hassles with server maintenance, we save the user’s bouquet data to their device directly. I added a wrapper over the top of PlayerPrefs in order to maintain data integrity and reduce the chance of data manipulation.
After that, I worked on the “carousel” UI structure, where the app would present the user with options generated from the model and the user would select from those options to move through the app.
Now that we could save, load, and navigate to a bouquet, it was time to work on the 3d navigation of the bouquet, such as zooming and orbiting.
With that done, I moved over to working on the system for in app purchases. This took a good deal of time, and complicated matters greatly in a lot of ways for the rest of the project.
After that, it was time to do a full integration build, which shook loose a lot of problems to fix, but we finally felt like the whole project was in the vicinity of completion. As it turned out though, a lot of work was still ahead of me.
Next were the ads, which were a whole other kettle of fish, which took a significant amount of time to get wrangled.
Then it was back to creating real flower packs for sale.
We added some enhancements after that, and then it was on to major user testing and bugfixing. Each of our builds seemed to shake a new problem loose, mostly with the build process and publishing end rather than with the core application programming. In there, I also built a number of report generation and automation tools to help us keep the project from breaking so much.
Then Google changed some requirements for their ads implementation and Unity’s implemntation lagged behind for a bit, so I was forced to come up with some creative solutions.
After that, Apple changed their submission system for IAP items, which torpedoed the way I’d built the first time, forcing me to build the IAP Sumbission fixture
As the sole developer on the project, not only were the backend code, frontend code, 2d artwork, graphic design, and 3d graphics all my responsibility, but so was the entire devops toolchain from Unity to Android and iOS.
Numerous times I was up against bad, incomplete, outdated, or factually incorrect documentation, with nobody to back me up. As a small business, the client doesn’t have infinite funding, so I was also trying to do all this as efficiently as I possibly could. On the upside, every success could be attributed only to myself. On the downside, some problems took weeks to solve.
Points of Interest
This class is the core of the whole concept of BBB. The
SlotBouquet class holds references to each group, which in turn holds references to each slot. It also generates and maintains all the stems in the bouquet.
SlotBouquet is the View analog to the Model’s
BouquetData and would consume it in order to build the view’s 3d model.
It would even count and report the triangles in the 3d bouquet so I could troubleshoot slowdowns.
Automated Testing in Unity
Unity includes the Nunit testing suite, but it seems very few developers actually make use of it. I used it as much as I possibly could afford to, especially on mission-critical components and classes.
In addition to writing unit tests and simple integration tests, I also developed a complex system of
FlowUtilities that allowed me to set up navigation paths in testing, so that entire workflows could be tested automatically. Unity’s cloud build system runs all playmode and edit mode tests on each dev build, so I can tell if things have broken before I try to push recent dev work to master, which generates the iOS and Android build files.
- Time This project frankly took years. I’m not sure if it could have been done faster, but it certainly wasn’t simple, and my estimates were confounded by problems that would arise from unknown pitfalls from developing for Android and mostly iOS. iOS was the bane of this project’s schedule, but most of our target market seems to prefer iOS.
- Complexity The app alone is complex. How it manages all the data fo 300+ assets and allows them to be connected together was hard enough. Add in the complexity of displaying ads in a compliant way, providing In App Purchases for hundreds of items, and publishing to two very different platforms was almost enought to break the spirit.
- Testing As ever, I didn’t have enough time to write complete unit tests for every component. Instead, I had to make do with limiting the testing to the most complicated and vital parts, while trying to keep code coverage up with complete workflow tests. Now, most of our bugs come from platform-specific problems and malformed content that isn’t technically broken.
What I learned
- Apple Clearly, I did not account for all the garbage and chaos of developing for Apple. At a guess, I’d say that at least half of the total development schedule was dealing with some Apple-specific problem. If I can avoid developing for them in the future, I will.
- Client Attention I had to spend such long periods fixing major issues with Apple that I had trouble keeping the client thinking about the thing I was trying to accomplish, and stay the course. I don’t know how communicate more clearly to the client that the design isn’t changing, it’s just taking a long time to unbreak things.