Menghubungkan dua platform seluler dalam satu kode di Unity





Pengembang Unity sudah terbiasa mengelola aliran dan layanan game di platform seperti iOS dan Android. Namun, setelah layanan seluler Huawei muncul di ekosistem, kini Anda perlu mendukung versi lain dari gim tersebut jika ingin menjangkau pemain yang memiliki perangkat Huawei.



Artikel ini hanya tentang cara mengelola dependensi antara beberapa layanan seluler Android dan Huawei dalam satu basis kode dengan sedikit usaha.







gambar

Gambar 1. Perbedaan antara dukungan untuk berbagai platform dan layanan seluler



Seperti yang Anda lihat pada gambar di atas, ponsel Huawei menggunakan sistem operasi Android, jadi proyek Unity Anda harus menggunakannya saat membuat perangkat dari perusahaan ini. Namun, sekarang Anda perlu mengembangkan 2 APK berbeda untuk Android atau paket terpisah untuk Huawei AppGallery.





Apa perbedaan antara APK ini?



Perbedaan pertama dan terpenting adalah layanan seluler. Ini adalah layanan seperti pembelian dalam aplikasi, periklanan, layanan game, analitik, dll. Anda tidak dapat menggunakan GMS di perangkat seluler Huawei. Oleh karena itu, dua APK perlu dibuat: untuk rilis di Huawei AppGallery dan di Google Play.



Perbedaan penting kedua adalah nama paket. Karena kedua ekosistem berjalan di Android, untuk menghindari ketidakkonsistenan dan penggantian, Huawei App Gallery memiliki aturan bahwa nama paket Anda harus diakhiri dengan .huawei atau .HUAWEI. Pendekatan ini digunakan untuk memisahkan build Huawei dari semua perangkat Android lainnya.



Tapi jangan khawatir: kami dapat menangani perbedaan ini dalam satu basis kode.



Berikut dua trik kecil untuk membantu memecahkan masalah ini.



1. Pernahkah Anda mendengar tentang #defines?



Berkat defines (definisikan), kami dapat mengontrol aliran kami pada waktu pembuatan, dan berkat satu lingkungan pengembangan - dan selama pengkodean.



Aliran apa yang sedang kita bicarakan?



Bayangkan Anda perlu mengoperasikan dua jenis layanan game: Google Play dan Huawei. Untuk membuat aplikasi untuk mereka dalam satu kode, Anda dapat memisahkannya menggunakan definisi. Mari kita lihat contoh kecilnya:



internal static class GameServiceFactory
{
    public static IGameServiceProvider CreateGameServiceProvider()
    {
        #if HMS_BUILD
            return new HMSGameServiceProvider();
        #else
            return new GooglePlayGameServiceProvider();                        
        #endif
    }
}

      
      





Jika Anda menambahkan kata kunci "HMS_BUILD" ke daftar definisi Anda, game akan memanggil HMSGameServiceProvider. Dengan cara ini kami dapat mengelola utas kami dalam satu kode.



Anda dapat menggunakan skrip di bawah ini untuk mengelola definisi sebelum membuat. Setelah Anda mengubah dan menyimpan DefineKeywords, IDE akan memperbarui aliran kode sesuai dengan kata kunci yang Anda tentukan.



public class ManageDefines : Editor
 {
     /// <summary>
     /// Symbols that will be added to the editor
     /// </summary>
     public static readonly string [] DefineKeywords = new string[] {
        //"TEST_VERSION",
        "HMS_BUILD",
        //"GMS_BUILD",
     };
  
     /// <summary>
     /// Add define symbols as soon as Unity gets done compiling.
     /// </summary>
     static AddDefineSymbols ()
     {
         List<string> allDefines = new List<string>();
         allDefines.AddRange ( DefineKeywords.Except ( allDefines ) );
         PlayerSettings.SetScriptingDefineSymbolsForGroup (
             EditorUserBuildSettings.selectedBuildTargetGroup,
             string.Join ( ";", allDefines.ToArray () ) );
     }
 }

      
      





2. Script sebelum dan sesudah build (pre-build dan post-build)



Jadi, seperti yang disebutkan sebelumnya, kita perlu mengubah nama paket game kita untuk versi Huawei AppGallery.



Namun, jika Anda menggunakan layanan Google Play pada saat yang sama, semua konfigurasi akan dikaitkan dengan nama paket Anda yang sudah ada dan mengubahnya akan memengaruhi konfigurasi. Selain itu, editor Unity di jendela pop-up akan memperingatkan Anda dari waktu ke waktu untuk memperbaiki nama paket aplikasi, karena sekarang nama paket dan konfigurasi layanan seluler berbeda. Menutup popup ini berulang kali sangat membosankan.



Untuk mengatasi masalah ini dan mengelola dua nama paket yang berbeda pada saat yang sama, solusi dapat digunakan dengan skrip pra-bangun dan pasca-bangun dengan definisi.



Lihatlah kode ini:



class MyCustomBuildProcessor : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
    public int callbackOrder { get { return 0; } }

    public void OnPostprocessBuild(BuildReport report)
    {
        PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, "your.package.name");
    }

    public void OnPreprocessBuild(BuildReport report)
    {
        #if HMS_BUILD
            PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, "your.package.name.huawei");
        #elif GMS_BUILD
            PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, "your.package.name");
        #endif
    }
}

      
      





Seperti yang Anda lihat, semuanya sederhana. Dengan bantuan definisi, kita dapat mengubah nama paket selama pra-pembuatan untuk HMS_BUILD saja. Kemudian, setelah membangun, Anda dapat mengembalikan nama paket ke yang asli, dan kemudian Unity tidak akan lagi memperingatkan kami tentang ketidakcocokan nama paket.



Itu saja. Kami sekarang siap untuk mengembangkan game dalam satu kode untuk Huawei dan Google Play secara bersamaan.





Contoh pengembangan aplikasi



Mari buat aplikasi dalam basis kode yang sama untuk Android dan Huawei, yang mencakup layanan game, pembelian dalam game, dan periklanan.



Kami tidak akan menerapkan semua fungsionalitas untuk setiap layanan karena ini hanya demo. Anda dapat mengembangkan sendiri setiap fitur dan fungsionalitas.





Struktur modul layanan





gambar

Gambar 2. Skema operasi modul layanan



Untuk setiap layanan kami akan memiliki layanan kami sendiri;



  • Manajer : Kelas ini menyertakan logika permainan untuk layanan dan mengelola fungsionalitas umum. Game yang berbeda mungkin perlu mengubah kelas ini agar sesuai dengan kebutuhan Anda.
  • Kelas pabrik (Pabrik) : Kelas ini menyertakan logika untuk memilih penyedia. Dalam pendekatan kami, kami akan menggunakan definisi, tetapi Anda dapat mengubah mekanisme pemilihan penyedia sesuai keinginan Anda.
  • Penyedia : untuk setiap layanan, kita perlu membuat penyedia sendiri. Semua ketergantungan antara proyek Anda dan layanan seluler harus tetap berada dalam kelas ini.
  • Antarmuka Penyedia : untuk menyatukan penggunaan berbagai layanan seluler, kami membutuhkan penyedia umum, dan untuk tujuan ini, antarmuka penyedia dibuat. Sesuai persyaratan game Anda, Anda perlu menentukan semua metode yang akan Anda gunakan dalam game dari layanan seluler.


Jika perlu, Anda juga dapat mengaktifkan:



  • Entitas umum : Anda mungkin memerlukan entitas umum untuk mengabstraksi beberapa layanan dari game Anda. Untuk mempertahankan ketergantungan hanya pada kelas penyedia, Anda dapat menggunakan entitas generik sesuai kebutuhan Anda.
  • Listener generik : Mirip dengan entitas generik, jika Anda menginginkan listener generik, Anda juga dapat membuatnya.


gambar

Gambar 3. Contoh struktur untuk modul layanan game



Sekarang mari kita lihat contoh dan mencoba memahami apa yang dapat kita lakukan dengan metode yang dijelaskan dalam artikel.



Untuk mengabstraksi layanan seluler dari logika game, kami akan menggunakan manajer. Manajer berkomunikasi dengan penyedia melalui kain. Dengan cara ini kita dapat menggunakan penyedia seperti plugin. Mereka perlu mengimplementasikan antarmuka umum yang berisi metode yang ingin kita akses.



public interface IGameServiceProvider
{
    void Init();
    bool IsAuthenticated();
    void SignOut();
    void AuthenticateUser(Action<bool> callback = null);
    void SendScore(int score, string boardId);
    void ShowLeaderBoard(string boardId = "");
    void ShowAchievements();
    void UnlockAchievement(string key);
    CommonAuthUser GetUserInfo();
}

      
      





Maka kita membutuhkan setidaknya satu penyedia yang mengimplementasikan antarmuka layanan. Seperti yang disebutkan sebelumnya, semua ketergantungan antara game dan layanan seluler pihak ketiga harus tetap berada dalam kelas ini. Mari buat dua penyedia: untuk Huawei dan Google Play.



Berikut beberapa contoh kode. Anda dapat menemukannya dalam proyek di GitHub di akhir artikel.





Penyedia Layanan Game Huawei



public class HMSGameServiceProvider : IGameServiceProvider
 {
      private static string TAG = "HMSGameServiceProvider";

      private HuaweiIdAuthService _authService;
      private IRankingsClient _rankingClient;
      private IAchievementsClient _achievementClient;

      public AuthHuaweiId HuaweiId;

      public CommonAuthUser commonAuthUser = null;

      public void Init()
      {
          InitHuaweiAuthService();
      }

      ....
        
}
      
      







Penyedia Layanan Google Game



public class GooglePlayGameServiceProvider : IGameServiceProvider
{
    private static string TAG = "GooglePlayServiceProvider";

    private PlayGamesPlatform _platform;

    public CommonAuthUser commonAuthUser = null;

    public void Init()
    {
        InitPlayGamesPlatform();
    }

    ....
}

      
      





Sekarang kita perlu membuat manajer dan kelas pabrik. Kemudian kami mendapatkan penyedia sesuai dengan definisi kami.



public class GameServiceManager : Singleton<GameServiceManager>
{
        public IGameServiceProvider provider;

        protected override void Awake()
        {
            base.Awake();
            provider = GameServiceFactory.CreateGameServiceProvider();
        }
        
        .....
        
}

      
      





Seperti inilah tampilan kelas pabrik kami:



internal static class GameServiceFactory
{
    public static IGameServiceProvider CreateGameServiceProvider()
    {
        #if HMS_BUILD
            return new HMSGameServiceProvider();
        #else
            return new GooglePlayGameServiceProvider();                        
        #endif
    }
}

      
      





Itu saja: kami sekarang memiliki kelas GameManager yang dapat mengelola fungsionalitas layanan game multi-penyedia.



Untuk menginisialisasi GameServices, gunakan baris kode berikut jika sesuai:



public class MainSceneManager : MonoBehaviour
{
    void Start()
    {
        GameServiceManager.Instance.Init();
        
        ....
        
    }
    
    ....
    
    private void OnClickedScoreBoardButton()
    {
        GameServiceManager.Instance.provider.ShowLeaderBoard();
    }

    private void OnClickedAchievementButton()
    {
        GameServiceManager.Instance.provider.ShowAchievements();
    }
    
    ....
}


      
      





Kita tidak akan membahas setiap modul layanan, karena semuanya memiliki logika dan struktur yang sama. Anda dapat melihatnya beraksi dengan menyalin kode dari proyek ke GitHub.



Selain itu, jika Anda memerlukan panduan tentang cara menyiapkan plugin Huawei di Unity, ini dijelaskan dalam posting ini .



Mari beralih ke kesimpulan.



Dengan mengubah definisi antara HMS_BUILD dan GMS_BUILD di DefineConfig.cs:



  1. kita bisa mendapatkan dua APK atau paket berbeda untuk Huawei AppGallery dan Google Play;
  2. antara HMS dan GMS, fungsi Masuk & Keluar, papan peringkat, pencapaian, pembelian dalam game berubah.


Di bawah ini adalah video pendek dari kedua majelis.



Dalam kasus "HMS_BUILD":



gambar



Dalam kasus "GMS_BUILD":



gambar



Proyek demo dan APK yang disiapkan untuk HMS dan GMS dapat ditemukan di tautan di GitHub .



All Articles