ArcadeZero4.0的Scenecontrol指南
原文地址:https://github.com/Tempestissiman/ArcadeScenecontrol
API文檔地址:https://github.com/Tempestissiman/ArcadeScenecontrol/wiki
ArcadeZero下載地址:https://drive.google.com/drive/folders/1ziY89wDWrwQJxbD-YGCSIwMwdE_WzrRE
開(kāi)發(fā)者油管地址:https://www.youtube.com/channel/UCHnTjGOLbwufuYBnFnW8oYQ/featured
已經(jīng)取得原作者授權(quán)。

引言
本文檔是指導(dǎo)新手或已經(jīng)有一定經(jīng)驗(yàn)的人開(kāi)始使用全新的Scenecontrol API。
注意,該文檔沒(méi)有涵蓋全部的API中可用的功能,但會(huì)為您提供足夠的知識(shí)以自由探索其余功能。全部的API使用請(qǐng)查看[參考文檔](https://github.com/Tempestissiman/ArcadeScenecontrol/wiki)。
一般而言,上手Scenecontrol的腳本編寫(xiě)需要一定的Lua語(yǔ)言基礎(chǔ),本文檔假定您已經(jīng)對(duì)該語(yǔ)言有一定的了解。如果您是新手或者想要復(fù)習(xí)一下Lua語(yǔ)言,請(qǐng)參考[官方教程](https://www.lua.org/pil/contents.html)。
貢獻(xiàn): 您可以幫忙將該文檔翻譯為其他語(yǔ)言!
新特性
舊版API存在的一些問(wèn)題:
慢:舊版API嚴(yán)重依賴用戶編寫(xiě)的Lua代碼,即使是在運(yùn)行態(tài)。這不僅很慢,也有難以移植到其他平臺(tái)的風(fēng)險(xiǎn)。
不靈活:寄存器系統(tǒng)過(guò)于復(fù)雜,造成了一些簡(jiǎn)單任務(wù)實(shí)現(xiàn)起來(lái)過(guò)于繁瑣,如在多場(chǎng)景下控制同一個(gè)對(duì)象。(這與它的目的恰恰相反?。?/p>
整體丑陋并且不直觀。
考慮到以上這些問(wèn)題,以下是新版API的改進(jìn):
完全確定性:新版API依賴于*Channels*這一概念(后續(xù)會(huì)詳細(xì)介紹)。只需要執(zhí)行一次Lua代碼,即可導(dǎo)出到其他不需要Lua的格式。
透明:您可以完全控制新系統(tǒng),從而可以更快地編寫(xiě)腳本。
協(xié)作:使用別的腳本也更加容易!
除此之外,本次更新還帶來(lái)了一些新的功能:
場(chǎng)景控制Scenecontrol編輯窗口:您可以直接在ArcadeZero中編輯您的事件!
拓展功能:如后期效果處理。
內(nèi)置的場(chǎng)景控制Scenecontrol命令。
如果這些讓您感到興奮,那讓我們不再浪費(fèi)時(shí)間,直接開(kāi)始吧!
對(duì)熟悉舊系統(tǒng)用戶的警告
新系統(tǒng)完全支持舊腳本的遷移,但請(qǐng)注意坐標(biāo)和旋轉(zhuǎn)等內(nèi)容可能需要修改。新系統(tǒng)對(duì)此進(jìn)行了一些變更,以使得它們編輯起來(lái)更加常規(guī)和便捷。

開(kāi)始
您需要使用到的工具:
- ArcadeZero v4或更高的版本,或者ArcadeZero v4的任何分支。
- 一個(gè)有效的IDE或文本編輯器,推薦使用VSCode。
- 您可以為VSCode安裝[“Vscode Arcaea文件格式支持”拓展](https://github.com/yojohanshinwataikei/vscode-arcaea-file-format),以及Lua拓展。
1. 內(nèi)置命令
我們從最基本的內(nèi)置命令開(kāi)始,首先熟悉下Scenecontrol編輯窗口。
aff語(yǔ)法
您可能已經(jīng)習(xí)慣于在.aff文件中手動(dòng)編寫(xiě)場(chǎng)景控制命令。如果您沒(méi)有手動(dòng)編輯過(guò),這里給出一個(gè)基礎(chǔ)的場(chǎng)景控制語(yǔ)法示例:
- `timing` 通常指特效發(fā)生的時(shí)間。
- `scenecontrolType` 定義了場(chǎng)景控制的類型。
- `argument0, argument1,...` 定義了場(chǎng)景控制的參數(shù),規(guī)定了場(chǎng)景控制命令的操作方式。
我們也可以在timingroup時(shí)間序列組中使用場(chǎng)景控制命令,但是可能會(huì)有不同的效果,這取決于場(chǎng)景命令的類型。
使用內(nèi)置命令
ArcadeZero目前支持以下類型:
- `trackdisplay` 改變主軌道的透明度。
- `hidegroup` 改變同一個(gè)時(shí)序組內(nèi)所有音符的透明度。
- `enwidenlane` 在主軌道兩側(cè)增加兩個(gè)額外軌道(用于Pentiment, Arcana Eden和Testify)
- `enwidencamera` 移動(dòng)攝像機(jī)來(lái)支持*enwidenlane*.
`timing` 和 `duration`都使用毫秒為基本單位。 `changeToAlpha` 接收一個(gè)從0-255的值表示透明度的大小。`changeToState`接收0或1,表示是否啟用效果,1表示啟用,0表示禁用。
> 從技術(shù)上講,這與官方游戲的規(guī)范有所不同,但是為了保持系統(tǒng)設(shè)計(jì)上的一致性,我選擇了與官方不完全重合。
如果您不習(xí)慣使用這些場(chǎng)景控制命令,那么我強(qiáng)烈建議您自己練習(xí)使用一段時(shí)間。場(chǎng)景控制是一個(gè)很不錯(cuò)的技能!
編輯窗口
現(xiàn)在讓我們熟悉一下場(chǎng)景控制的新編輯敞口。打開(kāi)一個(gè)譜面,然后單擊右側(cè)帶有星型的按鈕,您將看到一個(gè)如下所示的小窗口:

在最上方,您將會(huì)看到:
- 場(chǎng)景控制類型下拉菜單:您可以在這里選擇要使用的場(chǎng)景類型。
- 切換字段按鈕:這回在每個(gè)參數(shù)的單獨(dú)字段和組合字段之間切換。您可以嘗試按幾次,然后看看會(huì)發(fā)生什么。
- 刷新按鈕:這會(huì)刷新列表并重新加載任何包含的腳本。
在中間部分,是場(chǎng)景控制的事件列表?,F(xiàn)在它可能是空的,因?yàn)槟淖V面中并不包含與當(dāng)前選定控件相關(guān)的事件。讓我們通過(guò)按任意行上的"+"按鈕來(lái)添加一個(gè),您會(huì)看到出現(xiàn)一個(gè)新事件:

現(xiàn)在,您可以根據(jù)自己的喜好更改參數(shù)!
另外請(qǐng)注意,該窗口僅僅顯示當(dāng)前活動(dòng)時(shí)序組內(nèi)包含的場(chǎng)景控制事件。在編寫(xiě)過(guò)程中,這是很容易被遺忘的。在實(shí)際編寫(xiě)中,經(jīng)常會(huì)出現(xiàn)為什么列表內(nèi)沒(méi)有控制事件,但是控制效果仍然處于活躍狀態(tài)的問(wèn)題。
這就是最基本的使用了!我們已經(jīng)大致了解了場(chǎng)景控制的工作原理,我們將在下一節(jié)開(kāi)始深入了解腳本的部分。
2. 腳本編寫(xiě)
2.1. 譜面文件結(jié)構(gòu)
相信您之前一致在使用官方提供的內(nèi)置場(chǎng)景控制類型,但是Arcaea自制譜面的一大樂(lè)趣是能夠自定義場(chǎng)景控制類型,讓我們現(xiàn)在開(kāi)始吧!
首先進(jìn)入到您的譜面工程文件夾(包含`Arcade`文件夾的那個(gè))。創(chuàng)建一個(gè)名為`Scenecontrol`(區(qū)分大小寫(xiě))的文件夾,并在其中創(chuàng)建一個(gè)名為`init.lua`的文件。
`Scenecontrol/init.lua`是ArcadeZero加載譜面時(shí)默認(rèn)運(yùn)行的腳本。`Scenecontrol`文件夾是您放置所有資源文件(如圖像等)供腳本讀取的位置。
> 對(duì)于高級(jí)用戶:您還可以使用`require`將您的lua代碼拆分為多個(gè)腳本文件。文件名并不是那么重要?。ǔ四J(rèn)的`init.lua`)
讓我們打開(kāi)新創(chuàng)建的lua文件開(kāi)始編碼吧!但是,我們首先先來(lái)介紹一個(gè)基本概念:場(chǎng)景控制命令中的*Controllers* 和 *Channels*。(下一部分將學(xué)習(xí)如何自定義不同的場(chǎng)景控制類型?。?/p>
2.2. Controllers & Channels - 等級(jí)1
> 等級(jí)1的控制器和通道能夠使您獲取場(chǎng)景中已經(jīng)存在的任何東西,并根據(jù)自己的喜好對(duì)其進(jìn)行操作!
不同類型的控制器是您自定義的lua代碼與場(chǎng)景中對(duì)象交互的工具。舉例來(lái)說(shuō),您將通過(guò)軌道控制器控制軌道,與精靈控制器控制2D圖像等。這里的交互只意味著修改它的屬性,如位置、旋轉(zhuǎn)、縮放和顏色等。
到目前位置,它和舊系統(tǒng)是完全相同的!但是,這次并不是像舊系統(tǒng)那樣直接修改,而是用一種更間接的方式。
我們已經(jīng)了解了控制器,那么通道是什么呢?所有的通道都將用于回答以下問(wèn)題:
?“這首歌現(xiàn)在是X毫秒,它的值是多少?”
控制器的每個(gè)屬性都將被附加一個(gè)通道,該通道決定了對(duì)應(yīng)屬性在某個(gè)時(shí)刻如何改變。
您可能還是不太明白這意味著什么。讓我們從一個(gè)實(shí)際的lua代碼具體示例來(lái)說(shuō)明這一點(diǎn):
我們首先定義一個(gè)控制器,在這里我們選擇內(nèi)部控制器。我們選擇`Scene`來(lái)抓取一個(gè),這將是您抓取和創(chuàng)建絕大部分控制器的地方:
將控制器的位置賦值為其他:
單擊場(chǎng)景控件編輯窗口上的`Refresh`刷新按鈕,這會(huì)重新加載您的腳本,更新后的腳本會(huì)告知Arcade將軌道移動(dòng)到(1, 2, 3)的新位置。您的軌道目前會(huì)像這樣:

以下是對(duì)剛剛發(fā)生事情的詳細(xì)解釋:
1. `Channel.constant(value)`定義了一個(gè)通道,它總是返回您傳入的數(shù)值,而不管時(shí)間。(譯者注:常量通道,數(shù)值不會(huì)隨著時(shí)間發(fā)生改變。)
2. 您將其中的三個(gè)通道分配給控制器的三個(gè)屬性。
3. 控制器根據(jù)您設(shè)置的數(shù)值更新它的值,這里為常數(shù)值1,2和3。
您的腳本現(xiàn)在并沒(méi)有做什么特別有趣的事,但是這對(duì)您理解整個(gè)系統(tǒng)非常重要。如果您了解使用通道以后,您就會(huì)了解新系統(tǒng)下的場(chǎng)景控制系統(tǒng),所以請(qǐng)慢慢來(lái)!
如果您覺(jué)得您掌握了它,那么我們繼續(xù)學(xué)習(xí)使用時(shí)變通道來(lái)增加一些趣味性。(`Channel.constant()`類似的常量通道是行不通的。)在此之前,同樣介紹一個(gè)新概念:關(guān)鍵幀通道。
關(guān)鍵幀通道由一系列的關(guān)鍵幀定義。如果您之前曾經(jīng)有過(guò)動(dòng)畫(huà)制作的經(jīng)驗(yàn),那么您會(huì)對(duì)這個(gè)概念很熟悉。如果您沒(méi)有制作過(guò)動(dòng)畫(huà),那么讓我們看一個(gè)例子:

這個(gè)通道有3個(gè)關(guān)鍵幀:
- 第一個(gè)關(guān)鍵幀在時(shí)間0,且值為0。
- 第二個(gè)關(guān)鍵幀在時(shí)間1000,且值為1。
- 第三個(gè)關(guān)鍵幀在時(shí)間2000,且值為0。
然后,該通道將三個(gè)關(guān)鍵幀點(diǎn)連接起來(lái),來(lái)為所有的連續(xù)時(shí)刻計(jì)算出所有的輸出值。
實(shí)際上,使用關(guān)鍵幀通道非常簡(jiǎn)單。我們使用lua代碼對(duì)上述描述的通道進(jìn)行編碼:
>這只是一種寫(xiě)法,也是最清楚地說(shuō)明正在發(fā)生事件的一種方式,您可以這樣寫(xiě)來(lái)縮短這一命令:
> 您可以復(fù)用通道!同一個(gè)通道可以被分配給多個(gè)屬性,更改一個(gè)通道可以同時(shí)更改全部的屬性值。我認(rèn)為這是一個(gè)很好的做法,因?yàn)檫@意味著您只需要設(shè)置一次關(guān)鍵幀,就可以更改多個(gè)屬性。
刷新一下,然后看看效果。軌道現(xiàn)在應(yīng)該從0ms到1000ms線性移動(dòng)到一個(gè)位置,然后從1000ms到2000ms再返回原來(lái)的位置。
誒,您說(shuō)您不希望它線性移動(dòng)?那么我們來(lái)試試緩動(dòng)!只需要傳遞一個(gè)額外的字符串:
>警告:這里的'so'實(shí)際上類似于Arcaea中的si虹?。ㄆ鸪蹩欤詈舐?。這是和官方不一致的地方。
您可以在創(chuàng)建通道時(shí)更改默認(rèn)的緩動(dòng)類型,這和上方的代碼片段是等價(jià)的:
以下是支持的所有緩動(dòng)類型列表,每種緩動(dòng)類型都可以用多種方式編寫(xiě):
(詳情參見(jiàn)原文檔)
| 類型 | 別名 | 曲線 |
| - | - | - |
| linear | l | <img src="https://i.imgur.com/RW6npU1.png" width=120em> |
| inconstant | inconst, cnsti | <img src="https://i.imgur.com/OtPvAGb.png" width=120em> |
| outconstant | outconst, cnsto | <img src="https://i.imgur.com/UYKymRq.png" width=120em> |
| inoutconstant | inoutconst, cnstb | <img src="https://i.imgur.com/D916zO3.png" width=120em> |
| insine | si | <img src="https://i.imgur.com/6FWfL7v.png" width=120em> |
| outsine | so | <img src="https://i.imgur.com/VDB347V.png" width=120em> |
| inoutsine | b | <img src="https://i.imgur.com/uprRIh9.png" width=120em> |
| inquadratic | inquad, 2i | <img src="https://i.imgur.com/qafhmH3.png" width=120em> |
| outquadratic | outquad, 2o | <img src="https://i.imgur.com/lPvQZiq.png" width=120em> |
| inoutquadratic | inoutquad, 2b | <img src="https://i.imgur.com/KrMCfGe.png" width=120em> |
| incubic | incube, 3i | <img src="https://i.imgur.com/pBtlUPe.png" width=120em> |
| outcubic | outcube, 3o | <img src="https://i.imgur.com/pBtlUPe.png" width=120em> |
| inoutcubic | inoutcube, 3b | <img src="https://i.imgur.com/2vsaAfH.png" width=120em> |
| inquartic | inquart, 4i | <img src="https://i.imgur.com/1gkdwj3.png" width=120em> |
| outquartic | outquart, 4o | <img src="https://i.imgur.com/1gkdwj3.png" width=120em> |
| inoutquartic | inoutquart, 4b | <img src="https://i.imgur.com/DpLpSKE.png" width=120em> |
| inquintic | inquint, 5i | <img src="https://i.imgur.com/lO6CS1R.png" width=120em> |
| outquintic | outquint, 5o | <img src="https://i.imgur.com/cjNq1sq.png" width=120em> |
| inoutquintic | inoutquint, 5b | <img src="https://i.imgur.com/0ElZdrQ.png" width=120em> |
| inexponential | inexpo, exi | <img src="https://i.imgur.com/CxM7iHY.png" width=120em> |
| outexponential | outexpo, exo | <img src="https://i.imgur.com/zSi35WU.png" width=120em> |
| inoutexponential | inoutexpo, exb | <img src="https://i.imgur.com/bYFbAOK.png" width=120em> |
| incircle | incirc, ci | <img src="https://i.imgur.com/XlLATi4.png" width=120em> |
| outcircle | outcirc, co | <img src="https://i.imgur.com/V7jXmBe.png" width=120em> |
| inoutcircle | inoutcirc, cb | <img src="https://i.imgur.com/Nq5JkvD.png" width=120em> |
| inback | bki | <img src="https://i.imgur.com/vL2NZps.png" width=120em> |
| outback | bko | <img src="https://i.imgur.com/YKBd78p.png" width=120em> |
| inoutback | bkb | <img src="https://i.imgur.com/JnSeIih.png" width=120em> |
| inelastic | eli | <img src="https://i.imgur.com/BsUF01a.png" width=120em> |
| outelastic | elo | <img src="https://i.imgur.com/IhlWlew.png" width=120em> |
| inoutelastic | elb | <img src="https://i.imgur.com/oULApFZ.png" width=120em> |
| inbounce | bni | <img src="https://i.imgur.com/fCHgebv.png" width=120em> |
| outbounce | bno | <img src="https://i.imgur.com/58pzeQD.png" width=120em> |
| inoutbounce | bnb | <img src="https://i.imgur.com/dhdjvX0.png" width=120em> |
> 您還可以打開(kāi)通道外推的開(kāi)關(guān)。外推意味著延續(xù)您添加的關(guān)鍵幀之外的曲線,我不知道為什么有人會(huì)使用它,但是它是可用的:
那么現(xiàn)在您已經(jīng)掌握了控制器和通道的基礎(chǔ)知識(shí),現(xiàn)在可以將任何屬性更改為您喜歡的任何行為!但是新API系統(tǒng)提供了更多有用的功能,可以為您簡(jiǎn)化流程,我們?cè)诘燃?jí)2部分回到這一內(nèi)容。
現(xiàn)在讓我們真正開(kāi)始做一開(kāi)始我們想做的事情:自定義一個(gè)場(chǎng)景控制類型。
2.3 添加一個(gè)場(chǎng)景控制類型
您可以完全忽略整個(gè)場(chǎng)景控制類型的概念,只需要在`init.lua`中輸入所有內(nèi)容。但是為了復(fù)用,我建議您定義它們的類型。
我們來(lái)看看要實(shí)現(xiàn)這樣一個(gè)目標(biāo)需要做什么:
- 指定場(chǎng)景控制類型的名稱(可以隨意指定?。?/p>
- 指定場(chǎng)景控制的參數(shù),我們使用幾個(gè)參數(shù),它們的參數(shù)名是什么
- 指定場(chǎng)景控制的行為
其中以上的三分之二都在單個(gè)函數(shù)內(nèi),其余部分是我們?cè)谏弦徽伦龅臇|西,現(xiàn)在我們開(kāi)始吧!
我們將創(chuàng)建一個(gè)簡(jiǎn)單的場(chǎng)景控制類型,它將讀取3個(gè)數(shù)字,并將軌道從它的當(dāng)前位置移動(dòng)到這3個(gè)指定的新位置。
發(fā)生了什么呢?
1. 我們首先定義了關(guān)鍵幀通道來(lái)添加我們的關(guān)鍵幀。
2. 我們定義了一個(gè)名為"mytypename"的場(chǎng)景控制類型,它有三個(gè)參數(shù)。這意味著我們的aff命令將如下所示:`scenecontrol(timing, mytypename, arg1, arg2, arg3`。
3. 我們通過(guò)一個(gè)函數(shù)定義了我們的Scenecontrol的行為。一般而言,這一函數(shù)針對(duì)譜面中的每個(gè)場(chǎng)景控制事件運(yùn)行。我們的函數(shù)會(huì)讀取這些指令,并采取相應(yīng)的行動(dòng),為我們的通道添加關(guān)鍵幀。
>如果您熟悉Arcade宏,那么這種模式應(yīng)該很熟悉!唯一的區(qū)別是我們接受了一個(gè)參數(shù)來(lái)讀取場(chǎng)景控制命令中的數(shù)據(jù)。
另外, `channel.valueAt(timing)`是讀取關(guān)鍵幀數(shù)值的很好用的API。
這個(gè)例子也很好的說(shuō)明了場(chǎng)景控制腳本的基本結(jié)構(gòu):
- 設(shè)置控制器
- 分配通道
- 定義場(chǎng)景控制的類型
現(xiàn)在我們成功定義了我們的類型,打開(kāi)Arcade的Scenecontrol窗口,您現(xiàn)在會(huì)看到"mytypename"出現(xiàn)在類型選擇的下拉框中,并且可以向其中添加對(duì)應(yīng)的事件。
順便說(shuō)一句,您可能會(huì)在場(chǎng)景控制編輯窗口的第一行上方看到小的文本,它們表示每列中參數(shù)的名稱,是的,您可以更改它!
`{"xpos", "ypos", "zpos"}` 創(chuàng)建一個(gè)字符串列表作為aff命令的傳入?yún)?shù)名。刷新腳本并再次檢查窗口!
>零參數(shù)的事件也是有效的,命令`scenecontrol(timing,mytypename);`對(duì)應(yīng)于下面這段代碼:
到目前位置,您應(yīng)該能夠復(fù)制產(chǎn)生大量效果了。讓我們更進(jìn)一步,了解`Scene`的來(lái)龍去脈!
2.4. Scene
`Scene`場(chǎng)景對(duì)象提供兩個(gè)函數(shù):獲取內(nèi)部控制器和創(chuàng)建新控制器。我們已經(jīng)在前面嘗試過(guò)了內(nèi)部控制器,但是也只有一種,篇幅限制問(wèn)題這里不對(duì)每種控制器進(jìn)行詳細(xì)介紹,請(qǐng)參閱文檔以獲取更多信息。
想要了解您可以做什么,這里是所有的內(nèi)部控制器列表。
| 訪問(wèn)路徑 | 類 | 描述 |
| - | - | - |
| Scene.gameplayCamera | CameraController | 主攝像機(jī) |
| Scene.combo | TextController | 連擊文本 |
| Scene.score | TextController | 得分文本 |
| Scene.jacket | ImageController | Jacket(譯者注:曲繪圖片) |
| Scene.title | TextController | 曲名文本 |
| Scene.composer | TextController | 作曲家文本 |
| Scene.difficultyText | TextController | 難度文本 |
| Scene.difficultyBackground | ImageController | 難度文本背景圖片 |
| Scene.hud | CanvasController | 包含暫停按鈕的畫(huà)布 |
| Scene.pauseButton | ImageController | 暫停按鈕 |
| Scene.infoPanel | ImageController | 信息面板背景圖 |
| Scene.background | ImageController | 背景圖 |
| Scene.videoBackground | SpriteController | 視頻背景圖 |
| Scene.track | TrackController | 主軌道 |
| Scene.track.divideLine01 | SpriteController | 軌道劃分線0-1 |
| Scene.track.divideLine12 | SpriteController | 軌道劃分線1-2 |
| Scene.track.divideLine23 | SpriteController | 軌道劃分線2-3 |
| Scene.track.divideLine34 | SpriteController | 軌道劃分線3-4|
| Scene.track.divideLine45 | SpriteController | 軌道劃分線4-5 |
| Scene.track.divideLines | Table (of SpriteController) | 軌道劃分線組 |
| Scene.track.criticalLine0 | SpriteController | 0軌道判定線 |
| Scene.track.criticalLine1 | SpriteController | 1軌道判定線 |
| Scene.track.criticalLine2 | SpriteController | 2軌道判定線 |
| Scene.track.criticalLine3 | SpriteController | 3軌道判定線 |
| Scene.track.criticalLine4 | SpriteController | 4軌道判定線 |
| Scene.track.criticalLine5 | SpriteController | 5軌道判定線 |
| Scene.track.criticalLines | Table (of SpriteController) | 軌道判定線組 |
| Scene.track.extraL | SpriteController | 左側(cè)額外軌道(軌道0) |
| Scene.track.extraR | SpriteController | 右側(cè)額外軌道(軌道5) |
| Scene.track.edgeExtraL | SpriteController | 左側(cè)軌道的額外邊 |
| Scene.track.edgeExtraR | SpriteController | 右側(cè)軌道的額外邊 |
| Scene.singleLineL | SpriteController | 左側(cè)Memory Archive線 |
| Scene.singleLineR | SpriteController | 右側(cè)Memory Archive線 |
| Scene.skyInputLine | SpriteController | 天空線 |
| Scene.skyInputLabel | SpriteController | 天空線標(biāo)簽 |
| Scene.darken | SpriteController | 變暗控制器(由內(nèi)部trackdisplay控制)|
> 您可能想知道ImageController和SpriteController有什么區(qū)別,簡(jiǎn)而言之:
> - SpriteController可以設(shè)置自己的排序圖層和排列順序,但是ImageController不行。
> - 您可以使用樞紐和錨點(diǎn)更輕松地控制ImageController的位置。ImageController的圖層和排列順序只能通過(guò)將它們?cè)O(shè)置為另一個(gè)畫(huà)布來(lái)更改。
然而,我們不再使用內(nèi)部控制器,而是嘗試在這里創(chuàng)建我們自己的控制器,并以這種方式探索不同類型的控制器。同樣,您需要`Scene`來(lái)實(shí)現(xiàn)這一點(diǎn)。
| 方法 | 返回類型 | 描述 |
| - | - | - |
| Scene.createSprite(string imgPath, string material = "default", bool newMaterialInstance = false) | SpriteController | 從路徑創(chuàng)建一個(gè)Sprite對(duì)象,具有指定的材質(zhì) |
| Scene.createCanvas(bool worldSpace = false) | CanvasController | 創(chuàng)建一個(gè)畫(huà)布,以世界坐標(biāo)或屏幕坐標(biāo)展示 |
| Scene.createImage(string imgPath, string material = "default", bool newMaterialInstance = false) | ImageController | 從路徑創(chuàng)建一個(gè)Image對(duì)象,具有指定的材質(zhì) |
| Scene.createText(string font = "default", number fontSize = 40, number lineSpacing = 1, string alignment = "middlecenter", string material = "default") | ImageController | 從路徑創(chuàng)建一個(gè)Text對(duì)象,具有指定的材質(zhì) |
| Scene.createMesh(string objPath, string texturePath) | MeshController | 從.obj文件和紋理圖像中創(chuàng)建3D對(duì)象 |
| Scene.getNoteGroup(number group) | NoteGroupController | 獲取一個(gè)時(shí)間組的控制|
當(dāng)您看到參數(shù)中有`=`時(shí),如 `material = "default"`,意味著在這一位置參數(shù)有一個(gè)默認(rèn)值,您不必指定它。
您可以使用`material`參數(shù)來(lái)更改混合模式,以下是混合方式列表:
- default
- add
- colorburn
- darken
- difference
- exclusion
- fastadd
- fastdarken
- fastlighten
- fastmultiply
- fastscreen
- hardlight
- lighten
- linearburn
- lineardodge
- linearlight
- multiply
- overlay
- screen
- softlight
- subtract
- vividlight
`newMaterialInstance`在大多數(shù)情況下應(yīng)該都保留為`false`。如果您需要更改控制器的紋理偏移或者紋理紋理縮放,請(qǐng)將其設(shè)置為`true`。
考慮到這一點(diǎn),讓我們嘗試在場(chǎng)景中添加自定義的Sprite精靈。默認(rèn)情況下,精靈放置在“背景”層中,該層位于軌道所屬的下方,所以我們需要改變它才能看到別的東西。精靈的圖層可以隨時(shí)間改變,所以我們需要再次使用通道,但是這次我們需要使用的是`StringChannel`。
(譯者注:layer圖層和order順序是Unity中兩個(gè)不同的概念,可以簡(jiǎn)單理解為layer是圖層組,而order是一個(gè)圖層組中的先后順序,數(shù)值越大優(yōu)先級(jí)越高)
然后我們會(huì)在場(chǎng)景中看到:

可以隨意改變"test.img"來(lái)對(duì)應(yīng)您輸入的圖像文件名。
讓我們用圖像來(lái)嘗試一下,這次我們嘗試更改一下它的材質(zhì),將上述代碼更改為:
注意這次您需要指定圖像的高度和寬度,這是Sprite精靈和圖像之間的區(qū)別。另外需要調(diào)整混合模式來(lái)使得樣式盡量美觀,在這里我不得不將其改為了conflict側(cè),您可以自行調(diào)整其他的混合模式。

最后讓我們也創(chuàng)建一些文本:
如您所見(jiàn),字符串通道也可以設(shè)置關(guān)鍵幀,在這里,我們讓它在0ms時(shí)顯示"Hello",然后在1000ms時(shí)將自身更改為"World"。
>您還可以在字符串通道上使用緩動(dòng)!嘗試將其改為`addKey(0, "Hello", "so")`,然后看看會(huì)發(fā)生什么。
這是我們的結(jié)果:

這涵蓋了創(chuàng)建控制器時(shí)需要記住的最重要的事情,如果您想要查看每種類型控制器的可用屬性,請(qǐng)參閱API文檔。
2.5. Controllers & Channels - 等級(jí)2
> 等級(jí)2將教您如何在使用通道時(shí)節(jié)省大量的時(shí)間,您將了解不同類型的通道,以及如何將通道組合在一起以獲得各種效果。
讓我們首先考慮如何處理一個(gè)非常簡(jiǎn)單的效果:無(wú)限期地以正弦波模式來(lái)回移動(dòng)對(duì)象。我們的通道將如下所示:
(img)
手動(dòng)添加每個(gè)關(guān)鍵幀以實(shí)現(xiàn)此效果是完全可行的。實(shí)際上,要了解它需要做多少工作,讓我們來(lái)看一下執(zhí)行此操作的代碼。
該通道將以正弦波形式在-1和1之間持續(xù)震蕩,它雖然有效,但是我們可以做的更好。
實(shí)際上,API提供了除關(guān)鍵幀通道以外的*other*類型來(lái)幫助您,以上代碼可以縮短為:
您還可以使用一系列其他的通道,這是列表:
| 方法 | 類型 | 描述 |
| - | - | - |
| Channel.keyframe() | KeyChannel | 關(guān)鍵幀通道 |
| Channel.constant(value) | ValueChannel | 常數(shù)值通道 |
| Channel.random(min, max, seed = 0) | ValueChannel | 隨機(jī)值通道 |
| Channel.noise(frequency, min, max, offset = 0, octave = 1) | ValueChannel | 柏林噪聲通道 |
| Channel.sine(period, min, max, offset = 0) | ValueChannel | 正弦通道 |
| Channel.saw(string easing, period, min, max, offset = 0) | ValueChannel | 鋸齒波通道 |
| Channel.fft(freqBandMin, freqBandMax, min, max, smoothness = 0.1, scalar = 1) | ValueChannel | 指定頻率范圍內(nèi)當(dāng)前播放音頻的平均響度 |
| Channel.max(channelA, channelB) | ValueChannel | 返回兩個(gè)通道的最大值 |
| Channel.min(channelA, channelB) | ValueChannel | 返回兩個(gè)通道的最小值 |
| Channel.clamp(valueChannel, minChannel, maxChannel) | ValueChannel | 將valueChannel的值夾在兩個(gè)通道之間|
> FFT代表快速傅里葉變換,如果您感興趣的話。
> 順便說(shuō)一下,默認(rèn)情況下,F(xiàn)FT通道使用256個(gè)頻段,但您可以使用`Channel.setGlobalFFTResolution(resolution)`進(jìn)行更改,分辨率必須是2次冪的整數(shù)。
一行代碼已經(jīng)夠好了,是嗎?是的,它確實(shí)如此。不過(guò)您還可以用不同的通道組合來(lái)實(shí)現(xiàn)無(wú)限可能的效果:
通過(guò)將`vibrate` 振動(dòng)通道和`dampen`阻尼通道相乘,我們限制了通道隨時(shí)間振動(dòng)的程度。當(dāng)`dampen`返回1時(shí)振動(dòng)最大,當(dāng)`dampen`返回0時(shí)不再振動(dòng),由于`dampen`的形狀是鋸齒波,我們得到了有趣的脈動(dòng)效果。
當(dāng)然,您也可以通過(guò)這種方式將關(guān)鍵幀和其他通道組合,這也為一種非常有效的技術(shù)開(kāi)辟了可能性,該技術(shù)實(shí)際上在內(nèi)部用于實(shí)現(xiàn)內(nèi)置的場(chǎng)景控制類型,讓我們來(lái)看一下其中的`enwidenlane`。
這一場(chǎng)景控制有如下功能:
- 將兩個(gè)額外軌道的不透明度從0改為255
- 將兩個(gè)額外軌道的不透明度從0改為255
- 將默認(rèn)的兩條軌道邊界從255改為0
- 將兩條額外的軌道邊界(軌道0和5)從0改為255
- 將軌道0-1和軌道4-5的分界線從0更改為255
- 將兩個(gè)額外軌道的位置從-100改為0
您可以手動(dòng)為所有內(nèi)容設(shè)置關(guān)鍵幀,這非常煩人并且需要大量的寫(xiě)作,相反,內(nèi)部發(fā)生的事情是這樣的:
如果您仍然不清楚這段代碼在做什么,這里有一個(gè)簡(jiǎn)單的解釋:
- 第二個(gè)參數(shù)"toggle"是一個(gè)0或1的值,我們將該值直接寫(xiě)入`enwidenLaneFactor`的通道。
- 我們需要更改的每個(gè)屬性都是主通道的一些變體,這些變體是直接在主通道上進(jìn)行計(jì)算的,而不是單獨(dú)的關(guān)鍵幀。
您可能還注意到了,我們正在使用`posY`和`alpha`在通道之間進(jìn)行算數(shù)運(yùn)算。在內(nèi)部,數(shù)字實(shí)際上被轉(zhuǎn)換為常量通道,所以這里只是一個(gè)簡(jiǎn)單的縮寫(xiě)。
請(qǐng)注意,此腳本實(shí)際上并不其作用,因?yàn)樵趦?nèi)部額外的軌道已經(jīng)將它的透明度設(shè)置為0,因此在它上面乘以任何數(shù)不會(huì)發(fā)生任何事情,因此,您應(yīng)該這樣做:
這里發(fā)生的是我們將內(nèi)部和本系統(tǒng)提供的API疊加在一起。對(duì)于顏色,高于255的值沒(méi)有什么不同,因此我們不必?fù)?dān)心。但是對(duì)于額外軌道的位置,我們不希望它超過(guò)0,以防同時(shí)使用兩種場(chǎng)景控制類型。我們可以使用`Channel.min` 來(lái)確保這一點(diǎn)。
當(dāng)然,如果您不關(guān)心使用內(nèi)部類型,那么
也是可以的.
所以這個(gè)lua腳本實(shí)際兼容的版本是:
本節(jié)到此結(jié)束,有了這些知識(shí),復(fù)雜的運(yùn)動(dòng)只需要幾行代碼!
額外的調(diào)試技巧:
您可以通過(guò)記錄來(lái)查看通道的組成,例如:
打開(kāi)錯(cuò)誤日志,您應(yīng)該看到以下結(jié)果:
這會(huì)幫您找出為什么控制效果沒(méi)有按照您的預(yù)期方式工作。
2.6. 使用note組來(lái)工作
(譯者注:這一章有些抽象??梢院?jiǎn)單理解為note組的場(chǎng)景控制可能會(huì)面臨多控制命令間相互覆蓋的問(wèn)題。因此在對(duì)note組設(shè)計(jì)場(chǎng)景控制函數(shù)時(shí),需要首先查詢是否已經(jīng)有正在執(zhí)行的動(dòng)畫(huà)命令。)
Note組的使用有些奇怪。定義控制器的工作流程,然后將它們鍵入到場(chǎng)景控制定義工作流程中,這并不能工作。原因很簡(jiǎn)單,我們不知道我們想要哪些控制器,因?yàn)槲覀儾恢牢覀兊氖录?huì)被放置在哪些時(shí)間組中。
> 您可能想知道為什么它被成為note group而不是timinggroup。簡(jiǎn)單的說(shuō),您不是在這里與時(shí)間事件進(jìn)行交互,而是與實(shí)際的音符本身進(jìn)行進(jìn)行交互。我選擇使用NoteGroup來(lái)更好的反映這一點(diǎn)。
唯一可以確定的方法是為每個(gè)場(chǎng)景控制命令查詢控制器。
這完全沒(méi)問(wèn)題,但是我們不能為每個(gè)場(chǎng)景控制命令創(chuàng)建一個(gè)新通道,因?yàn)檫@會(huì)覆蓋每個(gè)場(chǎng)景控制命令的舊通道:
相反,我們需要一種方法來(lái)確定我們是否為note組創(chuàng)建過(guò)一個(gè)通道,如果沒(méi)有,則創(chuàng)建一個(gè)新通道。事實(shí)上,你可以使用lua代碼來(lái)實(shí)現(xiàn)這一點(diǎn)。但是這對(duì)每個(gè)通道和每個(gè)屬性都是非常笨重和繁瑣的。
這里我們引入新概念:通道命名。還記得您第一次使用通道時(shí),那里有一堆“未命名”嗎?這是每個(gè)通道的默認(rèn)名稱,您可以根據(jù)自己喜好更改通道名稱。
如果一個(gè)通道由多個(gè)通道組合而成,您可以使用 `.find(name)`將每個(gè)通道分開(kāi)以進(jìn)行編輯,讓我們看看它的實(shí)際效果:
combineChannel能夠從它的組件中搜索具有您想要的名稱的通道。此名稱也是目標(biāo)通道的本地名稱,因此您甚至不必?fù)?dān)心為每個(gè)屬性命名通道。
這使我們能夠做的是解決我們之前在note組中遇到的問(wèn)題。 讓我們嘗試在note組的屬性中找到我們的通道,如果它不存在,那么我們將創(chuàng)建一個(gè)新的并分配它。
始終為您的通道命名也是一個(gè)非常好的策略,因?yàn)樗兄谡{(diào)試。特別是如果您打算與其他人共享您的腳本。
2.7. 后期處理
后期是整個(gè)屏幕可見(jiàn)的效果,它們的范圍很廣:模糊屏幕、扭曲屏幕、添加暈影效果、使屏幕嘈雜、添加發(fā)光效果等。
老實(shí)說(shuō),我只是……復(fù)制了統(tǒng)一支持的所有內(nèi)容,并以 Channels 的形式對(duì)其進(jìn)行了包裝。所以我自己都不知道這里 80% 的參數(shù)是做什么的。 Unity 在這方面的文檔也很糟糕,所以你在這里大部分時(shí)間都是靠自己的。
話雖如此,如果您已經(jīng)掌握了 Channels,那么您就有 90% 的方法可以使用后期處理。唯一的區(qū)別是您必須從`PostProcessing` 對(duì)象中獲取控制器,并且您還必須單獨(dú)啟用每個(gè)參數(shù)才能使其生效(因?yàn)閱⒂盟鼈儠?huì)對(duì)性能產(chǎn)生巨大影響)
每個(gè)后期處理控制器還可以具有不隨時(shí)間改變的屬性。我不會(huì)演示它們,因?yàn)樗鼈兯坪醵紱](méi)有用,但是如果您好奇,請(qǐng)隨時(shí)查看文檔以獲取更多詳細(xì)信息。
這是一個(gè)演示,可能是所有這些中最有用的后期處理效果,顏色分級(jí):
這是結(jié)果:

2.8. 一些其他的細(xì)節(jié)
這些都是你應(yīng)該知道的小細(xì)節(jié),但不足以保證整個(gè)部分的內(nèi)容。
注意事項(xiàng)
1. 相機(jī)在aff場(chǎng)景命令和Scenecontrol API中的配合有很大不同!
2. 所有文件路徑都是相對(duì)于 *`Scenecontrol` 文件夾*,而不是相對(duì)于運(yùn)行腳本
> 例如,如果在您的 `init.lua` 腳本中,您引用了腳本 `folder/other_script.lua`,并且在 `other_script.lua` 中,您嘗試使用路徑 `image.jpg` 創(chuàng)建一個(gè)精靈,實(shí)際文件路徑應(yīng)位于 `Scenecontrol/image.jpg` 而不是 `Scenecontrol/folder/image.jpg`
3. 在為精靈、圖像和文本選擇材質(zhì)時(shí),請(qǐng)注意,任何不以 `fast` 開(kāi)頭的東西都會(huì)嚴(yán)重影響性能,尤其是在低端硬件上。
提示
1. 對(duì)于那些熟悉宏的人。 `Event` 和 `Context` 對(duì)象可用。我不知道為什么需要`Event`,但這是同樣開(kāi)放使用的。
2. 除了 `log`,`notify` 也是一個(gè)選項(xiàng),它會(huì)在 toast 通知上顯示一條消息。
3. 您可以隨時(shí)使用 `log(channel.valueAt(timing))` 獲取任何時(shí)間點(diǎn)的值。這對(duì)于計(jì)算場(chǎng)景中對(duì)象的坐標(biāo)也很有用。
4.您可以通過(guò)`Context.availableFonts`獲取所有有效安裝字體的列表。但是,僅將其用于調(diào)試,并且不要將其包含在實(shí)際腳本中。
5. 除非您確實(shí)打算將變量設(shè)為全局變量,否則請(qǐng)始終使用 `local`。
下一步是什么?
恭喜您完成了關(guān)于新的場(chǎng)景控制 API 的本教程!
您現(xiàn)在應(yīng)該有足夠的知識(shí)來(lái)有效地使用參考文檔,該文檔將詳細(xì)說(shuō)明 API 的所有內(nèi)容,供您在編寫(xiě)自己的腳本時(shí)參考。 [請(qǐng)?jiān)谶@里查看](https://github.com/Tempestissiman/ArcadeScenecontrol/wiki)
希望您玩得開(kāi)心!