我正在使用Unity构建应在电话和平板电脑上运行的应用程序。根据应用程序是在电话上还是在平板电脑上运行,UI的布局应有所不同(即某些UI元素的RectTransform
应该具有不同的值)。最后,我将提出一种逻辑来检测应用程序的启动情况,然后触发相应保存的布局配置的应用程序。我想避免构建两个不同版本的应用程序。
到目前为止,我的想法是:
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
: [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
中UI元素的LayoutConfiguration
的引用始终为 Missing 。
问题:
我的想法在概念上可行吗?
我该如何工作?