Я создаю приложение с использованием Unity, которое должно работать на телефоне и планшете. Пользовательский интерфейс должен быть размещен по-разному (т. Е. RectTransform
некоторых элементов пользовательского интерфейса должны иметь разные значения) в зависимости от того, работает ли приложение на телефоне или планшете. В конце я добавлю логику, чтобы определить при запуске приложения, в каком случае это происходит, и, следовательно, запустить приложение соответствующих сохраненных конфигураций макета. Я хочу избежать создания двух разных версий приложения.
Моя идея пока что :
- A
LayoutController
глобально контролирует сохранение и загрузку различных макетов:
using UnityEngine;
public class LayoutController : MonoBehaviour
{
public static LayoutController instance;
public LayoutConfigurationDatabase layoutConfigurationDatabase;
public string currentLayoutName = "Default";
private void Awake()
{
instance = this;
}
public void Load(string layoutName)
{
var objects = FindObjectsOfType<LayoutHelper>();
foreach(var o in objects)
{
o.currentLayoutName = layoutName;
layoutConfigurationDatabase.Get((RectTransform)o.transform, currentLayoutName);
}
}
public void SaveAll()
{
var objects = FindObjectsOfType<LayoutHelper>();
foreach (var o in objects)
{
layoutConfigurationDatabase.Put((RectTransform) o.transform, currentLayoutName);
}
}
}
- Объект сценария
LayoutConfigurationData
сохраняет LayoutConfiguration
s для всех соответствующих элементов:
[Serializable]
public class LayoutConfiguration
{
public string layoutName;
public RectTransform transform;
public Dictionary<string, object> data = new Dictionary<string, object>();
}
[CreateAssetMenu(fileName = "LayoutConfigurationDatabase", menuName = "Data/LayoutConfigurationDatabase")]
public class LayoutConfigurationDatabase : ScriptableObject
{
public List<LayoutConfiguration> data = new List<LayoutConfiguration>();
public bool Put(RectTransform from, string layoutName)
{
var item = data.Find(i => i.transform == from && i.layoutName == layoutName);
if(item != null)
{
data.Remove(item);
}
LayoutConfiguration configuration = new LayoutConfiguration() { transform = from, layoutName = layoutName };
var type = from.GetType();
PropertyInfo[] fields = from.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var field in fields)
{
try
{
var value = field.GetValue(from, null);
configuration.data[field.Name] = value;
}
catch(Exception){ }
}
data.Add(configuration);
return true;
}
public bool Get(RectTransform to, string layoutName)
{
var configuration = data.Find(i => i.transform == to && i.layoutName == layoutName);
if(configuration == null)
{
Debug.Log("Cannot find configuration");
return false;
}
PropertyInfo[] fields = to.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var field in fields)
{
if (configuration.data.ContainsKey(field.Name) && field.CanWrite && field.Name.ToLower() != "parent")
field.SetValue(to, configuration.data[field.Name], null);
}
return true;
}
}
- Каждый элемент, который должен вести себя по-разному, получает компонент
LayoutHelper
:
using UnityEngine;
public class LayoutHelper : MonoBehaviour
{
public string currentLayoutName;
[HideInInspector]
public string status = "";
public void Save()
{
LayoutController.instance.layoutConfigurationDatabase.Put((RectTransform)transform, currentLayoutName);
status = string.Format("Saved layout name {0}", currentLayoutName);
}
public void Load()
{
if (!LayoutController.instance.layoutConfigurationDatabase.Get((RectTransform) transform, currentLayoutName))
{
status = string.Format("Cannot load orientation {0}!", currentLayoutName);
}
}
public void Set(string layoutName)
{
this.currentLayoutName = layoutName;
Load();
}
}
Проблема :
Это работает только до тех пор, пока я не изменю сцену. После изменения сцены ссылка на RectTransform
элемента пользовательского интерфейса в LayoutConfiguration
s всегда равна Missing .
Вопросы :
Возможна ли моя идея концептуально?
Как я могу сделать эту работу?