前言
哈嘍,大家好,我是FEZ98.
由于今天需要實現(xiàn)一個小項目中的場景轉(zhuǎn)換效果,于是使用了Animator簡單的實現(xiàn)了這個需求,同時也與大家分享一下今日的收獲,如果哪里有錯誤,還望朋友們指正。
使用動畫實現(xiàn)簡單的場景轉(zhuǎn)換的思路是向場景中添加一個專門處理轉(zhuǎn)換效果的Image
(UGUI),同時向其添加一個Animator
,向Aniamtor
中加入兩個State
,一個設(shè)置為Set as Layer Defalut State
,即默認(rèn)狀態(tài),播放進(jìn)入場景后需要的效果,另一個則設(shè)置為關(guān)閉場景需要的效果,添加一個轉(zhuǎn)換,并設(shè)置相應(yīng)的參數(shù),這樣當(dāng)我們加載下一場景時,只需要在腳本中設(shè)置相應(yīng)的參數(shù)即可調(diào)用關(guān)閉場景需要的效果。
一、制作LevelLoader
首先我們需要制作一個GameObject
用來存放場景轉(zhuǎn)換效果所需對象與腳本,同時可以單獨加一個Camera
用來單獨顯示轉(zhuǎn)換特效。如下圖:
二、制作相應(yīng)場景轉(zhuǎn)換特效
1.淡入淡出效果
向LevelLoader中添加一個Canvas,命名為Crossfade,添加一個Image
,命名為Mask_Img,這個將這個Image
設(shè)置為全黑色,如下:
此時,我們可以通過Animator
來直接控制Image
的Color
的Alpha
來調(diào)整該圖片的透明度,使其實現(xiàn)逐漸透明的效果,這樣就可以實現(xiàn)淡出淡出的效果。
可是,如果直接通過控制Alpha
來調(diào)整透明度,如果后續(xù)我們需要在該場景轉(zhuǎn)換效果中添加一些文本或者圖片,那么就要單獨設(shè)置這些新添加的組件的透明度,這樣就會很麻煩。因此,我們可以像Mask_Img中添加一個Canvas Group
組件,之后把需要添加的組件作為Mask_Img的子節(jié)點,那么我們就可以避免做一些多余的工作了。
為Mask_Img添加一個Text
子組件,然后直接控制Canvas Group
,就可以看到效果了。如下圖:
擴(kuò)展:
Canvas Group可集中控制整組 UI 元素的某些方面,而無需單獨處理每個元素。畫布組的屬性會影響所在的游戲?qū)ο笠约八凶訉ο蟆?br>
回到正文,在添加完Mask_Img后,我們就可以通過Animator
控制其Canvas Group
來制作動畫了,在Hierarchy
選中Crossfade對象,按下Ctrl+6打開Animation
。
之后將其命名為Crossfade_End,即創(chuàng)建了一個Animator Clip
,同時Unity會自動為我們創(chuàng)建一個名為Crossfade的Animator Controller
,并將添加到Crossfade自動添加的Animator
組件中。
單擊 Animation Record
按鈕進(jìn)入動畫錄制模式,當(dāng)然也可單擊Preview
按鈕進(jìn)入預(yù)覽模式。之后在時間軸中選中1:00
的位置,這串?dāng)?shù)字第一個代表秒,第二個代表幀,1:00
即是1秒和60幀。
之后將Mask_Img的Canvas Group
中的Alpha
值由1變成0,即完成了淡入場景轉(zhuǎn)換的動畫效果。
之后我們可以先單擊選中0:00
處的關(guān)鍵幀,按住Shift再單擊1:00
處的關(guān)鍵幀,按Ctrl+C進(jìn)行復(fù)制。之后創(chuàng)建一個新的Animation Clip
,命名為Crossfade_Start。
再將兩個關(guān)鍵幀的位置調(diào)轉(zhuǎn),這樣我們就完成了Crossfade_Start的制作。
打開Crossfade Animator Controller
進(jìn)入Animator界面,在這里我們就要設(shè)置由動畫轉(zhuǎn)換狀態(tài)了,添加一個’Trigger’參數(shù),命名為Start,用來控制在轉(zhuǎn)換場景時通知Animator
播放Crossfade_Start效果。
之后從Crossfade_End右鍵單擊Make Transition
指向Crossfade_Start,同時對Transition進(jìn)行以下設(shè)置
之后我們將Crossfade_End和Crossfade_Start的Loop Time
取消勾選,因為我們只需要它們播放一次即可。
好了,這樣我們就完成了淡入淡出的動畫轉(zhuǎn)場特效。當(dāng)然現(xiàn)在還無法在場景中真正的應(yīng)用,因為還缺少控制腳本,我們會在第三部分講到同步與異步加載場景的控制腳本。
2.圓形擦除效果
首先我們用Photoshop制作一張如下的png圖片。
之后,同上述步驟一樣,創(chuàng)建一個名為CircleWipe的Canvas
,之后將橢圓形圖片加入其中,并使其能完全覆蓋住CircleWipe。
之后將其拖到右側(cè),使其無法顯示在CircleWipe中。
我們創(chuàng)建一個Aniamtor Override Controller
,其作用是擴(kuò)展Animator Controller
,從而可以使我們使用新的動畫替換掉原Animator Controller
中使用的動畫,但保留其原始結(jié)構(gòu),參數(shù)與邏輯。
之后將其添加到CircleWipe的Animator中
下面我們制作一個橢圓形由Canvas
中間向左側(cè)移動的動畫名為CircleWipe_End。
接著我們復(fù)制CircleWipe_End的關(guān)鍵幀,同時進(jìn)行反轉(zhuǎn),注意這里要將0:00
關(guān)鍵幀Position
取反,使其從右側(cè)移動到中心。
之后,我們進(jìn)行CircleWipeAnimator Override Controller
的設(shè)置,將CrossfadeAnimator Controller
作為原控制器,之后使用我們新制作的兩個動畫進(jìn)行替換即可。
這樣我們就完成了圓形擦除場景轉(zhuǎn)換效果的制作。
3.Logo旋轉(zhuǎn)效果
對于Logo旋轉(zhuǎn)場景轉(zhuǎn)換的效果步驟大體與圓形擦除一致,以下是LogoRotate_End與LogoRotate_Start的Animation Clip
。
三、編寫控制場景轉(zhuǎn)換效果腳本
1.同步加載場景
(1)將控制腳本添加進(jìn)LevelLoader中。
public class LoadLevelsManager : MonoBehaviour
{
Animator animator;
private void Awake()
{
animator = GameObject.Find("Crossfade").GetComponent<Animator>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
LoadNextLevel();
}
}
public void LoadNextLevel()
{
StartCoroutine(LoadLvel(SceneManager.GetActiveScene().buildIndex + 1));
}
IEnumerator LoadLvel(int levelBuildIndex)
{
animator.SetTrigger("Start"); //播放淡出特效
yield return new WaitForSeconds(1); //等待1秒,因為單個場景轉(zhuǎn)換特效的時長是1秒
SceneManager.LoadScene(levelBuildIndex); //加載Scenes In Build 中下一場景
}
}
(2)創(chuàng)建一個新場景,并將LevelLoader添加進(jìn)其中。
(3)將場景添加進(jìn)Build Settings。
(4)最終淡入淡出效果。
(5)最終圓形擦除效果。
(6)最終Logo旋轉(zhuǎn)效果。
2.異步加載場景
(1)分析需求。
這部分我們會在異步加載場景的過程中添加場景轉(zhuǎn)換效果。
首先,我們將Crossfade的Animator
設(shè)置如下
其中Crossfade_Idle是一個什么都不發(fā)生的動畫。
因為每次新創(chuàng)建一個場景,我們都需要將LevelLoader預(yù)制體添加到場景中會比較麻煩,因此我考慮使用單例模式加上DontDestroyOnLoad
方法,這樣在第一次加載后,LevelLoader就不會被銷毀,在后續(xù)新添加的場景中自然也不用添加LevelLoader了。之后,我們還希望使用一個LevelLoader就可以使用不同的場景轉(zhuǎn)換動畫,這樣可以方便我們進(jìn)行后續(xù)新的場景轉(zhuǎn)換動畫的添加與使用。于是我們需要添加一個用于控制不同場景轉(zhuǎn)換動畫的腳本。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Effect //三種場景轉(zhuǎn)換特效
{
Crossfade = 0, //淡入淡出
CircleWipe = 1, //圓形擦除
LogoRotate = 2, //Logo旋轉(zhuǎn)
}
public class TransitionEffect : MonoBehaviour
{
private static TransitionEffect _instance;
public static TransitionEffect Instance { get { return _instance; } }
Animator m_CrossfadeAnim; //淡入淡出
Animator m_CircleWipeAnim; //圓形擦除
Animator m_LogoRotateAnim; //Logo旋轉(zhuǎn)
private void Awake()
{
if (_instance == null)
{
DontDestroyOnLoad(this);
_instance = this;
}
else
{
Destroy(this);
}
m_CrossfadeAnim = GameObject.Find("Crossfade").GetComponent<Animator>();
m_CircleWipeAnim = GameObject.Find("CircleWipe").GetComponent<Animator>();
m_LogoRotateAnim = GameObject.Find("LogoRotate").GetComponent<Animator>();
}
/// <summary>
/// 播放指定類型場景轉(zhuǎn)換結(jié)束動畫
/// </summary>
/// <param name="effect">場景轉(zhuǎn)換特效類型</param>
public void HandleAllAnimationEnd(Effect effect)
{
switch (effect)
{
case Effect.Crossfade:
SetTransitionEffectEnd(m_CrossfadeAnim);
break;
case Effect.CircleWipe:
SetTransitionEffectEnd(m_CircleWipeAnim);
break;
case Effect.LogoRotate:
SetTransitionEffectEnd(m_LogoRotateAnim);
break;
default:
break;
}
}
private void SetTransitionEffectEnd(Animator animator)
{
animator.SetTrigger("End");
Debug.Log("AnimationClip_End is Start!");
}
/// <summary>
/// 播放指定類型場景轉(zhuǎn)換開始動畫
/// </summary>
/// <param name="effect">場景轉(zhuǎn)換特效類型</param>
public void HandleAllAnimationStart(Effect effect)
{
switch (effect)
{
case Effect.Crossfade:
SetTransitionEffectStart(m_CrossfadeAnim);
break;
case Effect.CircleWipe:
SetTransitionEffectStart(m_CircleWipeAnim);
break;
case Effect.LogoRotate:
SetTransitionEffectStart(m_LogoRotateAnim);
break;
default:
break;
}
}
private void SetTransitionEffectStart(Animator animator)
{
animator.SetTrigger("Start");
Debug.Log("AnimationClip_Start is Start!");
}
/// <summary>
/// 判斷當(dāng)前動畫是否完成播放
/// </summary>
/// <param name="effect">場景轉(zhuǎn)換特效類型</param>
/// <returns></returns>
public bool HandleAllAnimationDone(Effect effect)
{
switch (effect)
{
case Effect.Crossfade:
return IsAnimationClipDone(m_CrossfadeAnim);
case Effect.CircleWipe:
return IsAnimationClipDone(m_CircleWipeAnim);
case Effect.LogoRotate:
return IsAnimationClipDone(m_LogoRotateAnim);
default:
break;
}
return false;
}
private bool IsAnimationClipDone(Animator animator)
{
//normalizedTime:整數(shù)部分為狀態(tài)已循環(huán)的次數(shù)。小數(shù)部分為當(dāng)前循環(huán)的進(jìn)度百分比 (0-1)
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1)
{
return false;
}
Debug.Log("AnimationClip is Over!");
return true;
}
}
代碼比較簡單并且都加上了注釋,就不進(jìn)行詳細(xì)講解了。TransitionEffect 主要用到了單例模式,配合上DontDestroyOnLoad它就可以在運(yùn)行期間一致存在,我們就不用向同步加載場景那樣需要不斷往新創(chuàng)建的場景中加入LoadLevelManager。
下一部分是控制異步加載場景及選擇使用的場景轉(zhuǎn)換特效。LoadNextLevel(string levelName, Effect effect)
方法有兩個參數(shù),一個是下一需要加載場景的名稱,一個用于控制場景轉(zhuǎn)換效果類型(淡入淡出、圓形擦除、Logo旋轉(zhuǎn)等)。LoadLevel(string levelName, Effect effect)
則是具體實現(xiàn)異步加載的一個協(xié)程。我們需要在開始異步加載后,將allowSceneActivation
設(shè)置為false,這樣asyncOperation.progre
會停在0.9并且asyncOperation.isDone
也會一直為false。將LoadAble
設(shè)置為false,這樣除非當(dāng)前協(xié)程執(zhí)行完畢,否則無法調(diào)用加載另一個場景的方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class AsyncLoadLevelManager : MonoBehaviour
{
private static AsyncLoadLevelManager _instance;
public static AsyncLoadLevelManager Instance { get { return _instance; } }
public bool LoadAble { get; private set; } //當(dāng)前是否可以場景轉(zhuǎn)換
private void Awake()
{
if (_instance == null)
{
DontDestroyOnLoad(this);
_instance = this;
}
else
{
Destroy(this);
}
}
private void Start()
{
LoadAble = true; //初始允許場景轉(zhuǎn)換
}
/// <summary>
/// 使用指定場景轉(zhuǎn)換特效異步加載下一場景
/// </summary>
/// <param name="levelName">下一場景名稱</param>
/// <param name="effect">場景轉(zhuǎn)換特效類型</param>
public void LoadNextLevel(string levelName, Effect effect)
{
if (!LoadAble)
{
return;
}
StartCoroutine(LoadLevel(levelName, effect));
}
IEnumerator LoadLevel(string levelName, Effect effect)
{
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(levelName); //異步加載下一場景
asyncOperation.allowSceneActivation = false;
//當(dāng)allowSceneActivation為false時,asyncOperation.progre會停在0.9并且asyncOperation.isDone也會一直為false
LoadAble = false; //當(dāng)前不允許轉(zhuǎn)換場景
TransitionEffect.Instance.HandleAllAnimationStart(effect); //播放場景轉(zhuǎn)換開始動畫
yield return null;
while (asyncOperation.progress < 0.9f) //檢查是否已完成異步加載
{
yield return null;
}
while (!TransitionEffect.Instance.HandleAllAnimationDone(effect)) //檢查當(dāng)前動畫是否完成播放
{
yield return null;
}
asyncOperation.allowSceneActivation = true; //允許場景準(zhǔn)備就緒后立即激活場景
while (!asyncOperation.isDone) //檢查是否已經(jīng)激活場景
{
yield return null;
TransitionEffect.Instance.HandleAllAnimationEnd(effect); //播放場景轉(zhuǎn)換結(jié)束動畫
}
while (!TransitionEffect.Instance.HandleAllAnimationDone(effect)) //檢查當(dāng)前動畫是否完成播放
{
yield return null;
}
LoadAble = true; //可以繼續(xù)轉(zhuǎn)換場景
}
}
之后,我們用一個測試腳本進(jìn)行方法的調(diào)用。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private void Update()
{
if (Input.GetMouseButtonDown(0)) //點擊鼠標(biāo)左鍵
{
AsyncLoadLevelManager.Instance.LoadNextLevel("SceneB", Effect.Crossfade);
}
else if (Input.GetMouseButtonDown(1)) //點擊鼠標(biāo)右鍵
{
AsyncLoadLevelManager.Instance.LoadNextLevel("SceneC", Effect.CircleWipe);
}
else if (Input.GetMouseButtonDown(2)) //點擊鼠標(biāo)中鍵
{
AsyncLoadLevelManager.Instance.LoadNextLevel("SceneA", Effect.LogoRotate);
}
}
}
最終效果如下:
擴(kuò)展
背景圖片移動文章來源:http://www.zghlxwxcb.cn/news/detail-778611.htmlusing UnityEngine; using UnityEngine.UI; public class BackgroundMove : MonoBehaviour { public float speed = 0; //移動速度 float pos = 0; //當(dāng)前位置 private RawImage image; void Start() { image = GetComponent<RawImage>(); } void Update() { pos += speed; if (pos > 1.0F) pos -= 1.0F; image.uvRect = new Rect(pos, 0, 1, 1); } }
四、完畢
好啦,以上就是我今天想要分享的內(nèi)容啦~
我是FEZ98:https://blog.csdn.net/weixin_43057990
原創(chuàng)不易,若轉(zhuǎn)載請注明出處,感謝大家~
喜歡我的可以點贊、關(guān)注、收藏,最后希望能夠?qū)Υ蠹矣兴鶐椭?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-778611.html
到了這里,關(guān)于【Unity】Unity使用動畫實現(xiàn)場景轉(zhuǎn)換的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!