今天要做一个多设备适配方案,发现在修改了Canvas Scaler的Reference Resolution后不会立即生效,RectTransfrom的大小不变。
感觉要等到Update后才执行,个人不喜欢这种控制流程。
在网上搜了半天也没发现有人问这个,因为我的某些UI要通过Rect Size来计算大小,可能比较变态吧。所以做一个笔记记录一下。
网上找到一个函数
private void OnRectTransformDimensionsChange()
{
Debug.Log("x==========>x:"+GetComponent<RectTransform>().rect);
}
加到UI Root节点脚本中,可以在大小发生变化的时候调用到。
经过测试。在实例化UI预设的时候就已经改变了好几次大小。
AssetBundle ab = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle;
GameObject uimainobj = (GameObject)UnityEngine.Object.Instantiate(ab.LoadAsset(ab.GetAllAssetNames()[0]));//这里输出了4 次
uimainobj.name = "UIMain";
Canvas c = uimainobj.GetComponent<Canvas>();
c.worldCamera = uiCamera; //这里输出了1次
Object.Instantiate输出了前4次。
worldCamera 赋值也会调用1次。
看了CanvasScaler.cs源码后,应该是Hander()函数重新计算了大小。
发现OnEnable函数也会调用Hander()函数,所以,我们只要禁用脚本然后打开让他调用一次就好了。
Debug.Log("x========1");
cScaler.enabled = false;
//不同的分辨率比率,显示不用的画布大小
w_h_rate = (float)Screen.width / Screen.height;
isPad = w_h_rate > pad_rate ? true : false;
if (isPad)
cScaler.referenceResolution = new Vector2(padUIWidth, padUIHeight);
else
cScaler.referenceResolution = new Vector2(defaultUIWidth, defaultUIHeight);
cScaler.enabled = true;
Debug.Log("x========2");
2133就是正常后的高度,看来可行。
附:CanvasScaler.cs 部分代码
protected override void OnEnable()
{
base.OnEnable();
this.m_Canvas = this.GetComponent<Canvas>();
this.Handle();
}
/// <summary>
/// <para>See MonoBehaviour.OnDisable.</para>
/// </summary>
protected override void OnDisable()
{
this.SetScaleFactor(1f);
this.SetReferencePixelsPerUnit(100f);
base.OnDisable();
}
/// <summary>
/// <para>Handles per-frame checking if the canvas scaling needs to be updated.</para>
/// </summary>
protected virtual void Update()
{
this.Handle();
}
/// <summary>
/// <para>Method that handles calculations of canvas scaling.</para>
/// </summary>
protected virtual void Handle()
{
if ((UnityEngine.Object) this.m_Canvas == (UnityEngine.Object) null || !this.m_Canvas.isRootCanvas)
return;
if (this.m_Canvas.renderMode == RenderMode.WorldSpace)
{
this.HandleWorldCanvas();
}
else
{
switch (this.m_UiScaleMode)
{
case CanvasScaler.ScaleMode.ConstantPixelSize:
this.HandleConstantPixelSize();
break;
case CanvasScaler.ScaleMode.ScaleWithScreenSize:
this.HandleScaleWithScreenSize();
break;
case CanvasScaler.ScaleMode.ConstantPhysicalSize:
this.HandleConstantPhysicalSize();
break;
}
}
}
/// <summary>
/// <para>Handles canvas scaling that scales with the screen size.</para>
/// </summary>
protected virtual void HandleScaleWithScreenSize()
{
Vector2 vector2 = new Vector2((float) Screen.width, (float) Screen.height);
float scaleFactor = 0.0f;
switch (this.m_ScreenMatchMode)
{
case CanvasScaler.ScreenMatchMode.MatchWidthOrHeight:
scaleFactor = Mathf.Pow(2f, Mathf.Lerp(Mathf.Log(vector2.x / this.m_ReferenceResolution.x, 2f), Mathf.Log(vector2.y / this.m_ReferenceResolution.y, 2f), this.m_MatchWidthOrHeight));
break;
case CanvasScaler.ScreenMatchMode.Expand:
scaleFactor = Mathf.Min(vector2.x / this.m_ReferenceResolution.x, vector2.y / this.m_ReferenceResolution.y);
break;
case CanvasScaler.ScreenMatchMode.Shrink:
scaleFactor = Mathf.Max(vector2.x / this.m_ReferenceResolution.x, vector2.y / this.m_ReferenceResolution.y);
break;
}
this.SetScaleFactor(scaleFactor);
this.SetReferencePixelsPerUnit(this.m_ReferencePixelsPerUnit);
}
......