這篇文章承接上篇: Add-On 在遊戲中新增生物實體
要教大家如何為自訂實體製作「動作」
動作實際上就是一連串動畫(animations)組成。
學完這個,恭喜你就擁有Mine-Imator做動畫的基本觀念了。
動畫示例:
本篇繼續以神秘生物boku當例子。
1. 透過Blockbench製作動畫#
我使用Blockbench製作了4種不同條件下會觸發的動畫(左側列表)。
分別是移動、耳朵擺動、攻擊、眼睛轉動。這些動畫不會同時播放,各自有其播放時機。
Blockbench按右上角的動畫切換到動畫區塊。
新增動畫請點選左上角的+號,創建動畫。
能改的只有最後面的屬性。預設叫做new,這一長串就是動畫的真正名字。
接下來點選右邊想要製作動畫的部位,例如我點選body,就會出現在下方的時間軸。 注意: 通常動畫是對操作骨骼,立方體不行。
時間軸上面的數字是「畫格」又稱幀,動畫的原理是告訴3D模型它在第幾秒要怎樣動作。
此範例中,首先在第0秒的位置按+新增一個畫格,這個代表原點,動作完全不變。
接著在第0.5秒按+新增一個畫格,body就會出現轉軸,我拉動設定X軸旋轉20度。
在第1秒,我設定X軸旋轉-20度。
基本動畫就完成了。動畫的總時長依最後一個畫格決定,此範例共1秒。
這裡提一下觀念,關於骨骼子母物件的問題。
上面的例子,可以看到boku的身體動了,手腳卻沒跟著轉? 因為沒有設定子母物件的關係。
Q: 如果想要「某個部位動的時候,其他部位也跟著動」應該怎麼做? 如果要製作關節,這點很重要。
A: 參考盔甲架的結構
盔甲架有一個叫做waist的bone,其餘所有的bone都放在這個bone下面,也就是成為它的子物件。 所以如果要製作這種連動,只要把一個bone塞到另一個bone下面就可以了。
這是boku原本的bone結構,各個bone互不干涉。
用滑鼠全拖進去body裡面,這樣就全部變成body的子物件。
再看一次剛才做的動畫,整個手腳都跟著轉了。
最後要匯出動畫,按上方選單,匯出動畫
在Add-On的資源包資料夾新增一個叫做"animations"的資料夾,把檔案存進去。
2. 在資源包註冊動畫#
開啟資源包資料夾,開啟entity
資料夾下的boku.json
,就是註冊實體的那個檔案。
注意format_version
為1.10.0
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "newmob:boku",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/boku"
},
"geometry": {
"default": "geometry.boku"
},
"render_controllers": [
"controller.render.newmob"
],
"spawn_egg": {
"texture": "spawn_boku",
"texture_index": 0
}
}
}
}
在geometry":{}
後面加入的"animations": {}
程式碼,這就是新增動畫。
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "newmob:boku",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/boku"
},
"geometry": {
"default": "geometry.boku"
},
"animations": {},
"scripts": {
"animate": []
},
"render_controllers": [
"controller.render.newmob"
],
"spawn_egg": {
"texture": "spawn_boku",
"texture_index": 0
}
}
}
}
animations
這一段,輸入以下內容:
"animations": {
"move": "animation.boku.new",
"move_controller": "controller.animation.boku.new"
},
我想製作移動時播放的動畫,第二行的"move"是簡短代號,用來表示後面那一長串用Blockbench做的時候輸出的字樣。
“move_controller"是動畫控制器,用來設定什麼時候播放該動畫的條件。前面同樣是簡短代號,後面接的就是以"controller.“開頭,然後再接上面的"animation.boku.new”。
註: 1.8.0以前動畫控制器是分開註冊,1.10.0之後就跟animations寫在一起了。
如果不做動畫控制器,等同該實體生成時就會直接無條件播放動畫;每個不同動畫的動畫控制器也都得個別設定。
接著移步到scripts":{}
,在"animate"
的括號裡面新增:
"scripts": {
"animate": [
"move_controller"
]
},
告訴系統,請渲染這個動畫。因為move動畫由動畫控制器控制,所以填寫move_controller。
因此資源包/entity/boku.json
全部會長這樣:
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "newmob:boku",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/boku"
},
"geometry": {
"default": "geometry.boku"
},
"animations": {
"move": "animation.boku.new",
"move_controller": "controller.animation.boku.new"
},
"scripts": {
"animate": [
"move_controller"
]
},
"render_controllers": [
"controller.render.newmob"
],
"spawn_egg": {
"texture": "spawn_boku",
"texture_index": 0
}
}
}
}
接著製作動畫控制器。在資源包新增animation_controllers
資料夾,裡面新增名為boku_controller.json
的檔案。
輸入:
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.boku.move": {
"states": {
//預設狀態
"default": {
"animations": [
{
//要播放的動畫 + 條件
"move": "query.modified_move_speed"
}
]
}
}
}
}
}
在"controller.animation.boku.move"
的"animations"
後面的陣列,填入的就是要執行的動畫。
{"moving": "query.modified_move_speed"}
這段的意思是說,當後面的條件為true,就播放"move"這個動畫。
query.modified_move_speed
這個是Molang語言,這裡用來偵測實體的移動速度,只要>0就會傳回true,代表實體在移動。
經過這一番努力後,你的資料夾應該有以下項目 (圖片中的materials現在已不需要)。
開啟遊戲查看效果吧!
3. 設定動畫重複播放#
動畫為什麼只播放一次就停止了?
輸出動畫前,可以按二下Blockbench的動畫名字,Loop mode點選"loop"再輸出。
迴圈模式代表會重複播放,還有一個是播放完後,定格在最後一個關鍵畫格的選項。
或者,在註冊實體的檔案,scipts:{}
的"animate"
部分直接填入動畫名稱,就會無條件開始時播放。
如果要進一步的重複播放,參考動畫控制器。
4. 動畫控制器的狀態設定#
state
是「狀態」,一個控制器下可以有多個states。
以原版資源包鐵巨人的controller為例子:
鐵巨人"states"
下有"default"
和"has_target"
二種狀態,"initial_state"
代表的是預設要載入哪個狀態。
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.iron_golem.move": {
"initial_state": "default",
"states": {
//初始狀態
"default": {
"animations": [
{
//要播放的動畫 + 條件
"walk": "query.modified_move_speed"
}
],
"transitions": [
//滿足後面的條件則轉場到另一個狀態(has_target)
{
"has_target": "query.has_target"
}
]
},
//has_target狀態
"has_target": {
"animations": [
{
//要播放的動畫 + 條件
"walk_to_target": "query.modified_move_speed"
}
],
"transitions": [
{
//滿足後面的條件則轉場到另一個狀態(default)
"default": "!query.has_target"
}
]
}
}
}
}
}
這二個狀態是互相切換的關係,也就是符合條件就會切換到另一種狀態。
在"default"
狀態中,有上面提到的,當移動時播放"walk"這個動畫。
於是你就看到了"transitions":{}
這段,這個叫做「轉場」。它跟"animations":{}
這段原理一樣,只要後面條件傳回true,就執行。 這裡的功用是切換狀態,如"query.has_target"
傳回true時就切到"has_target"
的狀態。
"has_target"
的狀態也有寫切換回"default"
狀態的條件。
如果條件是寫"1.0"的話,代表無條件執行。
states的應用是什麼? animation_controller可以放在行為包裡執行,做出假性「連閃器」 讓Add-on重複執行遊戲內的指令。
5. 使用演算法來製作動畫#
如果連走路這種簡單的動畫都要用Blockbench慢慢拉,你還能怎麼做?
使用三角函數來控制骨骼吧。
原版資源包中,豬牛羊的腳部動畫都是使用quadruped.animation.json
這個檔案,裡面長這樣:
{
"format_version": "1.8.0",
"animations": {
"animation.quadruped.walk": {
"anim_time_update": "query.modified_distance_moved",
"loop": true,
"bones": {
"leg0": {
"rotation": [
"math.cos(query.anim_time * 38.17) * 80.0",
0.0,
0.0
]
},
"leg1": {
"rotation": [
"math.cos(query.anim_time * 38.17) * -80.0",
0.0,
0.0
]
},
"leg2": {
"rotation": [
"math.cos(query.anim_time * 38.17) * -80.0",
0.0,
0.0
]
},
"leg3": {
"rotation": [
"math.cos(query.anim_time * 38.17) * 80.0",
0.0,
0.0
]
}
}
}
}
}
請跟Blockbench輸出的檔案作比較。
每個bone裡面,寫的不是畫格和座標,而是直接寫一條算式。如此一來可大幅減少麻煩。