天天看點

NGUI中的Anchor自适應的執行先後問題

NGUI中的Anchor自适應的執行先後問題

一直以為Execute下的三個枚舉 OnUpdate, OnStart,OnEnable的意思分别是 在Update,Start,OnEnable執行的時候适配尺寸(相對于Target的自适應),原來一直是我了解錯了。

今天項目需求需要在Anchor适應完了之後 執行一個計算操作,我把這個操作放在了Start裡,也就是需要讓Start在Anchor适應完了之後執行,結果無論怎麼調整Execute都達不到效果,照理說即使OnEnable應該是會在Start之前執行的 結果Execute選擇OnEnable也不行。 于是去看NGUI實作Anchors适配的代碼,這一步操作是繼承自UIRect的. 

protected virtual void OnEnable ()
	{
#if UNITY_EDITOR
		mEnabled = true;
#endif
		mUpdateFrame = -1;
		
		if (updateAnchors == AnchorUpdate.OnEnable)
		{
			mAnchorsCached = false;
			mUpdateAnchors = true;
		}
		if (mStarted) OnInit();
		mUpdateFrame = -1;
	}
           
protected void Start ()
	{
		mStarted = true;
		OnInit();
		OnStart();
	}
           
public void Update ()
	{
		if (!mAnchorsCached) ResetAnchors();

		int frame = Time.frameCount;

#if UNITY_EDITOR
		if (mUpdateFrame != frame || !Application.isPlaying)
#else
		if (mUpdateFrame != frame)
#endif
		{
#if UNITY_EDITOR
			if (updateAnchors == AnchorUpdate.OnUpdate || mUpdateAnchors || !Application.isPlaying)
#else
			if (updateAnchors == AnchorUpdate.OnUpdate || mUpdateAnchors)
#endif
			{
				mUpdateFrame = frame;
				mUpdateAnchors = false;

				bool anchored = false;

				if (leftAnchor.target)
				{
					anchored = true;
					if (leftAnchor.rect != null && leftAnchor.rect.mUpdateFrame != frame)
                        leftAnchor.rect.Update();
				}

				if (bottomAnchor.target)
				{
					anchored = true;
					if (bottomAnchor.rect != null && bottomAnchor.rect.mUpdateFrame != frame)
                        bottomAnchor.rect.Update();
				}

				if (rightAnchor.target)
				{
					anchored = true;
					if (rightAnchor.rect != null && rightAnchor.rect.mUpdateFrame != frame)
                        rightAnchor.rect.Update();
				}

				if (topAnchor.target)
				{
					anchored = true;
					if (topAnchor.rect != null && topAnchor.rect.mUpdateFrame != frame)
                        topAnchor.rect.Update();
				}

				// Update the dimensions using anchors
				if (anchored) OnAnchor();
			}

			// Continue with the update
			OnUpdate();
		}
	}
           

可以看到隻有在Update中有執行Anchor的适應操作,難怪不管Execute中不管選擇哪個Anchors的适配都要比Start晚執行了,Update确實是比Start要晚執行啊。

<pre name="code" class="csharp">if (updateAnchors == AnchorUpdate.OnUpdate || mUpdateAnchors)
           

Update中控制執行Anchor的條件 可以看出若Execute類型選擇了OnUpdate 那麼每次Update的時候都會自适應一次。另一個mUpdateAnchors 變量在初始化的時候是為True的,也就是說如果選擇了OnStart 那麼在遊戲開始的時候會執行一次自适應,但是也是在Update中執行的,隻是這個模式 隻在開始的時候執行一次。

而如果選擇了OnEnable則在每次Enable的時候都将mUpdateAnchors都置為true一次,然後就能進到Update中進行自适應了,但是這個操作還是在Update中執行的。

是以這三個選擇并不是分别在Start Update 和OnEnable的時候 自适應一次的意思。而是隻适配一次(Stasrt),每次Update都适配,和每次Enable都适配 的意思。

那麼想要達到 分别在Start Update 和OnEnable的時候 自适應一次的效果 隻需要在Start 和 OnEnable的時候調用一次Update 就可以了、

更改Start和OnEnable中的代碼

protected virtual void OnEnable ()
	{
#if UNITY_EDITOR
		mEnabled = true;
#endif
		mUpdateFrame = -1;
		
		if (updateAnchors == AnchorUpdate.OnEnable)
		{
			mAnchorsCached = false;
			mUpdateAnchors = true;
            Update();
		}
		if (mStarted) OnInit();
		mUpdateFrame = -1;
	}
           
protected void Start ()
	{
		mStarted = true;
		OnInit();
		OnStart();
        if (updateAnchors == AnchorUpdate.OnStart)
        {
            Update();
        }
	}
           

這樣也沒有改變代碼原來的意思,選擇OnStart還是隻在開始的時候 适應一次,隻是變成了 在Start中立即執行,OnEnable也是一樣。這樣就能滿足一些更适應順序相關的需求了。