2018年6月7日 星期四

「傘之下」開發記錄—22

程式大致上說完了
會用「大致上」這個詞,是因為還有個BGM腳本未講w
但這個腳本,基本上只要貼張圖:
基本上也不用再補充甚麼了ww
(所以上篇文才說會有個小番外)

 ————分隔線————

那麼,今次主題其實是BGM
遊戲裡的BGM和部分音效也是我自己製作的
雖然我在音樂方面算不上厲害(甚至比我的程式還爛w),但做下來還是有點心得

先來聽聽遊戲中的音樂……
呀,其實音樂現時只是寫好樂譜,還沒混音,所以聽起來會很生硬。
打個比方,就是只畫完線稿還沒上色_(:3」
嘛不過畢竟是開發記錄,不完美的東西也要po就是w:

. Title裡播放的Opening
 
我自己作曲時,通常會先想像一個情景,然後盡量用旋律去描述那個畫面
Opening的情景,是「在草原上踏出腳本,看到豁然開朗的景色。帶出『踏上旅程』的感覺」
然後之後會想玩點花樣:隨著主角的夥伴增加,Opening的樂器就越來越多

在這裡先補充一點,設定上,每個角色都有他的代表樂器。卡尼是鋼琴白鍵;雅蘿是提琴
所以遊戲一開始,都會以鋼琴為主,提琴為副——這是理論上的說法w
Opening現時只有鋼琴,是因為我來不及寫提琴的部分_(:3」
沒其他理由了((結案
嘛不過現在清新一點的風格也不太壞吧((自己說



接著是遊戲關卡裡的音樂:

 .一般場景裡的BGM
遊戲的開頭,是以「熟悉操作」來設計的
除了有「開關雨傘」的教學外,更想讓玩家無意識地熟悉跳躍距離(所以設計了不少平台讓玩家跳過去)
也因此,這裡的BGM加入了一點「彈跳感」
只不過太彈跳的話,和我想給予的感覺不一樣,所以加了支長笛下去中和一下
其實原本是想用小提琴的,但小提琴音色沒調過的話會很恐佈
恐佈到我想砸電腦(((゚д゚)))
所以最後還是長笛好www



最後一首是打Boss的BGM:

.Boss戰
因為Boss戰氣氛較為激昂,這裡套上小提琴比較沒問題owob
這裡整首曲子都是在描述Boss的動作行為
原本Boss的動作配合音樂來移動的,但因為節奏太快,玩家很難打中Boss(尤其不太擅於動作遊戲的玩家)
因此在校內展之後,就把Boss的動作間隔調長,降低難易度。BGM也就沒法配合了
不過說回來,在展場這麼吵的地方,其實很難注意到BGM就是www

現時遊戲內就這三首樂曲
和原本預定的五首還有段距離Orz
畢製的時候就是很容易企劃發太大,東西都來不及做有點遺憾
但這就當作是一個重新審視自己能力的經驗吧/

2018年6月4日 星期一

「傘之下」開發記錄—21

這次可以說是最後一篇關於程式的心得(之後還會有篇番外(?))
所有主要的系統架構都稍為講過一下,剩下的就是「Title」了
遊戲的Title長這樣,主要有三個選項供玩家選擇
當按下「上下方向鍵」後,箭頭位置亦會跟著移動


這裡的寫法,是用一個 int 來記下位置
當按下按鍵後, int 會有一個增減,而箭頭會根據 int 來移動自身座標
為免被玩家重覆按下按鍵,令到 int 亂掉,所以判斷式裡也限制 int 不能超過最大值


當確定位置後,玩家按下Enter時,會因應當前 int 來判斷執行甚麼動作
比如 int = 0(開始遊戲)時,會轉換場景


轉換場景時,因為每個遊戲都會有讀取時間
為免讀取期間畫面一直卡住,通常都會有個「讀取畫面」,讓玩家知道遊戲有在運行
這一段主要就是在顯示讀取進度,以及讓剪影跟著進度條跑


Title其實也是個不太複雜的架構,基本上這樣就講完了ww
然後程式方面的心得也一樣講完了ww ((灑花
沒想到寫著寫著居然寫到21篇 ((抖

2018年6月2日 星期六

「傘之下」開發記錄—20

最複雜的對話系統講完了,接下來是「最硬來」的劇情系統ww
現時的劇情系統,算是依附在對話系統下的
當對話進行到一定程度時,會把UI關掉,然後進入劇情動畫
這個「一定程度」的意思:
就是對話系統中有提到的,「對話後的動作」裡的選項(After Talk)


現時的做法,是先宣告一個 interface
然後 interface 裡再設立一個void (VoidEvent)
每當執行VoidEvent一次,就會自動執行對應動作
直接看上圖的例子,VoidEvent裡其實只有兩行
一個是 int 增加,另一個是呼叫下一個 void(會被 int 影響)
所以每按一次按鍵,就會執行不同的 void,達成一個劇情動畫流程

在每個 void裡,會寫入對應動作
比方說攝影機移動、生成特效之類的
……還有因為當初硬來,甚麼都沒設定好,所以還要控制對應的bool 參數w
大致上整個系統長這鬼樣子,只要和對話配合好的話,台面上還是不太有問題就是##


總而言之,這是個我自己都會寫到亂掉的系統XD
要優化的話,除了把參數都事先設定好外,應該還會把經常會用到的動作寫成一個void
比方說攝影機移動:
void CameraMove(Vector3 _target) {...}
很可能會寫成這樣,到時只要呼叫這個 void,並傳送一個座標過去就行了
作業上會快速方便許多

2018年6月1日 星期五

「傘之下」開發記錄—19


上一篇傳送對話資料後,會來到下面這組腳本
這腳本用來控制整個對話UI,包括UI的淡出淡入、文字和圖像切換等
在啟動對話UI後,會先讀取名字,然後判斷他是出現在上/下對話框
先假設現在使用上對話框。如果對話框沒有顯示,則讓對話框淡入(設定上,還沒有對話出現的對話框,在起始不會出現)
淡入後,會把名字和頭像進行切換。而「對話內容」由另一個void管理(下一張圖)
當上下對話框都已出現時,「沒在說話的角色對話框」會變為暗灰色
最後,在該段對話結束後,會判斷有沒有劇情或UI

更改對話內容的void裡,同樣會先判斷這是上/下對話框,之後才更改對話內容
另一個比較特別的是:Replace \\n , \n
先說一下,\n是用來自動換行的。但輸入這個語法後,Unity好像會自動把 \n 變成 \\n
所以這時需要手動把它調回來"XD(把 \\n 變回 \n)

不過說實在,以我自己的實力不可能知道這種東西的ww
那時在查資料時剛好看到別人的教學,就拿來用一下
可惜的是現在找不回那教學,沒辦法附上連結_(:3」

能切換相關資料,亦要防止對話互相干擾
因為現在的設定是按下相關按鍵(比如Z)後,對話就會跑下去
假如沒設限制,那在「對話一」時按下Z,「對話二」也會跟著跑。到時所有對話都會亂掉

現時遊戲中的防禦機制,會和遊戲物件的Component有關,所以先解說一下:
.控制對話UI用的腳本是掛在UI上的
.每段對話分開成不同GameObject,裡面掛著對話資料(上一篇文的腳本)和觸發對話腳本(等下會講到)

那麼,我是讓所有對話在一開始時都 inactive的。當觸發對話後,對應的物件才變成active
至於怎樣才做到這點,那就是宣告一個陣列來抓取子物件(GetChild)
每當要觸發對話時,腳本都會傳送自身子物件的位置,讓子物件啟動
宣告子物件位置的程式碼,則會在下幾張圖中說到

在那之前先繼續UI操控的部分:
當全部對話結束後,會呼叫ResetImage,把相關參數都重置(為免下次啟動UI時,會有殘留的資料出現)
然後對話框便淡出


UI控制大致上是這樣,然後今天就一氣呵成的「觸發對話」也說完
當玩家碰到觸發器後,會自動開啟對話UI
上圖的最後一句,就是用來傳送子物件位置的程式碼(用Debug.Log測試過,它會回傳一個數字(int))
除此之外,在觸發器腳本上,有設置一個下拉選單,選擇是哪一種觸發方式
現時分別設置成:
.對話完後就不會再重新對話
.同樣對話完就不會再觸發,但若對話裡內含劇情動畫的話,就要選擇這方式
.對話後離開範圍,再次踏進觸發範圍時會被重新觸發

目前主要用到的就這三種模式……其實還有寫一個「按下按鍵後才觸發對話」的模式,但因為美術部分未準備好,於是先把它拿掉_(:3」

最後啦,當在離開觸發範圍後,會回傳一個「-1」給UI的防禦機制
這個「-1」在void裡已設定好,代表讓GameObject inactive
與此同時,對話中的參數也重置,以免出Bug


 ……第一次寫這麼長w
認真來說,這個系統的複雜度應該可以分3、4篇
但那樣的話感覺會變成教學文——我還沒有實力這那種東西
腳本內一堆誤人子弟的程式,被看見就不好了XD
所以我一直以來都只是講講基本架構。一來用於整理自己思緒,二來……也或多或小希望這些邏輯概念刺激到別人啦 ((自肥ww

總之,感謝看到這裡
如無意外,程式架構的東西還有三篇就完了
還在想之後要不要寫美術心得_(:3」

2018年5月31日 星期四

「傘之下」開發記錄—18

發生Boss戰前,通常會段劇情動畫,營造一種Boss要來了Σ(*゚д゚ノ)ノ的感覺
所以接下來幾篇,就是要來說遊戲中的「對話」和「劇情」系統
這兩個系統,是這遊戲裡最複雜,同時也是最不滿意的東西ww
硬來的東西根本多到不能直視

嘛總之,先來看一下遊戲的對話長怎樣:
對話框是分成上下兩個,所以要操控的東西也變成兩倍……
不止啦www
為了避免各種bug,要調整的東西說不定是2.5倍
為甚麼當初要設定這種對話視窗呢?這就要問企劃
……咦,企劃就是我耶ww((自M

要寫成這個對話UI,除了要編寫怎麼控制外,還要建立一個基本的架構,來輸入對話資料:
在對話中,要更改的資料有:
.名字
.人物頭像
.說話內容
.要使用上/下對話框
.對話結束後的行動

這五個列為一個class,再在公開面版中隨時修改
然而,因為遊戲中有時會出現對話分支,因此再以一個class包住這個class "XDD
當出現分支時,選擇哪個class的資料

架構建立起來,再由別的腳本調用後,在面版中大概長這樣:
一個不太人性化的資料輸入版面w
有時亂到自己都不太懂Orz


Anyway,有架構後,就用另一個腳本來讀取資料
在腳本啟動時,會先偵察有沒有分支對話
沒有的話直接讀取對話資料,有的話則由其他腳本控制要讀第幾個分支
然後:
當按下對應按鍵時,會呼叫ClassChange
ClassChange內,則傳送「上/下對話框、名字、頭像、對話後動作」這四筆資料,給予TalkUI腳本(控制UI的腳本,會在下篇文提及)
最後再呼叫SayChange
SayChange內,會傳送對話內容給TalkUI腳本
但在傳送之前會有一個判斷式:有沒有超出對話行數
在腳本內宣告一個 int(SayNo)……SayNumber的簡寫啦不是另一意味上的SayNo  XD
當每讀取對話一次時,這個int就+1。假如SayNo大於對話行數時,就會自動跳到ClassChange,更改其餘四項資料——畢竟超出行數的意思,就是指該名角色暫時說完話
跳到ClassChange的同時SayNo變回零,同時CharacterNo+1。CharacterNo是用來偵察「有多少段對話」用的,和SayNo異曲同工
當CharacterNo超出「對話段數」時,則完結對話,呼叫ResetNumber
ResetNumber裡,除了把SayNo和CharacterNo重置外,一堆和對話(劇情)相關的參數也重置,並關閉對話視窗
因為在進行對話時要限制玩家移動
而且進行對話時可能會出現劇情……這部分也要限制
因此出現了一堆bool參數w

說了這麼多,這部分只是「傳送資料」而已
對話UI裡的更動,還需要另一個腳本協助才能達成
這部分就留在下篇吧ww

2018年5月30日 星期三

「傘之下」開發記錄—17

上一篇結尾是在講判斷Boss動作的bool
這次會貼上那段void,所以應該會更清晰一點
(沒貼在上篇,是因為在這裡的關聯性更大)

在進行判斷之前,要先講到為甚麼Boss會中止行動
當Boss受到玩家一般攻擊時,會進行防禦
在打了第一下之後,為免Boss被攻擊多下,多次觸發程式產生Bug,所以會取消攻擊判定
接著偵察被打的方位,以免防禦錯方向
防禦時會停止其他協程,然後呼叫反擊協程

反擊開始時,會設定攻擊強度(為了把玩家推開),同時更改攻擊範圍
最後則是呼叫void,繼續Boss的行動



除了一般攻擊外,Boss會被掉落的果實砸傷(或者說,Boss只會在受到果實攻擊時才會扣HP,一般攻擊時會完全防禦)
當被果實打中,會優先播放受傷動畫
然後和防禦反擊時一樣,呼叫重新行動的void


最後這個void,其實也不是甚麼厲害的東西www
就只是根據bool的開關,判斷呼叫哪個協程而已


Boss的所有行動大概就是這樣
是有些小細節的東西沒有貼出來啦,因為那些都是沒優化過硬來的東西(黑歷史)

最後再補充一下,上面幾張圖有看到個名為NextSkill的bool
那個……是沒用處的東西"XDD
因為BossAI是整個遊戲中第3個寫的腳本,是超早期的產物
雖然中途有優化過一次,但有些東西忘了刪掉_(:3」
你就知道我當初多亂來

2018年5月21日 星期一

「傘之下」開發記錄—16

小怪AI講完,當然要來個大Boss (`・ω・´)
然後因為Boss的程式太長,還是會分個兩篇就是

首先先說說Boss的攻擊模式
牠的主要攻擊為「打地板」和「高速旋轉」,這兩套動作之間的循環
兩套動作都是用協程計時,不同時間播放不同動作,組合起來才是一整套攻擊

打地板的部分:
.先是重擊地板時(攝影機同時晃動),攻擊判定範圍會增大
.果實從樹上掉下(果實自帶「可擊飛物品」腳本,以及一個控制動畫用腳本)
.接下來準備去下一組動作
(HitFloor和Rolling的bool在文末解說)


高速旋轉的部分:(Part1)
.Boss會在空間裡左右旋轉,為了避免旋轉時超出範圍,因此一開始先宣告好一個位置,用以旋轉後固定座標
.更改攻擊範圍,同時取消旋轉期間的被攻擊判定(以免被打中出Bug)
.把Boss的碰撞器更改為觸發器,重力也改為零。會這麼做,是因為用碰撞器的話,移動途中擊中玩家時會有一個「推擠」,Boss也就不能準確地移動到位置上
.把設定都弄好後,最後就讓Boss進行位移


高速旋轉的部分:(Part2)
.在旋轉途中,Boss會有一個「跌倒」動畫,這時再往前滑行一小段(這都是用時間或數值來調整,有沒有更人性化的調整方法現在還在測試)
.滑行停止後,Boss的位置固定在設置好的座標上
.恢復碰撞器及重力的數值,以及恢復被攻擊判定
.旋轉後要面對玩家,因此會有一個Flip的效果


兩套動作大致這樣,最後來講HitFloor和Rolling的bool
在設定上,Boss被一般攻擊打中時會進行防禦反擊(另一套動作),那時會停止「旋轉」和「打地板」的動作,當反擊後才重新回到這兩套動作循環裡
那這個「重新回到循環」,就是靠bool來決定
Rolling = true的時候,反擊後會切入「旋轉」的動作再次展開攻擊。反之亦然
所以當一套動作已經完成了的時候,就會開關對應的bool,讓Boss繼續行動