最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

UGUI-創(chuàng)建屏幕過渡

2020-07-22 09:37 作者:unity_某某師_高錦錦  | 我要投稿

在多個(gè) UI 屏幕之間進(jìn)行過渡的需求相當(dāng)普遍。在本頁面中,我們將探索一種使用動(dòng)畫和狀態(tài)機(jī)來創(chuàng)建和管理這些過渡以便驅(qū)動(dòng)和控制每個(gè)屏幕的簡單方法。

概述

大體思路是每個(gè)屏幕都有一個(gè)動(dòng)畫控制器以及兩個(gè)狀態(tài)(Open 和 Closed)和一個(gè)布爾參數(shù)?(Open)。要在屏幕之間過渡,只需關(guān)閉當(dāng)前打開的屏幕并打開所需的屏幕。為了簡化這一過程,我們將創(chuàng)建一個(gè)小型的 ScreenManager 類,稍后用于跟蹤并處理所有已打開的屏幕。觸發(fā)過渡的按鈕只需要讓 ScreenManager 打開所需的屏幕。

關(guān)于導(dǎo)航的注意事項(xiàng)

如果打算支持通過控制器/鍵盤對(duì) UI 元素進(jìn)行導(dǎo)航,必須注意幾點(diǎn)。必須避免可選元素超出屏幕,因?yàn)檫@樣會(huì)讓玩家選擇屏幕外的元素,為此我們可以停用所有屏幕外層級(jí)視圖。我們還需要確保在顯示新屏幕時(shí)將其中的某個(gè)元素設(shè)置為選中狀態(tài),否則玩家將無法導(dǎo)航到新屏幕。我們將在下面的 ScreenManager 類中處理所有這些問題。

設(shè)置動(dòng)畫控制器

讓我們來看看進(jìn)行屏幕過渡時(shí)所需的最常見和最小低限度的動(dòng)畫控制器設(shè)置??刂破餍枰粋€(gè)布爾參數(shù) (Open) 和兩個(gè)狀態(tài)(Open 和 Closed),每個(gè)狀態(tài)應(yīng)該有一段只有一個(gè)關(guān)鍵幀的動(dòng)畫,這樣就能讓狀態(tài)機(jī)為我們執(zhí)行過渡混合。

Open 狀態(tài)和動(dòng)畫
Closed 狀態(tài)和動(dòng)畫

現(xiàn)在我們需要在兩個(gè)狀態(tài)之間創(chuàng)建過渡,讓我們從 Open 到 Closed 的過渡開始,首先正確設(shè)置條件,當(dāng)參數(shù) Open 設(shè)置為 false 時(shí),我們希望從 Open 變?yōu)?Closed。接著,我們創(chuàng)建從 Closed 到 Open 的過渡,并將條件設(shè)置為:當(dāng)參數(shù) Open 為 true 時(shí),狀態(tài)從 Closed 變?yōu)?Open。

從 Closed 到 Open 的過渡
從 Open 到 Closed 的過渡

管理屏幕

進(jìn)行以上所有設(shè)置后,唯一缺少的是我們需要在要過渡到的屏幕的動(dòng)畫器上將參數(shù) Open 設(shè)置為 true,并在當(dāng)前打開的屏幕的動(dòng)畫器上將 Open 設(shè)置為 false。為此,我們將創(chuàng)建一個(gè)小腳本:

using UnityEngine;?

using UnityEngine.UI;?

using UnityEngine.EventSystems;?

using System.Collections;?

using System.Collections.Generic;?

public class ScreenManager : MonoBehaviour { ? ?

//在場景開始時(shí)自動(dòng)打開的屏幕 ? ?

public Animator initiallyOpen; ? ?

//當(dāng)前打開的屏幕 ? ?

private Animator m_Open; ? ?

//我們用來控制過渡的參數(shù)的哈希值。 ? ?

private int m_OpenParameterId; ? ?

//在我們打開當(dāng)前屏幕之前選擇的游戲?qū)ο蟆? ? ?

//在關(guān)閉屏幕時(shí)使用,因此我們可以返回將其打開的按鈕。 ? ?

private GameObject m_PreviouslySelected; ? ?

//我們?cè)跈z查時(shí)需要比對(duì)的動(dòng)畫器狀態(tài)和過渡名稱。 ? ?

const string k_OpenTransitionName ="Open"; ? ?

const string k_ClosedStateName = "Closed"; ? ?

public void OnEnable() ? ?{ ? ? ? ?

//我們將哈希緩存到 "Open" 參數(shù),因此可提供給 Animator.SetBool。 ? ? ? ?m_OpenParameterId = Animator.StringToHash (k_OpenTransitionName);?

//現(xiàn)在打開初始屏幕(如果已設(shè)置)。 ? ? ? ?

if (initiallyOpen == null) ? ? ? ? ? ?return; ? ? ? ?

OpenPanel(initiallyOpen); ? ?

} ? ?

//關(guān)閉當(dāng)前打開的面板并打開提供的面板。 ? ?

//還負(fù)責(zé)處理導(dǎo)航,設(shè)置新的選定元素。 ? ?

public void OpenPanel (Animator anim) ? ?{ ? ? ? ?

if (m_Open == anim) ? ? ? ? ? ?return; ? ? ? ?

//激活新的屏幕層級(jí)視圖,以便對(duì)其進(jìn)行動(dòng)畫化。 ? ? ? ?

anim.gameObject.SetActive(true); ? ? ??

?//保存當(dāng)前選定的用于打開此屏幕的按鈕。(CloseCurrent 會(huì)對(duì)其進(jìn)行修改) ? ? ? ?

var newPreviouslySelected = EventSystem.current.currentSelectedGameObject; ? ? ? ?

//將屏幕移到前面。 ? ? ? ?

anim.transform.SetAsLastSibling(); ? ? ? ?

CloseCurrent(); ? ? ? ?

m_PreviouslySelected = newPreviouslySelected; ? ? ? ?

//將新屏幕設(shè)置為打開的屏幕。 ? ? ? ?

m_Open = anim; ? ? ??

//啟動(dòng)打開動(dòng)畫 ? ? ? ?

m_Open.SetBool(m_OpenParameterId, true); ? ? ??

?//將新屏幕中的一個(gè)元素設(shè)置為新的選定元素。 ? ? ? ?

GameObject go = FindFirstEnabledSelectable(anim.gameObject); ? ? ??

?SetSelected(go); ? ?

} ? ?

//查找提供的層級(jí)視圖中的第一個(gè)可選元素。 ? ?

static GameObject FindFirstEnabledSelectable (GameObject gameObject){ ? ? ? ?GameObject go = null; ? ? ? ?

var selectables = gameObject.GetComponentsInChildren<Selectable> (true); ? ? ? ?

foreach (var selectable in selectables) { ? ? ? ? ? ?

if (selectable.IsActive () && selectable.IsInteractable ()) { ? ? ? ? ? ? ? ?

go = selectable.gameObject; ? ? ? ? ? ? ? ?

break; ? ? ? ? ??

?} ? ? ??

?} ? ? ? ?

return go; ? ?

} ? ?

//關(guān)閉當(dāng)前打開的屏幕 ? ?

//還負(fù)責(zé)處理導(dǎo)航。 ? ?

//將選定元素還原為打開當(dāng)前屏幕之前使用的可選元素。 ? ?

public void CloseCurrent() ? ?{ ? ? ? ?

if (m_Open == null) ? ? ? ? ? ?

return; ? ? ??

?//啟動(dòng)關(guān)閉動(dòng)畫。 ? ? ? ?

m_Open.SetBool(m_OpenParameterId, false); ? ? ? ?

//將選定元素還原為打開當(dāng)前屏幕之前使用的可選元素。

?SetSelected(m_PreviouslySelected); ? ? ??

?//關(guān)閉動(dòng)畫結(jié)束時(shí)啟動(dòng)協(xié)程以禁用該層級(jí)視圖。?

?StartCoroutine(DisablePanelDeleyed(m_Open)); ? ? ? ?

//無打開屏幕。 ? ? ? ?

m_Open = null; ? ?

} ? ?

//協(xié)程將檢測關(guān)閉動(dòng)畫何時(shí)結(jié)束,并會(huì)停用 ? ?

//層級(jí)視圖。 ? ?

IEnumerator DisablePanelDeleyed(Animator anim)?{ ? ? ? ?

bool closedStateReached = false; ? ? ? ?

bool wantToClose = true; ? ? ? ?

while (!closedStateReached && wantToClose){

if (!anim.IsInTransition(0)) ? ? ? ? ? ? ??

?closedStateReached = anim.GetCurrentAnimatorStateInfo(0).IsName(k_ClosedStateName);

? wantToClose = !anim.GetBool(m_OpenParameterId); ? ? ? ? ? ?

yield return new WaitForEndOfFrame(); ? ? ? ?

} ? ? ? ?

if (wantToClose) ? ? ? ? ? ?

anim.gameObject.SetActive(false); ? ?

} ? ?

//選定提供的游戲?qū)ο? ? ?

//當(dāng)使用鼠標(biāo)/觸摸時(shí),我們實(shí)際上想要將其設(shè)置為先前選定的對(duì)象并且 ? ?

//現(xiàn)在不將任何對(duì)象設(shè)置為選定狀態(tài)。 ? ?

private void SetSelected(GameObject go) ? ?{ ? ? ? ?

//選擇游戲?qū)ο蟆? ? ? ? ?

EventSystem.current.SetSelectedGameObject(go); ? ? ? ?

//如果我們現(xiàn)在正在使用鍵盤,那么我們便完成了所有設(shè)置。 ? ? ? ?

var standaloneInputModule = EventSystem.current.currentInputModule as StandaloneInputModule; ? ? ? ?

if (standaloneInputModule != null) ? ? ? ? ? ?

return; ? ? ? ?

//由于我們使用的是指針設(shè)備,因此我們不希望選擇任何內(nèi)容。 ? ? ? ?

//但是如果用戶切換到鍵盤,我們希望從提供的游戲?qū)ο箝_始導(dǎo)航。 ? ? ? ?

//所以,此處我們將當(dāng)前的選定項(xiàng)設(shè)置為 null,因此提供的游戲?qū)ο蟪蔀?EventSystem 中的最后選定項(xiàng)。 ? ? ? ?

EventSystem.current.SetSelectedGameObject(null); ? ?

} }

讓我們連接此腳本,為此需要?jiǎng)?chuàng)建新的游戲?qū)ο?,我們可以將其重命名為“ScreenManager”之類的名稱,并將上面的組件添加到該游戲?qū)ο?。您可以為其指定初始屏幕,此屏幕將在場景啟?dòng)時(shí)打開。

現(xiàn)在,最后的工作是讓?UI 按鈕生效。選擇應(yīng)觸發(fā)屏幕過渡的按鈕,并在 Inspector 的?On Click ()?列表下添加一個(gè)新操作。將剛創(chuàng)建的 ScreenManager 游戲?qū)ο笸系?ObjectField,在下拉選單中選擇?ScreenManager > OpenPanel (Animator),然后將用戶點(diǎn)擊按鈕時(shí)要打開的面板拖放到 ObjectField。

Button Inspector

注意

這種方法只要求每個(gè)屏幕有一個(gè)動(dòng)畫控制器 (AnimatorController) 以及一個(gè) Open 參數(shù)和一個(gè) Closed 狀態(tài)即可發(fā)揮作用(無論屏幕或狀態(tài)機(jī)的構(gòu)造如何)。這種方法也適用于嵌套的屏幕,這意味著每個(gè)嵌套級(jí)別只需要一個(gè) ScreenManager。

我們上面設(shè)置的狀態(tài)機(jī)的默認(rèn)狀態(tài)為 Closed,因此使用此控制器的所有屏幕在開始時(shí)均為關(guān)閉狀態(tài)。ScreenManager 提供了一個(gè) initiallyOpen 屬性,因此可以指定首先顯示的屏幕。

UGUI-創(chuàng)建屏幕過渡的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
多伦县| 门头沟区| 积石山| 托克逊县| 乌苏市| 望都县| 保定市| 铅山县| 陆川县| 灌南县| 隆化县| 孝感市| 巴马| 碌曲县| 神木县| 祁门县| 普兰店市| 满城县| 永泰县| 水城县| 和龙市| 邯郸县| 吉安县| 宜兰市| 吉林省| 葫芦岛市| 揭东县| 昌图县| 望城县| 娄底市| 锦州市| 利川市| 独山县| 宜春市| 通许县| 淳化县| 安岳县| 海晏县| 霍林郭勒市| 申扎县| 吕梁市|