WWW.GAMEDEVELOPER.COM
A Unity project for all platforms: Part 1
Today I would like to share one of the template projects, the settings and modules of which I use from project to project. With its help I will show one of the options for setting up a Unity game that will work on many platforms, including Steam, Android platforms (Google Play), Web platforms (platforms supported by Playgama (Instant) Bridge, for example, CrazyGames, Game Distribution, Playgama, Yandex Games etc.). This template project covers the following topics:- Working with basic project classes- Saving game data- Importing textures, working with sprites and Sprite Atlas- Transitions between scenes- Project build settings- Project .gitignore file- Video playback- Playing music and sounds- Input System- Working with metrics- Classes for monetization via advertising- LocalizationIn this article, we will analyze the first few topics, the rest will be described in upcoming articles.The template project is available for download at the following link.A small disclaimer: using this template does not guarantee passing the moderation of specific platforms, each game has its own nuances that, one way or another, affect the successful overcoming of the obstacle in the form of moderation.In this project, I tried to collect the most frequently used mechanisms that are necessary in almost any game.So, let's get started...Working with basic project classesFirst of all, a few words about the project structure. If everything is pretty clear with most of the folders (but one way or another, we will analyze everything in the corresponding chapters), then the Scripts folder is worth a special mention. The root of this folder contains all the scripts that are inherited from the MonoBehaviour class, and which, accordingly, can be added to game objects as components.The Services folder contains classes for working with localization, metrics, sound and advertising.The Settings folder contains everything you need to successfully save and load game data.The Utility folder contains several constant classes, as well as a number of static utility classes with auxiliary methods.In this chapter, we will focus on two main classes of the Scripts folder, namely SingletonServices and GameServices.Let's start with the first and most frequently used. SingletonServices, as the name suggests, works on the principle of the singleton template, accordingly, when initializing project objects, only one such object of the SingletonServices class will be created. This class provides access to all available auxiliary services of the game that may be needed on any scene. I emphasize the word "any", because if, for example, we compare this class with GameServices, which use cases are limited to game scenes only, excluding the initialization scene. But we will discuss it a little bit later.The SingletonServices class stores links to services for working with localization, music, advertising and metrics. Here you can also find methods for loading and saving game settings, as well as a method for getting sprites by their name. For example, saving game settings using this class will look like this:_singletonServices.SaveSettings();where the _singletonServices variable was previously initialized as follows:SingletonServices _singletonServices = SingletonServices.Instance;In order to work appropriately SingletonServices must be added to the game object on the initialization scene (InitScene).The second most important class GameServices is also a singleton and is used to combine classes and methods for working with game objects. For example, hide the game menu and show the game itself, and vice versa, as well as change the language and others. With a significant expansion of the project, I still recommend separating, for example, work with the game UI to a separate script and using GameServices only as an intermediate class for access to the UI controller. There is not much need for this in our template project. In order to work appropriately GameServices must be added to the game object on the scene immediately following the initialization one (in our case, this is MainScene). In addition, since GameServices uses SingletonServices methods inside itself, it must be initialized after the latter. To do this, go to the project settings and set the order of script execution as follows:Saving game dataAs I mentioned earlier, all scripts for saving game data are located in the Scripts/Settings folder.GameSettings is the main object for game data. I have added several fields for saving in it, for example, the selected language and the number of button clicks.The file that is directly involved in loading and saving GameSettings is called FileSettingsAdapter. It implements the ISettingsAdapter interface, which contains only two methods: loading and saving.Saving data is probably quite obvious, but it is worth saying a few words about the signature of the loading method. Now it looks like this:void LoadSettings(Action<GameSettings> callAfterLoad);The method does not return anything, but only accepts a delegate as a parameter, a reference to the method that should be called after the data loading is complete. In the general case (for example, for PC and Android builds), such a design is not necessary. This is done in order to support the web version, which we will talk about separately in one of the upcoming articles.The entire process of loading game settings can be viewed in SingletonServices.Start method, the saving process can be viewed, for example, in the GameServices.IncreaseCounter.Importing textures, working with sprites and Sprite AtlasLet's now discuss the components of the Sprites folder and start with a small, optional TextureImporter file. For some unknown reason, Unity decided to change the default behavior of the sprite importer and began to set the Sprite Mode to Multiple by default (previously it was Single), which means that the added image contains more than one sprite, for example, it can be a sprite sheet with character animation. So, if your project has much fewer sprite sheets than regular single sprites, then you can create a TextureImporter and set sprite settings for it, which will be applied to all imported textures by default. To do this, in the importer settings, you need to click on the preset selection button and create a new one with the desired import parameters.We change all the necessary parameters of the created preset (in the case of this particular template project, the Sprite Mode was changed to Single and compression was turned off) and add the preset to the default ones.Now when adding new sprites, their settings will match the settings of the created TextureImporter.Now let's look at the SpriteAtlas file, which not only allows you to reduce the number of draw calls, but also provides a convenient way to get sprites by their name in the code. You can create a sprite atlas in the following way:Now about the atlas settings.You need to be extremely careful with the Allow Rotation and Tight Packing parameters. They are enabled by default, but this sometimes leads to various distortions, flips and artifacts if you change component sprites on the fly from the code.And of course, don't forget to add folders that will be nested in the created sprite atlas. In our case, this is one folder named Atlas. In the Sprites directory, there is also a NonAtlas folder, which, as you can judge by the name, we do not add to the sprite atlas. For example, you can store icons, a cursor, etc here.An example of getting sprites from a sprite atlas by name can be found in the SoundsButtonController.Start method.Transitions between scenesAn example of transition from the initialization scene to the main one can be seen in the InitSceneLoader class. I need to mention that this script should be added as a component to the game object on the InitScene scene.In the LoadingCheck method of this script, we wait for the initialization of all the main services, without which our game cannot work, and if everything is successful, in this case the intro video is launched, after which the transition to a new scene is carried out by the SceneManager.LoadScene method. Playing the video, of course, is not necessary here, and serves only as an example. Alternatively, you can launch any animation or immediately go to the main scene without additional steps.Project build settingsThe main branch of the project is currently configured for the Android build, so in this article I will show the main settings for this platform, and I will describe the remaining settings in upcoming articles.So, when creating an Android project, I first go to the Project Settings -> Player -> Publishing settings section and check the following files: Custom Main Gradle Template, Custom Gradle Properties Template and Custom Gradle Settings Template.Believe me, this will save you from a painful headache when it comes to importing and using third-party packages, for example, the EDM package, also known as external dependency manager, which is needed for the Firebase, Appodeal, and other packages.Next, I go to the Other Settings settings, set the package name and set the Target API Level.By default, the Target API Level is set to Automatic (highest installed), which means that when building an Android project, Unity will rely on the Android SDK and NDK already installed on the computer, so if, for example, version 33 is installed on the computer, then after building the package you will not be able to upload it to the Google Play Console, since at the moment the minimum value of Target API Level should be 34. But I would not recommend rushing and setting the highest version either, or at least have the opportunity to test your application on more than one device. Otherwise you could catch something like this:In short, not long ago, if you set the Target API Level to 34, the game crashed when it launched on devices with API level 34 (it worked successfully on the rest). The solution here, unfortunately, is not the most pleasant and you will have to update Unity to a more recent version with that fix on board, which is not always possible and/or painless.Project .gitignore fileI would like to finish today's part of the article with a short mention of the .gitignore file. There is nothing special here and at the moment it contains all the files and directories that should not be added to the repository. I will only add that it ignores folders web_build and PCBuild. I usually add these folders myself and they serve, apparently, exclusively for builds of the corresponding platforms.That's all for today, we will continue to analyze this template project in the upcoming articles, but you can download it and analyze it yourself right now at the following link.I am collecting wishlists here and here.Thank you for your attention!Link to my website
0 Comentários 0 Compartilhamentos 16 Visualizações