Add-On 製作實體動畫

這篇文章承接上篇: Add-On 在遊戲中新增生物實體
要教大家如何為自訂實體製作「動作」
動作實際上就是一連串動畫(animations)組成。
學完這個,恭喜你就擁有Mine-Imator做動畫的基本觀念了。


動畫示例:



本篇繼續以神秘生物boku當例子。


     

    第一步:透過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"的資料夾,把檔案存進去。

    第二步:註冊動畫

    在資源包資料夾開啟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":{}後面加入藍色字的程式碼,這就是新增動畫。
    {
        "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現在已不需要)。

    開啟遊戲查看效果吧!

    設定動畫重複播放

    動畫為什麼只播放一次就停止了?
    輸出動畫前,可以按二下Blockbench的動畫名字,Loop mode點選"loop"再輸出。
    迴圈模式代表會重複播放,還有一個是播放完後,定格在最後一個關鍵畫格的選項。

    或者,在註冊實體的檔案,scipts:{}的"animate"部分直接填入動畫名稱,就會無條件開始時播放。
    如果要進一步的重複播放,參考動畫控制器。

    動畫控制器的狀態設定

    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重複執行遊戲內的指令

    使用演算法來製作動畫

    如果連走路這種簡單的動畫都要用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裡面,寫的不是畫格和座標,而是直接寫一條算式。如此一來可大幅減少麻煩。

    留言

    此網誌的熱門文章

    Minecraft基岩版多人連線教學: 方法一覽

    【詳細解說】什麼是Minecraft基岩版,跟Java版有什麼差?

    Minecraft基岩版安裝模組(Add-On)&資源包&光影教學