Hanya tentang pengaturan internal dan eksternal untuk aplikasi di Unity3D

Pendahuluan


Halo para pembaca, dalam artikel hari ini saya ingin berbicara tentang pengaturan dan konfigurasi aplikasi game yang dibuat di lingkungan Unity3d.

Secara tradisi, saya akan mulai dengan latar belakang. Saat bekerja di industri game, saya mengembangkan berbagai proyek dengan berbagai kompleksitas dan mengunjungi kamp desain game dan kamp programmer (di mana saya sampai hari ini). Bukan rahasia lagi bahwa aplikasi apa pun membutuhkan sejumlah besar data konfigurasi dan pengaturan yang berbeda. Dalam bentuk klasik, relatif Unity3d, pengaturan seperti itu ditempatkan di bagian inspektur yang terlihat, di mana beberapa angka dimasukkan, dll. Saya pikir itu tidak layak untuk berbicara tentang kenyamanan pendekatan ini, itu bahkan jika dikecualikan, fakta bahwa pada saat penyetelan, adegan di mana kelas MonoBehaviour berada diblokir untuk perubahan oleh pengembang lain. Oleh karena itu, setelah serangkaian berbagai macam cobaan di masa lalu, saya memutuskan untuk menulis sesuatu yang sederhana dan efektif yang akan membuat hidup lebih mudah bagi semua orang dan menyederhanakan bekerja dengan data seperti itu, yang ingin saya bagikan dengan Anda.

Catatan : semua kode yang dijelaskan di bawah ini berlaku untuk versi Unity 2018.3+ dan menggunakan kompiler Roslyn (versi bahasa C # 7+).

Pengaturan internal


Untuk memulai, pertimbangkan pengaturan internal proyek, yang mencakup berbagai konstanta, tautan, pengidentifikasi SDK eksternal, kunci, dll. hal-hal termasuk pengaturan gameplay global dan lokal. Secara umum, semua data tersebut dapat dibagi menjadi empat jenis:

  • Tali
  • Int
  • Mengapung
  • Bool

Semua data lain dapat dengan mudah disimpan di dalamnya, dan dengan mempertimbangkan string, Anda dapat menyimpan apa saja menggunakan serialisasi JSON. Kami akan menggunakan ScriptableObject sebagai dasar, yang cocok untuk menyelesaikan tugas ini tidak seperti orang lain.

public class Setting : ScriptableObject { public enum ParameterTypeEnum { Float, Int, String, Bool } [Serializable] public class ParameterData { public string Name => _name; public ParameterTypeEnum ParameterType => _parameterType; public string DefaultValue => _defaultValue; [SerializeField] private string _name; [SerializeField] private ParameterTypeEnum _parameterType; [SerializeField] private string _defaultValue; } [SerializeField] protected ParameterData[] Parameters; } 

Jadi, dalam database, kami memiliki array nilai yang:

  • Nama parameter
  • Tipe Parameter
  • Nilai Parameter sebagai String

Catatan : mengapa garis? Sepertinya saya lebih nyaman daripada menyimpan 4 variabel dari jenis yang berbeda.

Untuk digunakan dalam kode, kami menambahkan metode bantu dan kamus yang akan menyimpan nilai yang dikonversi dalam bentuk kotak.
 protected readonly IDictionary<string, object> settingParameters = new Dictionary<string, object>(); [NonSerialized] protected bool initialized; private void OnEnable() { #if UNITY_EDITOR if (EditorApplication.isPlayingOrWillChangePlaymode) { Initialization(); } #else Initialization(); #endif } public virtual T GetParameterValue<T>(string name) { if (settingParameters.ContainsKey(name)) { var parameterValue = (T)settingParameters[name]; return parameterValue; } else { Debug.Log("[Setting]: name not found [{0}]".Fmt(name)); } return default; } protected virtual void Initialization() { if (initialized || Parameters == null) return; for (var i = 0; i < Parameters.Length; i++) { var parameter = Parameters[i]; object parameterValue = null; switch (parameter.ParameterType) { case ParameterTypeEnum.Float: { if (!float.TryParse(parameter.DefaultValue, out float value)) { value = default; } parameterValue = GetValue(parameter.Name, value); } break; case ParameterTypeEnum.Int: { if (!int.TryParse(parameter.DefaultValue, out int value)) { value = default; } parameterValue = GetValue(parameter.Name, value); } break; case ParameterTypeEnum.String: { parameterValue = GetValue(parameter.Name, parameter.DefaultValue); } break; case ParameterTypeEnum.Bool: { if (!bool.TryParse(parameter.DefaultValue, out bool value)) { value = default; } parameterValue = GetValue(parameter.Name, value); } break; } settingParameters.Add(parameter.Name, parameterValue); } initialized = true; } protected virtual object GetValue<T>(string paramName, T defaultValue) { return defaultValue; } 


Inisialisasi dilakukan di OnEnable . Kenapa tidak bangun ? Metode ini tidak dipanggil untuk instance yang disimpan sebagai aset (itu disebut pada saat CreateInstance , yang tidak kita butuhkan). Ketika aplikasi untuk aset diluncurkan, ScriptableObject disebut pertama, OnDisable (hanya dalam editor), kemudian OnEnable . Juga, sehingga dalam editor selama setiap kompilasi dan pembukaan inisialisasi proyek tidak berfungsi, Anda perlu menambahkan arahan precompilation, dan menyisipkan di awal file:
 #if UNITY_EDITOR using UnityEditor; #endif 

Kami akan membutuhkan metode GetValue lebih lanjut, dan untuk pengaturan internal, itu hanya mengembalikan nilai default.

Metode GetParameterValue adalah metode utama kami untuk mengakses parameter. Perlu dipertimbangkan bahwa meskipun nilai unboxing, parameter yang disimpan dalam Pengaturan dalam beberapa cara konstanta, sehingga harus diambil ketika menginisialisasi adegan. Jangan panggil metode dalam Pembaruan .

Contoh penggunaan:

 public class MyLogic : MonoBehaviour { [SerializeField] private Setting _localSetting; private string _localStrValue; private int _localIntValue; private float _localFloatValue; private bool _localBoolValue; private void Start() { _localStrValue = _localSetting.GetParameterValue<string>("MyStr"); _localIntValue = _localSetting.GetParameterValue<int>("MyInt"); _localFloatValue = _localSetting.GetParameterValue<float>("MyFloat"); _localBoolValue = _localSetting.GetParameterValue<bool>("MyBool"); } } 

Kami menulis yayasan dan sekarang kami membutuhkan editor, karena tujuan utama bagi kami hanyalah kenyamanan bagi mereka yang bekerja dengan pengaturan ini.

Untuk menambahkan item menu agar dapat membuat aset, Anda dapat menggunakan atribut:

 CreateAssetMenu(fileName = "New Setting", menuName = "Setting") 

Sekarang kami akan menulis inspektur khusus yang akan memungkinkan Anda untuk menampilkan data pada aset dan meluncurkan editor eksternal.
 [CustomEditor(typeof(Setting), true)] public class SettingCustomInspector : Editor { private GUIStyle _paramsStyle; private GUIStyle _paramInfoStyle; private const string _parameterInfo = "<color=white>Name</color><color=grey> = </color><color=yellow>{0}</color> <color=white>Type</color><color=grey> = </color><color=yellow>{1}</color> <color=white>Defualt Value</color><color=grey> = </color><color=yellow>{2}</color>"; public override void OnInspectorGUI() { if (GUILayout.Button("Edit Setting")) { SettingEditorWindow.Show(serializedObject.targetObject as Setting); } EditorGUILayout.LabelField("Parameters:", _parametersStyle, GUILayout.ExpandWidth(true)); var paramsProp = serializedObject.FindProperty("Parameters"); for (var i = 0; i < paramsProp.arraySize; i++) { var paramProp = paramsProp.GetArrayElementAtIndex(i); var paramNameProp = paramProp.FindPropertyRelative("_name"); var paramTypeProp = paramProp.FindPropertyRelative("_parameterType"); var paramDefaultValueProp = paramProp.FindPropertyRelative("_defaultValue"); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(_paramInfo.Fmt( paramNameProp.stringValue, paramTypeProp.enumDisplayNames[paramTypeProp.enumValueIndex], paramDefaultValueProp.stringValue), _paramInfoStyle); EditorGUILayout.EndHorizontal(); } } private void PrepareGUIStyle() { if (_parametersStyle == null) { _paramsStyle = new GUIStyle(GUI.skin.label); _paramsStyle.fontStyle = FontStyle.Bold; _paramsStyle.fontSize = 12; _paramsStyle.normal.textColor = Color.green; _paramInfoStyle = new GUIStyle(GUI.skin.label); _paramInfoStyle.richText = true; } } } 


Beginilah tampilannya:

gambar

Sekarang kita memerlukan editor parameter itu sendiri dan nilainya, untuk ini kita menggunakan jendela khusus.
 public class SettingEditorWindow : EditorWindow { public Setting SelectedAsset; private int _currentSelectedAsset = -1; private readonly List<string> _assetNames = new List<string>(); private readonly IList<SerializedObject> _settingSerializationObjects = new List<SerializedObject>(); private readonly IList<T> _assets = new List<T>(); private readonly IList<int> _editedNames = new List<int>();; private GUIContent _editNameIconContent; private GUIStyle _headerStyle; private GUIStyle _parametersStyle; private GUIStyle _parameterHeaderStyle; private GUIStyle _nameStyle; private Vector2 _scrollInspectorPosition = Vector2.zero; private Vector2 _scrollAssetsPosition = Vector2.zero; private const string _SELECTED_ASSET_STR = "SettingSelected"; public static void Show(Setting asset) { var instance = GetWindow<Setting>(true); instance.title = new GUIContent("Settings Editor", string.Empty); instance.SelectedAsset = asset; } private void OnEnable() { var assetGuids = AssetDatabase.FindAssets("t:{0}".Fmt(typeof(Setting).Name)); foreach (var guid in assetGuids) { var path = AssetDatabase.GUIDToAssetPath(guid); var asset = AssetDatabase.LoadAssetAtPath<T>(path); _assetNames.Add(path.Replace("Assets/", "").Replace(".asset", "")); _assets.Add(asset); _settingSerializationObjects.Add(new SerializedObject(asset)); } _currentSelectedAsset = PlayerPrefs.GetInt(_SELECTED_ASSET_STR, -1); _editNameIconContent = new GUIContent(EditorGUIUtility.IconContent("editicon.sml")); } private void OnDisable() { PlayerPrefs.SetInt(_SELECTED_ASSET_STR, _currentSelectedAsset); } private void PrepareGUIStyle() { if (_headerStyle == null) { _headerStyle = new GUIStyle(GUI.skin.box); _headerStyle.fontStyle = FontStyle.Bold; _headerStyle.fontSize = 14; _headerStyle.normal.textColor = Color.white; _headerStyle.alignment = TextAnchor.MiddleCenter; _parametersStyle = new GUIStyle(GUI.skin.label); _parametersStyle.fontStyle = FontStyle.Bold; _parametersStyle.fontSize = 12; _parametersStyle.normal.textColor = Color.green; } } private void OnGUI() { PrepareGUIStyle(); if (SelectedAsset != null) { _currentSelectedAsset = _assets.IndexOf(SelectedAsset); SelectedAsset = null; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginVertical(GUI.skin.box, GUILayout.MinWidth(350f), GUILayout.ExpandHeight(true)); _scrollAssetsPosition = EditorGUILayout.BeginScrollView(_scrollAssetsPosition, GUIStyle.none, GUI.skin.verticalScrollbar); _currentSelectedAsset = GUILayout.SelectionGrid(_currentSelectedAsset, _assetNames.ToArray(), 1); EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true)); var assetSerializedObject = (_currentSelectedAsset >= 0) ? _settingSerializationObjects[_currentSelectedAsset] : null; EditorGUILayout.Space(); EditorGUILayout.LabelField((_currentSelectedAsset >= 0) ? _assetNames[_currentSelectedAsset] : "Select Asset...", _headerStyle, GUILayout.ExpandWidth(true)); EditorGUILayout.Space(); _scrollInspectorPosition = EditorGUILayout.BeginScrollView(_scrollInspectorPosition, GUIStyle.none, GUI.skin.verticalScrollbar); Draw(assetSerializedObject); EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); assetSerializedObject?.ApplyModifiedProperties(); } private void Draw(SerializedObject assetSerializationObject) { if (assetSerializationObject == null) return; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Parameters:", _parametersStyle, GUILayout.Width(20f), GUILayout.ExpandWidth(true)); var parametersProperty = assetSerializationObject.FindProperty("Parameters"); if (GUILayout.Button("Add", GUILayout.MaxWidth(40f))) { if (parametersProperty != null) { parametersProperty.InsertArrayElementAtIndex(parametersProperty.arraySize); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (parametersProperty != null) { for (var i = 0; i < parametersProperty.arraySize; i++) { var parameterProperty = parametersProperty.GetArrayElementAtIndex(i); var parameterNameProperty = parameterProperty.FindPropertyRelative("_name"); var parameterTypeProperty = parameterProperty.FindPropertyRelative("_parameterType"); var parameterDefaultValueProperty = parameterProperty.FindPropertyRelative("_defaultValue"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(_editNameIconContent, GUILayout.MaxWidth(25f), GUILayout.MaxHeight(18f))) { if (_editedNames.Contains(i)) { _editedNames.Remove(i); } else { _editedNames.Add(i); } } EditorGUILayout.LabelField("Name", _parameterHeaderStyle, GUILayout.MaxWidth(40f)); if (_editedNames.Contains(i)) { parameterNameProperty.stringValue = EditorGUILayout.TextField(parameterNameProperty.stringValue, GUILayout.Width(175f)); var ev = Event.current; if (ev.type == EventType.MouseDown || ev.type == EventType.Ignore || (ev.type == EventType.KeyDown && ev.keyCode == KeyCode.Return)) { _editedNames.Remove(i); } } else { EditorGUILayout.LabelField(parameterNameProperty.stringValue, _nameStyle, GUILayout.Width(175f)); } EditorGUILayout.LabelField("Type", _parameterHeaderStyle, GUILayout.MaxWidth(40f)); parameterTypeProperty.enumValueIndex = EditorGUILayout.Popup(parameterTypeProperty.enumValueIndex, parameterTypeProperty.enumDisplayNames, GUILayout.Width(75f)); GUILayout.Space(20f); EditorGUILayout.LabelField("DefaultValue", _parameterHeaderStyle, GUILayout.Width(85f)); switch (parameterTypeProperty.enumValueIndex) { case 0: { if (!float.TryParse(parameterDefaultValueProperty.stringValue, out float value)) { value = default; } value = EditorGUILayout.FloatField(value, GUILayout.ExpandWidth(true)); parameterDefaultValueProperty.stringValue = value.ToString(); } break; case 1: { if (!int.TryParse(parameterDefaultValueProperty.stringValue, out int value)) { value = default; } value = EditorGUILayout.IntField(value, GUILayout.ExpandWidth(true)); parameterDefaultValueProperty.stringValue = value.ToString(); } break; case 2: parameterDefaultValueProperty.stringValue = EditorGUILayout.TextField(parameterDefaultValueProperty.stringValue, GUILayout.ExpandWidth(true)); break; case 3: { if (!bool.TryParse(parameterDefaultValueProperty.stringValue, out bool value)) { value = default; } value = EditorGUILayout.Toggle(value, GUILayout.ExpandWidth(true)); parameterDefaultValueProperty.stringValue = value.ToString(); } break; } if (GUILayout.Button("-", GUILayout.MaxWidth(25f), GUILayout.MaxHeight(18f))) { if (_editedNames.Contains(i)) { _editedNames.Remove(i); } parametersProperty.DeleteArrayElementAtIndex(i); } EditorGUILayout.EndHorizontal(); } } } } 


Saya tidak akan menjelaskan banyak kode, semuanya sederhana di sini. Saya hanya mencatat bahwa editor memungkinkan Anda untuk mengedit secara opsional semua aset jenis Pengaturan . Untuk melakukan ini, ketika membuka jendela, kita menemukannya di proyek menggunakan metode AssetDatabase.FindAssets ("t: {0}". Fmt (typeof (Setting) .Name)) . Dan juga mengedit nama parameter dilakukan melalui tombol untuk mengecualikan perubahan yang tidak disengaja.

Seperti inilah bentuk editor:

gambar

Kami memeriksa pengaturan yang digunakan di dalam aplikasi, sekarang kami akan mempertimbangkan kasus yang lebih spesifik.

Pengaturan eksternal


Bayangkan sebuah situasi yang dalam game yang sudah berjalan, kami tiba-tiba perlu mengubah nilai-nilai tertentu untuk menyesuaikan gameplay. Dalam versi primitif, kami mengubahnya di build, mengakumulasikan perubahan tersebut, membuat pembaruan dan mengirimkannya ke toko, setelah itu kami menunggu konfirmasi, dll. Tetapi bagaimana dengan mereka yang tidak memperbarui aplikasi? Dan bagaimana jika perubahan perlu dilakukan segera? Untuk mengatasi masalah ini, ada mekanisme seperti Remote Settings . Ini bukan penemuan baru dan digunakan di banyak SDK pihak ketiga untuk analitik, dll., Misalnya - itu ada di Firebase , di GameAnalytics , serta di Unity Analytics . Yang terakhir inilah yang akan kita gunakan.

Catatan : secara umum, tidak ada perbedaan antara semua sistem ini, mereka serupa dan menggunakan prinsip yang sama.

Mari kita bahas Remote Settings di Unity Analytics dan apa yang bisa dilakukan.

Agar fungsi ini tersedia di proyek, Anda harus mengaktifkan analitik di proyek pada tab Layanan .

gambar

Setelah itu, Anda perlu masuk ke akun Unity3d Anda dan menemukan proyek Anda di sana dan ikuti tautan ke bagian analitik, di mana di sebelah kiri dalam menu pilih Remote Settings .

gambar

Semua pengaturan dibagi menjadi yang digunakan dalam mode pengembangan dan yang akan digunakan dalam aplikasi yang sudah dirilis.

gambar

Untuk menambahkan parameter, pilih item yang sesuai dan masukkan nama, jenis dan nilai parameter.

gambar

Setelah kami menambahkan semua parameter yang diperlukan, kami membutuhkan dukungan dalam kode untuk bekerja dengannya.

Catatan : Tombol Sync menyinkronkan pengaturan dengan aplikasi. Proses ini tidak terjadi secara instan, namun, pada saat parameter dalam aplikasi diperbarui, peristiwa terkait akan dipicu, kita akan membicarakannya nanti .

Untuk bekerja dengan Pengaturan Jarak Jauh, Anda tidak perlu SDK tambahan, cukup hidupkan analitik, seperti yang saya tulis di atas.

Kami akan menulis kelas untuk bekerja dengan pengaturan jarak jauh, untuk ini kami menggunakan kelas Pengaturan yang dijelaskan di atas sebagai basis.
 public sealed class RemoteSetting : Setting { public IList<string> GetUpdatedParameter() { var updatedParameters = new List<string>(); for (var i = 0; i < Parameters.Length; i++) { var parameter = Parameters[i]; switch (parameter.ParameterType) { case ParameterTypeEnum.Float: { var currentValue = Get<float>(parameter.Name); var newValue = RemoteSettings.GetFloat(parameter.Name, currentValue); if (currentValue != newValue) { settingParameters[parameter.Name] = newValue; updatedParameters.Add(parameter.Name); } } break; case ParameterTypeEnum.Int: { var currentValue = Get<int>(parameter.Name); var newValue = RemoteSettings.GetInt(parameter.Name, currentValue); if (currentValue != newValue) { settingParameters[parameter.Name] = newValue; updatedParameters.Add(parameter.Name); } } break; case ParameterTypeEnum.String: { var currentValue = Get<string>(parameter.Name); var newValue = RemoteSettings.GetString(parameter.Name, currentValue); if (string.Compare(currentValue, newValue, System.StringComparison.Ordinal) != 0) { settingParameters[parameter.Name] = newValue; updatedParameters.Add(parameter.Name); } } break; case ParameterTypeEnum.Bool: { var currentValue = Get<bool>(parameter.Name); var newValue = RemoteSettings.GetBool(parameter.Name, currentValue); if (currentValue != newValue) { settingParameters[parameter.Name] = newValue; updatedParameters.Add(parameter.Name); } } break; } } return updatedParameters; } protected override object GetValue<T>(string paramName, T defaultValue) { switch(defaultValue) { case float f: return RemoteSettings.GetFloat(paramName, f); case int i: return RemoteSettings.GetInt(paramName, i); case string s: return RemoteSettings.GetString(paramName, s); case bool b: return RemoteSettings.GetBool(paramName, b); default: return default; } } } 


Seperti yang Anda lihat, kami mendefinisikan ulang metode GetValue dan menambahkan metode baru yang memungkinkan Anda untuk mendapatkan daftar parameter yang diubah, kami akan membutuhkannya nanti.

Di atas, kami menulis contoh menggunakan Pengaturan dalam kode, itu cukup sederhana, tetapi tidak memperhitungkan keberadaan pengaturan jarak jauh, oleh karena itu, untuk menyatukan akses ke semua pengaturan dalam satu tombol, kami akan menulis manajer yang akan membantu dalam hal ini.

Kode Pengaturan Manajer
 public class SettingsManager : MonoBehaviourSingleton<SettingsManager> { public Setting this[string index] => GetSetting(index); [SerializeField] private Setting[] _settings; private readonly IDictionary<string, Setting> _settingsByName = new Dictionary<string, Setting>(); public void ForceUpdate() { RemoteSettings.ForceUpdate(); } private void Start() { foreach(var setting in _settings) { _settingsByName.Add(setting.name, setting); } RemoteSettings.BeforeFetchFromServer += OnRemoteSettingBeforeUpdate; RemoteSettings.Updated += OnRemoteSettingsUpdated; RemoteSettings.Completed += OnRemoteSettingCompleted; } private Setting GetSetting(string name) { if(_settingsByName.ContainsKey(name)) { return _settingsByName[name]; }else { Debug.LogWarningFormat("[SettingManager]: setting name [{0}] not found", name); return null; } } private void OnRemoteSettingBeforeUpdate() { RemoteSettingBeforeUpdate.Call(); } private void OnRemoteSettingsUpdated() { foreach (var setting in _settingsByName.Values) { if (setting is RemoteSetting) { var updatedParameter = remoteSetting.GetUpdatedParameter(); foreach (var parameterName in updatedParameter) { RemoteSettingUpdated.Call(parameterName); } } } } private void OnRemoteSettingCompleted(bool wasUpdatedFromServer, bool settingsChanged, int serverResponse) { RemoteSettingsCompleted.Call(wasUpdatedFromServer, settingsChanged, serverResponse); } private void OnDestroy() { RemoteSettings.BeforeFetchFromServer -= OnRemoteSettingBeforeUpdate; RemoteSettings.Updated -= OnRemoteSettingsUpdated; RemoteSettings.Completed -= OnRemoteSettingCompleted; } } 


Manajer disajikan dalam bentuk sigleton yang hanya hidup di tempat kejadian. Ini dilakukan untuk kemudahan referensi dan agar mudah mengelola satu set parameter di setiap adegan (mengecualikan parameter yang tidak diperlukan oleh logika).

Seperti yang Anda lihat, RemoteSettings memiliki tiga acara:

  1. Acara dinaikkan sebelum nilai parameter diterima dari server jarak jauh
  2. Acara pembaruan parameter (dipanggil hanya dengan tombol Sinkronisasi, yang kami tulis sebelumnya), serta dalam kasus pembaruan parameter secara paksa melalui fungsi ForceUpdate
  3. Peristiwa dipicu ketika data tentang pengaturan jarak jauh diterima dari server. Kode respons server juga dikeluarkan di sini jika ada kesalahan.

Catatan : kode ini menggunakan sistem acara yang dibangun berdasarkan tipe data, lebih lanjut tentang itu ditulis dalam artikel saya yang lain .

Catatan : Anda perlu memahami cara kerja RemoteSettings. Pada awalnya, jika ada akses Internet, ia secara otomatis mengunduh data tentang parameter dan menyimpannya, jadi pada saat Anda memulai, jika tidak ada Internet, data akan diambil dari cache. Pengecualian adalah situasi ketika aplikasi awalnya diluncurkan dengan akses ke jaringan dimatikan, dalam hal ini, fungsi untuk mendapatkan nilai parameter akan mengembalikan nilai default. Dalam kasus kami, ini adalah yang kami masukkan di editor.

Sekarang mari kita ubah contoh menggunakan pengaturan dari kode, dengan mempertimbangkan hal di atas.

 public class MyLogic : MonoBehaviour { private const string INGAME_PARAMETERS = "IngamgeParameters"; private const string REMOTE_RAPAMETERS = "RemoteParamteters"; private string _localStrValue; private int _localIntValue; private float _localFloatValue; private bool _localBoolValue; private string _remoteStrValue; private int _remoteIntValue; private float _remoteFloatValue; private bool _remoteBoolValue; private void Start() { var ingameParametes = SettingsManager.Instance[INGAME_PARAMETERS]; var remoteParametes = SettingsManager.Instance[REMOTE_RAPAMETERS]; _localStrValue = ingameParametes.GetParameterValue<string>("MyStr"); _localIntValue = ingameParametes.GetParameterValue<int>("MyInt"); _localFloatValue = ingameParametes.GetParameterValue<float>("MyFloat"); _localBoolValue = ingameParametes.GetParameterValue<bool>("MyBool"); _remoteStrValue = remoteParametes.GetParameterValue<string>("MyStr"); _remoteIntValue = remoteParametes.GetParameterValue<int>("MyInt"); _remoteFloatValue = remoteParametes.GetParameterValue<float>("MyFloat"); _remoteBoolValue = remoteParametes.GetParameterValue<bool>("MyBool"); } } 

Seperti yang Anda lihat, dari kode, tidak ada perbedaan dalam pekerjaan antara pengaturan internal dan eksternal, namun, jika perlu, jika logika mengharuskannya, Anda dapat berlangganan ke acara manajer yang terkait dengan pengaturan jarak jauh.

Catatan : jika Anda hanya memerlukan parameter jarak jauh, Anda dapat mengunduh plug-in khusus dari AssetStore , ini memungkinkan Anda untuk segera menggunakannya.

Kesimpulan


Pada artikel ini saya mencoba menunjukkan bagaimana Anda bisa mengkonfigurasi aplikasi yang ditulis dalam Unity3d menggunakan pengaturan internal dan yang jauh. Saya menggunakan pendekatan serupa dalam proyek saya, dan itu membuktikan keefektifannya. Kami bahkan berhasil menggunakan pengaturan jarak jauh kami untuk menerapkan sistem pengujian A / B kami . Selain itu, pengaturan ini banyak digunakan untuk menyimpan berbagai konstanta yang terkait dengan SDK, hal-hal server, serta pengaturan gameplay, dll. Perancang gim dapat membuat seperangkat parameter terlebih dahulu dan menjelaskan bagaimana, untuk apa, dan di mana mereka digunakan, sementara ia dapat menyesuaikan gameplay tanpa menghalangi adegan. Dan karena fakta bahwa kami menggunakan ScriptableObject dan menyimpan parameter seperti aset, mereka dapat dimuat melalui AssetBundle , yang semakin memperluas kemampuan kami.

Tautan yang ditentukan dalam artikel :

habr.com/en/post/282524
assetstore.unity.com/packages/add-ons/services/analytics/unity-analytics-remote-settings-89317

Source: https://habr.com/ru/post/id436634/


All Articles