项目为了支持热更,预制和脚本会分离。脚本都是运行时动态绑定在预制上的。脚本均继承至MonoBehaviour,势必要和Mono的状态联系在一起,如Awake,Start等。举个例子,某些复杂的界面中,比如有多分页的情况。对于隐藏的分页对象,绑定对应脚本后,并不会执行Awake脚本。由于,基本上Awake中,会获得该界面的控件并缓存。如下图:
public class UILoginPopup : MonoBehaviour{
UIInput inputName,
inputPassword;
public string userName
{
set { this.inputName.value = value; }
}
void Awake
{
inputName = transform.GetComponentAt<UIInput>("Back/Name");
inputPassword = transform.GetComponentAt<UIInput>("Back/Password");
}
从而,设置界面外观时错误,各控件值均为null。
于是,想了个方法。参考ngui addMissingCompont,修改绑定脚本过程如下:
static public T AddMissingComponent<T> (this GameObject go) where T : Component
{
#if UNITY_FLASH
object comp = go.GetComponent<T>();
#else
T comp = go.GetComponent<T>();
#endif
if (comp == null)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
RegisterUndo(go, "Add " + typeof(T));
#endif
comp = go.AddComponent<T>();
}
//**增加部分**
var childView = comp as IChildView;
if(childView!=null)
childView.Load();
#if UNITY_FLASH
return (T)comp;
#else
return comp;
#endif
}
接口IChildView定义如下:
interface IChildView
{
/// <summary>
/// 自动调用
/// </summary>
void Load();
}
从而界面脚本修改如下,在Load函数中获得了控件,不用闹心Awake不执行带来的问题了。
public class UILoginPopup : MonoBehaviour,IChildView{
UIInput inputName,
inputPassword;
public string userName
{
set { this.inputName.value = value; }
}
//修改部分
public void Load(){
inputName = transform.GetComponentAt<UIInput>("Back/Name");
inputPassword = transform.GetComponentAt<UIInput>("Back/Password");
}
void Awake(){
}