Présentation
Bonjour chers lecteurs, dans l'article d'aujourd'hui, je voudrais parler des paramètres et de la configuration des applications de jeu créées dans l'environnement Unity3d.
Par tradition, je vais commencer par le fond. Tout en travaillant dans l'industrie du jeu, j'ai développé divers projets avec une complexité variable et visité le camp de conception de jeux et le camp des programmeurs (où je suis à ce jour). Ce n'est un secret pour personne qu'une application nécessite un grand nombre de données de configuration et de paramètres différents. Dans le formulaire classique, relativement Unity3d, ces paramètres sont placés dans la partie visible de l'inspecteur, où certains chiffres sont entrés, etc. Je pense que cela ne vaut pas la peine de parler de la commodité de cette approche, c'est même si elle est exclue, le fait qu'au moment du réglage, la scène dans laquelle se trouve la classe
MonoBehaviour est bloquée pour les modifications par d'autres développeurs. Par conséquent, après une série d'épreuves diverses dans le passé, j'ai décidé d'écrire quelque chose de simple et efficace qui facilitera la vie de tout le monde et simplifiera le travail avec ces données, que je veux partager avec vous.
Remarque :
tout le code décrit ci-dessous s'applique à Unity version 2018.3+ et utilise le compilateur Roslyn (version en langage C # 7+).Paramètres internes
Pour commencer, considérez les paramètres internes du projet, qui incluent diverses constantes, liens, identificateurs de SDK externes, clés, etc. choses, y compris les paramètres de jeu mondiaux et locaux. En général, toutes ces données peuvent être divisées en quatre types:
Toutes les autres données peuvent y être facilement stockées, et en tenant compte de la chaîne, vous pouvez stocker n'importe quoi en utilisant la sérialisation JSON. Nous utiliserons
ScriptableObject comme base, ce qui convient pour résoudre cette tâche comme personne d'autre.
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; }
Donc, dans la base de données, nous avons un tableau de valeurs qui sont:
- Nom du paramètre
- Type de paramètre
- Valeurs des paramètres sous forme de chaîne
Remarque :
pourquoi les lignes? Cela m'a semblé plus pratique que de stocker 4 variables de types différents.Pour une utilisation dans le code, nous ajoutons des méthodes auxiliaires et un dictionnaire qui stockera les valeurs converties sous forme encadrée. 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; }
L'initialisation se fait dans
OnEnable . Pourquoi pas à
Awake ? Cette méthode n'est pas appelée pour les instances stockées en tant qu'actifs (elle est appelée au moment de
CreateInstance , dont nous n'avons pas besoin). Lorsque l'application pour les actifs est
lancée, le ScriptableObject est appelé d'abord,
OnDisable (dans l'éditeur uniquement), puis
OnEnable . De plus, pour que dans l'éditeur lors de chaque recompilation et ouverture de l'initialisation du projet ne fonctionne pas, vous devez ajouter des directives de précompilation et insérer au début du fichier:
#if UNITY_EDITOR using UnityEditor; #endif
Nous aurons besoin de la méthode
GetValue plus loin, et pour les paramètres internes, elle renvoie simplement la valeur par défaut.
La méthode
GetParameterValue est notre principale méthode d'accès aux paramètres. Il convient de noter que malgré le déballage des valeurs, les paramètres stockés dans
Setting sont en quelque sorte des constantes, ils doivent donc être pris lors de l'initialisation des scènes. N'appelez pas la méthode dans
Update .
Exemple d'utilisation:
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"); } }
Nous avons écrit la fondation et maintenant nous avons besoin d'un éditeur, car l'objectif principal pour nous était simplement la commodité pour ceux qui travaillent avec ces paramètres.
Pour ajouter un élément de menu afin de pouvoir créer un actif, vous pouvez utiliser l'attribut:
CreateAssetMenu(fileName = "New Setting", menuName = "Setting")
Nous allons maintenant écrire un inspecteur personnalisé qui vous permettra d'afficher des données sur l'élément et de lancer un éditeur externe. [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; } } }
Voici à quoi cela ressemblera:

Maintenant, nous avons besoin d'un éditeur des paramètres eux-mêmes et de leurs valeurs, pour cela nous utilisons une fenêtre personnalisée. 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(); } } } }
Je n'expliquerai pas beaucoup le code, tout est simple ici. Je note seulement que l'éditeur vous permet d'éditer éventuellement tous les actifs de type
Setting . Pour ce faire, lorsque nous ouvrons la fenêtre, nous les trouvons dans le projet à l'aide de la méthode
AssetDatabase.FindAssets ("t: {0}". Fmt (typeof (Setting) .Name)) . La modification du nom du paramètre se fait également via le bouton afin d'exclure sa modification accidentelle.
Voici à quoi ressemble l'éditeur:

Nous avons examiné les paramètres utilisés dans l'application, nous allons maintenant considérer un cas plus spécifique.
Paramètres externes
Imaginez une situation où dans un jeu déjà en cours, nous devions soudainement changer certaines valeurs afin d'ajuster le gameplay. Dans la version primitive, nous changeons cela dans la construction, accumulons ces modifications, faisons une mise à jour et l'envoyons aux magasins, après quoi nous attendons la confirmation, etc. Mais qu'en est-il de ceux qui ne mettent pas à jour l'application? Et si des changements devaient être apportés d'urgence? Pour résoudre ce problème, il existe un mécanisme tel que
Paramètres à distance . Ce n'est pas une nouvelle invention et est utilisé dans de nombreux SDK tiers pour l'analyse, etc., par exemple - c'est dans
Firebase , dans
GameAnalytics , ainsi que dans
Unity Analytics . C'est ce dernier que nous utiliserons.
Remarque :
en général, il n'y a pas de différence entre tous ces systèmes, ils sont similaires et utilisent les mêmes principes.Arrêtons-nous sur ce que sont les
paramètres distants dans
Unity Analytics et ce qu'ils peuvent faire.
Pour que cette fonctionnalité soit disponible dans le projet, vous devez activer l'analyse dans le projet sous l'onglet
Services .

Après cela, vous devez vous connecter à votre compte Unity3d et y trouver votre projet et suivre le lien vers la section analytique, où à gauche dans le menu, sélectionnez
Paramètres à distance .

Tous les paramètres sont divisés en ceux qui sont utilisés en mode développement et ceux qui seront utilisés dans une application déjà publiée.

Pour ajouter un paramètre, sélectionnez l'élément approprié et entrez le nom, le type et la valeur du paramètre.

Après avoir ajouté tous les paramètres nécessaires, nous avons besoin de support dans le code pour travailler avec eux.
Remarque : Le
bouton Sync synchronise les paramètres avec l'application. Ce processus ne se produit pas instantanément, cependant, au moment où les paramètres de l'application sont mis à jour, les événements correspondants seront déclenchés, nous en parlerons plus tard .
Pour travailler avec les
paramètres à distance, vous n'avez pas besoin de SDK supplémentaires, activez simplement l'analyse, comme je l'ai écrit ci-dessus.
Nous allons écrire une classe pour travailler avec des paramètres distants, pour cela nous utilisons la classe Setting décrite ci-dessus comme base. 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; } } }
Comme vous pouvez le voir, nous avons redéfini la méthode
GetValue et ajouté une nouvelle méthode qui vous permet d'obtenir une liste des paramètres modifiés, nous en aurons besoin plus tard.
Ci-dessus, nous avons écrit un exemple d'utilisation de
Setting dans le code, c'est assez simple, mais cela ne prend pas en compte la présence de paramètres distants, donc, pour unifier l'accès à tous les paramètres dans une seule clé, nous écrirons un gestionnaire qui vous aidera dans cela.
Code du gestionnaire de paramètres 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; } }
Le manager se présente sous la forme d'un sigleton qui ne vit que dans la scène. Cela a été fait pour faciliter la référence et pour gérer facilement un ensemble de paramètres dans chaque scène (exclure les paramètres qui ne sont pas requis par la logique).
Comme vous pouvez le voir,
RemoteSettings a trois événements:
- Événement déclenché avant que les valeurs des paramètres ne soient reçues du serveur distant
- Événement de mise à jour des paramètres (appelé simplement par le bouton Sync, dont nous avons parlé plus tôt), ainsi qu'en cas de mise à jour forcée des paramètres via la fonction ForceUpdate
- Événement déclenché lorsque des données sur les paramètres distants sont reçues du serveur. Le code de réponse du serveur est également émis ici en cas d'erreur.
Remarque : le
code utilise un système d'événements construit sur des types de données, plus à ce sujet est écrit dans un autre de mes articles .Remarque : vous
devez comprendre le fonctionnement de RemoteSettings. Au début, s'il y a un accès Internet, il télécharge automatiquement les données sur les paramètres et les met en cache, donc au prochain démarrage, s'il n'y a pas Internet, les données seront prises dans le cache. L'exception est la situation lorsque l'application est initialement lancée avec l'accès au réseau désactivé, dans ce cas, les fonctions d'obtention de la valeur du paramètre renverront la valeur par défaut. Dans notre cas, ce sont ceux que nous entrons dans l'éditeur.Modifions maintenant l'exemple d'utilisation des paramètres du code, en tenant compte de ce qui précède.
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"); } }
Comme vous pouvez le voir, d'après le code, il n'y a pas de différence de travail entre les paramètres internes et externes, cependant, si nécessaire, si la logique l'exige, vous pouvez vous abonner aux événements du gestionnaire liés aux paramètres distants.
Remarque :
si vous n'avez besoin que de paramètres distants, vous pouvez télécharger un plug-in spécial depuis AssetStore , il vous permet de travailler avec eux immédiatement.Conclusion
Dans cet article, j'ai essayé de montrer comment vous pouvez simplement configurer une application écrite en Unity3d à l'aide de paramètres internes et distants. J'utilise une approche similaire dans mes projets, et cela prouve son efficacité. Nous avons même réussi à utiliser nos paramètres à distance pour implémenter notre
système de test A / B. De plus, les paramètres sont largement utilisés pour stocker diverses constantes liées au SDK, aux éléments du serveur, ainsi qu'aux paramètres de jeu, etc. Le concepteur de jeu peut créer un ensemble de paramètres à l'avance et décrire comment, pour quoi et où ils sont utilisés, tout en personnalisant le gameplay sans bloquer la scène. Et du fait que nous avons utilisé
ScriptableObject et
stocké de tels paramètres en tant qu'actifs, ils peuvent être chargés via
AssetBundle , ce qui étend encore nos capacités.
Liens spécifiés dans l'article :
habr.com/en/post/282524assetstore.unity.com/packages/add-ons/services/analytics/unity-analytics-remote-settings-89317