Unity Development Services

Unity is the pragmatic choice for a large share of interactive projects: strong 2D and 3D support, mature AR and VR tooling, wide platform reach, and a large talent pool. We build games, simulations and immersive applications in Unity and ship them across mobile, PC, web and headset.

What We Build in Unity

  • Games2D and 3D, mobile through desktop.
  • Simulation and training — realistic environments with authored scenarios. See simulation and training software.
  • AR and VR — headset and mobile-AR applications. See AR and VR.
  • Interactive visualisation — 3D product, facility and data experiences.
  • Multiplayer and networking — shared sessions, which is where most of the hard engineering is.

Where Unity Projects Get Into Trouble

Rarely in prototyping — almost always in performance and scale. A scene that runs beautifully on a development machine and poorly on a three-year-old phone is the classic outcome, and it is usually an architecture problem rather than a settings problem: asset budgets, draw calls, memory and physics decided too late.

We plan for the target device from the start, because retrofitting performance means rebuilding rather than tuning.

Unity or Unreal?

Both are excellent and the honest answer depends on the project. Unity generally wins on mobile, AR/VR tooling maturity, and iteration speed; Unreal tends to win on high-fidelity rendering. We build in both and will recommend based on your target platform and visual bar rather than preference.

Tell us what you are building and where it needs to run and we will advise honestly.

Related services

Which Unity Version Should a New Project Start On?

The version number matters far less than the render pipeline you commit to. A long term support release is the sensible default for anything with a production horizon, because fixes keep landing and the feature surface stops shifting under your team. The decision worth arguing about is Built-in, URP, or HDRP. That choice governs which shaders, lighting workflows, and post-processing your artists can use, and moving a project across pipelines after art is authored means reauthoring materials and lighting, and usually renegotiating the visual target with everyone who signed off on it.

We settle the pipeline against the actual target device before art production begins, then leave it alone. It is one of the few Unity decisions that is awkward to reverse.

The Asset Store Question

Third party packages are a legitimate part of Unity work and we use them. The risk is concentration. A package that gets a prototype moving can later be the reason an engine upgrade stalls, or the reason a platform port needs a rewrite, because the author moved on and the source was never yours to change.

The test we apply before adopting one is simple: is full source included, is it actively maintained, and could the team take it over if the author disappeared. For systems that are painful to swap late, meaning input, save and serialization, networking, and platform SDKs, we keep dependencies few and shallow. For editor tooling and content authoring the calculation is looser, because a failure there costs you convenience.

How a Unity Engagement Is Structured

Work runs in stages that each end in something you can run yourself. A prototype answers whether the core interaction holds up. A vertical slice takes one representative piece to shipping quality on the real target device, which is where performance assumptions meet the hardware. Production then scales content against a pattern that has already been proven.

Deploy to that device early. It is the easiest step to postpone, because a scene authored on a workstation reads as finished long before it runs at frame rate on a phone, a browser tab, or a standalone headset. Regional Service Coverage sets out how milestone builds and reviews work when the team is distributed.

Not Everything That Arrives as Unity Work Needs an Engine

Some projects described as Unity work are better served without a game engine at all. A form driven training module with a handful of diagrams is a web application and stays easier to update as one. A single linear walkthrough that nobody needs to steer is a rendered video. A configurator with a fixed set of combinations can often be handled with pre-rendered images and a straightforward front end. A data dashboard with a 3D chart in it is a dashboard.

If the interaction is flat and interface shaped, an engine adds a build pipeline, a runtime, and a store compliance surface that you then own for the life of the product. Settling this while the tooling decision is still soft saves an awkward conversation later.

One Codebase, Several Targets

Reach is the usual reason a team picks Unity. One codebase can serve phones, browsers, desktops, consoles, and standalone headsets. What travels across those targets is the gameplay logic. What does not travel is input handling, interface scaling, asset delivery, store requirements, and the performance budget, and each of those has to be built and tested per target.

So fix the target list before production starts. Every addition brings its own build configuration, its own QA pass, and its own release process, and adding one late costs more than it looks like it should. Platforms covers what each target asks of a build, and Unreal Engine Development Services covers where visual fidelity earns its keep.

Authority, Latency and Transport

The first decision in a shared session is who owns the truth. A server authoritative design simulates on a machine no player controls and treats client input as a request, which is the only structure that survives a competitive game or anything with a score that matters. Cooperative work among trusted users can run host-client, where one player's machine is the server and everyone else inherits its ping, its uptime and its ability to end the session by closing the application. Peer to peer with deterministic lockstep avoids servers entirely, but it requires every machine to produce bit identical results from the same inputs, which floating point behavior and physics solvers make difficult to guarantee across platforms and compiler targets.

Latency is not something netcode removes, only something it hides. Client-side prediction runs the local player's input immediately and replays queued inputs when the server's authoritative state arrives, and remote entities are drawn from an interpolation buffer that is deliberately a hundred milliseconds or so behind so that a lost packet does not stall them. Both techniques have a cost in gameplay design rather than in code: every mechanic has to tolerate being corrected after the fact, which is why hitscan weapons, instant pickups and physics objects that players push each other with are the mechanics that get redesigned once the netcode is real.

Reachability is a separate problem from latency. Consumer devices sit behind NAT and cannot accept inbound connections, so a session needs either a relay or a server with a public address, and a relay adds a hop along with the round trip that comes with it. Dedicated servers are per-region infrastructure that somebody has to operate and pay for continuously, which makes the hosting model a running cost rather than a build cost.

The items below are settled before netcode is written, because each one changes how ordinary gameplay code is written rather than what it gets wrapped in later.

  • Authority model: server authoritative, host-client, or peer to peer.
  • Tick rate and send rate, which are two separate numbers. Simulation can run at 60 Hz while state goes out at 20 Hz, and the gap is filled by interpolation on the receiving end.
  • What gets replicated and at what precision: full snapshots, deltas against the last acknowledged baseline, or events only. Quantizing positions and rotations is usually where bandwidth is actually recovered.
  • Reliability per channel. Movement can be unreliable and unordered because a newer packet supersedes a lost one, while an inventory change or a score update cannot.
  • Maximum session size, because the per-tick cost of naive replication grows with the square of the participant count and interest management has to be designed in, not added.
  • Whether late join, reconnect and host migration are in scope. Each of those requires serializing the whole session state, not just the player, and that is a different piece of engineering from moving transforms around.

Asset Delivery and Download Size

A build has two size numbers and they are not the same: what the store allows in the initial download, and what the device can hold in memory at once. Google Play limits the compressed download of an Android App Bundle's base module and its configuration APKs, currently 200 MB, with anything beyond that delivered as install-time, fast-follow or on-demand asset packs. Apple applies its own ceiling and warns users before large downloads over cellular. A project that ignores both numbers until submission discovers them at the point where the content is already authored.

Everything placed in a Resources folder is built into the player whether or not it is ever used, and its dependencies come with it. Addressables replaces that with content referenced by key through a catalog, with reference counted loading and groups that can build to local or remote bundles, which is what makes patching content without a store submission possible. The limit worth knowing up front is that remote content can be data only. On ahead-of-time platforms there is no runtime code generation, so new assets can be downloaded and new scripts cannot.

Texture format is a build-level decision with a large memory consequence. ASTC covers modern mobile and standalone headsets, BC7 and the DXT formats cover desktop, and ETC2 is the older Android fallback, but a texture whose dimensions do not suit the chosen format falls back to uncompressed without stopping the build. Mipmaps add roughly a third again on top. Audio has the same shape of decision: streaming, decompress on load, and compressed in memory trade disk reads against resident memory, and background music left as decompress on load is a common way to lose tens of megabytes for nothing.

  • The Editor log's build report lists what each asset contributed to the build, which is the fastest way to find the one uncompressed texture that is larger than the rest of the scene.
  • The Memory Profiler package takes a snapshot of what is actually resident on device, which is a different question from what the build contains.
  • The Addressables analyze rules find assets duplicated across bundles, which happens when a shared mesh or material is pulled implicitly into two groups and ships twice.

Scripting Backend: Mono, IL2CPP and What Ahead-of-Time Compilation Breaks

C# in Unity compiles to intermediate language and then follows one of two paths. Mono just-in-time compiles it at runtime, which is what the editor always does. IL2CPP converts the intermediate language to C++ and compiles it ahead of time, which is what iOS, WebGL and consoles require. That difference is the reason a class of bug exists only in the built player and cannot be reproduced by pressing play.

Ahead-of-time compilation removes runtime code generation. System.Reflection.Emit is unavailable, generic virtual methods over value types can throw at runtime when that specific instantiation was never generated at build time, and managed code stripping removes types that nothing references statically. Reflection-based serializers are the usual casualty, because the type they need is reached only by name at runtime and the stripper cannot see it. The fix is a link.xml entry or a Preserve attribute, and the symptom that points there is a field that populates in the editor and comes back null or missing in the player.

The other cost is iteration. An IL2CPP build compiles the entire generated C++ and takes far longer than a Mono development build, so the practical arrangement is to iterate on a Mono development build and run IL2CPP builds on a schedule and ahead of any milestone rather than at the end. That split also gives a clean diagnostic: a defect that reproduces in a Mono development build is application logic, while one that appears only under IL2CPP is stripping, an ahead-of-time limitation, or a native plugin.

Project Setup That Survives More Than One Developer

Unity projects are unforgiving of casual version control. The Library folder is a derived cache and belongs in the ignore file, while .meta files must be committed, because the GUID inside a .meta is how every reference in every scene, prefab and material resolves. Losing or regenerating one does not raise an error. The object still exists, the reference is simply empty, and it usually surfaces as a missing script or a pink material some commits after the change that caused it.

Scenes and prefabs serialize to YAML, which is readable in a diff but is not reliably mergeable when two people have edited the same scene, because the file is a graph of file IDs rather than lines of text. The structural answer is composition rather than merge tooling: small prefabs, additive scene loading so different people own different scenes, and prefab variants for the cases that would otherwise duplicate a hierarchy.

  • Asset Serialization set to Force Text and Version Control mode set to Visible Meta Files in the editor project settings, so diffs are readable and meta files are visible to everyone rather than hidden by editor preference.
  • An ignore file that excludes Library, Temp, Obj, Logs, Builds and per-user layout files, and excludes nothing that carries a GUID.
  • Git LFS configured for binary art before the first large binary lands rather than after, because converting history afterward rewrites every commit and everyone reclones.
  • Packages/manifest.json and packages-lock.json committed together, since the manifest alone lets two machines resolve different package versions and produce different builds from the same commit.
  • One pinned editor version recorded in the project, because opening a project in a newer editor upgrades it and the upgrade is not something you undo by discarding changes.
  • The build settings scene list treated as code, because a scene missing from that list is present in the editor and absent from the player, which is a bug that only exists in builds.

Frame Budget on a Standalone Headset

A standalone headset runs a mobile-class system on a chip at a display rate of 72, 90 or 120 Hz. At 90 Hz that leaves about 13.9 ms per frame for simulation, culling, draw call submission and the GPU work for both eyes. A missed frame is not a cosmetic problem in that context, because the compositor reprojects the previous frame and the user feels the result physically rather than seeing it.

Stereo rendering is per eye but not double. Single-pass instanced rendering submits geometry once and uses instancing for the two views, which is mostly a saving on the CPU side of draw submission. Forward rendering with multisampling is the usual choice because tile-based mobile GPUs make the bandwidth of a deferred G-buffer expensive, and full-screen post-processing is priced in bandwidth rather than shader complexity for the same reason. Fixed foveated rendering trades peripheral resolution for fill rate and costs very little at low levels.

CPU bound and GPU bound feel identical from inside the headset, so the diagnostic order matters. Read GPU time against total frame time in the platform's own metrics tool first, then Unity's profiler for main thread cost, then the render thread separately, because a render thread stalled on draw submission looks like a GPU problem from the main thread's point of view. Batch count and SetPass calls point at the CPU. Changing the dynamic resolution scale is the cheap test for fill rate: if halving it does not move frame time, the fill rate is not the constraint and shader complexity is not either.

Frequently Asked Questions

What do incoming 3D models and source assets have to look like to be usable?

They have to be game-ready meshes rather than CAD or film assets. That means FBX or glTF, real-world scale with one unit as one meter, Y up, transforms frozen, pivots at the point the object actually rotates about, non-overlapping UVs on anything that will be lightmapped, and triangle counts and texture sizes chosen against the target device rather than the workstation. Materials do not survive the trip whatever an exporter claims, because shaders are specific to the render pipeline the project is on, so materials are rebuilt in the project. CAD formats such as STEP and IGES are not directly usable at all: they describe NURBS surfaces and have to be tessellated and reduced first, and the reduction is where most of that work sits.

Does Unity include a back end, and what does an application connect to?

Unity ships no back end. There is no database, no user account system and no server component in the engine, so anything that has to persist beyond the device or be shared between users is an external service the application talks to over HTTP, usually through UnityWebRequest. PlayerPrefs is a small key value store for settings, held in the Windows registry or a macOS plist as readable text, and it is not a save system or a place for anything a player would mind losing or editing. If an API already exists, that is normally the thing to build against; note also that mobile and headset platforms suspend a backgrounded application, so long-lived connections need a reconnect path rather than an assumption of continuity.

What are the real limits of the WebGL target?

A WebGL build runs in one browser tab under constraints that do not apply anywhere else Unity ships. Memory is the first ceiling: the heap is sized at build time, the 32-bit WebAssembly address space tops out near 2 GB, and practical budgets sit well below that, so a scene built for desktop does not port by changing the build target. There is no raw socket access, so networking is HTTP or WebSocket rather than UDP. Threads require SharedArrayBuffer, which requires cross-origin isolation through COOP and COEP response headers, so most builds run single threaded, and the web server also has to send the correct Content-Encoding for gzip or Brotli compressed builds or the browser downloads a file it cannot decode.

What determines whether an existing Unity project can be picked up mid-flight?

Whether it builds from a clean clone on a machine that has never opened it. The specific checks are the editor version it was last saved with, whether the Library folder was committed (a sign that GUIDs and caches have been fought before), whether every Asset Store package in it shipped with source and a license that transfers to a new holder, and whether packages resolve from a committed manifest and lock file rather than local paths. Projects that build on exactly one person's machine are common, and the gap is usually an uncommitted plugin, a package referenced by a path that only exists there, or signing material living in someone's keychain.

Who has to hold the Unity licenses?

Unity is licensed per seat to a legal entity, not per project and not per build target, and the license follows the organization whose product is being shipped. Personal is free below a trailing twelve month revenue and funding threshold, above which Pro or Enterprise seats are required, and Unity's terms require everyone in an organization to be on the same tier rather than mixing them. Both the threshold and the surrounding terms have been revised more than once in recent years, so the current figure is worth reading from Unity's own license terms rather than from a secondhand summary.

How does getting a build onto an actual device work?

Android devices and standalone headsets install directly from the editor over USB once developer options and USB debugging are enabled, using an SDK, NDK and JDK that Unity Hub installs per editor version; release goes out as an AAB through the store, internal builds as an APK sideloaded with adb. iOS does not work that way. Unity does not produce an .ipa at all, it emits an Xcode project, so a Mac with Xcode is required along with an Apple Developer Program membership, a signing certificate and provisioning profiles before the first install on the first device. Tester distribution then goes through TestFlight, which involves a review step that is not instantaneous.

What has to exist before a training simulation can be built?

The procedure being simulated, written down. That means the steps in the order that matters, which deviations count as incorrect, what conditions end a run, and what is scored, because those are the requirements and no amount of environment art substitutes for them. The environment needs its own source material: floor plans or measured dimensions, photographs, and the make and model of equipment that has to be recognizable. Access to someone who actually performs the procedure is the part most often underestimated, since without it the scenario becomes an approximation of the procedure, and an approximation is what it will train.