कोई मॉब शायद ही कभी सिर्फ़ एक animation चलाता है। हमारा Ruby golem खड़े होकर हल्का-हल्का झूलेगा, चलने पर walk करेगा, और दुश्मन दिखते ही अपनी मुट्ठियाँ उठा लेगा। एक animation controller तय करता है कि इस वक्त इनमें से कौन-सा चलेगा।
यह गाइड Entity animations पर आधारित है। अगर आपने अभी तक कोई animation नहीं बनाया है, तो पहले वह पढ़ें।
फ़ाइलें
RP/
animations/
ruby_golem.animation.json
animation_controllers/
ruby_golem.animation_controllers.json
entity/
ruby_golem.entity.jsonइसे कमरों के एक सेट की तरह सोचें
Controller states का एक सेट है। हर state को एक कमरा समझें:
- मॉब हमेशा ठीक एक कमरे में होता है।
- हर कमरे में animations की एक लिस्ट होती है, जो मॉब के अंदर रहने तक चलते हैं।
- हर कमरे में दरवाज़े (transitions) होते हैं। हर दरवाज़े पर एक Molang जाँच लगी होती है। जब जाँच true होती है, तो मॉब चलकर दूसरे कमरे में चला जाता है।
शुरुआत में हमारे golem के दो कमरे हैं: idle और walking।
कदम 1: idle और walk
Controller फ़ाइलें रिसोर्स पैक के animation_controllers फ़ोल्डर में जाती हैं:
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.ruby_golem.move": {
"initial_state": "idle",
"states": {
"idle": {
"animations": ["idle"],
"transitions": [
{ "walking": "query.modified_move_speed > 0.1" }
],
"blend_transition": 0.2
},
"walking": {
"animations": ["walk"],
"transitions": [
{ "idle": "query.modified_move_speed < 0.05" }
],
"blend_transition": 0.2
}
}
}
}
}इसे ऐसे पढ़ें:
- Golem
idleमें शुरू होता है औरidleanimation चलाता है। - जैसे ही उसकी speed 0.1 से ऊपर जाती है, वह
walkingमें चला जाता है और उसकी जगहwalkचलाता है। - जब वह 0.05 से नीचे धीमा होता है, तो वापस
idleमें आ जाता है। - हर बदलाव 0.2 सेकंड में धीरे-धीरे होता है, ताकि पैर झटके से न बदलें।
animations के अंदर लिखे नाम client entity के छोटे नाम (nicknames) हैं, लंबे animation. वाले नाम नहीं। इसके बारे में कदम 2 में और जानेंगे।
जानबूझकर दो अलग नंबर
अंदर जाने का रास्ता (> 0.1) और बाहर आने का रास्ता (< 0.05) अलग-अलग नंबर इस्तेमाल करते हैं। अगर दोनों एक जैसे होते, तो ठीक उसी speed पर चलता golem हर frame में कमरे बदल सकता था और काँपता हुआ दिखता।
Controller की fields
| Field | यह क्या करती है |
|---|---|
initial_state | वह state जिसमें मॉब शुरू होता है। इसे छोड़ दें तो गेम default नाम की state ढूँढता है। |
states | सारी states, नाम के साथ। |
Controller के नाम controller.animation. से शुरू होते हैं। एक अच्छा pattern है controller.animation.<mob>.<job>, जैसे controller.animation.ruby_golem.move।
State के अंदर
| Field | यह क्या करती है |
|---|---|
animations | इस state में क्या चलता है। छोटे नाम, या blend के साथ छोटे नाम। |
transitions | इस state से बाहर जाने के दरवाज़े, क्रम से जाँचे जाते हैं। |
blend_transition | इस state से अगली state में धीरे-धीरे बदलने के सेकंड। |
blend_via_shortest_path | true करने पर blend के दौरान bones छोटे रास्ते से घूमती हैं। |
on_entry | मॉब के state में आने पर एक बार चलने वाली चीज़ें। |
on_exit | मॉब के state से निकलने पर एक बार चलने वाली चीज़ें। |
variables | इस state के लिए निकाली गई वैल्यू, नीचे देखें। |
particle_effects | इस state में रहते हुए दिखने वाले particles। |
sound_effects | इस state में आने पर बजने वाली साउंड। |
Particles और साउंड Animation events में समझाए गए हैं।
Transitions
transitions एक लिस्ट है। हर entry में एक key (जिस state में जाना है) और एक Molang जाँच होती है:
"transitions": [
{ "alert": "query.has_target" },
{ "swimming": "query.is_in_water" },
{ "idle": "query.modified_move_speed < 0.05" }
]- जाँचें ऊपर से नीचे चलती हैं। जो पहली true होती है, वही जीतती है।
- हर frame में सिर्फ़ एक transition होता है।
- अगर कोई भी true नहीं है, तो मॉब जहाँ है वहीं रहता है।
इसलिए सबसे ज़रूरी दरवाज़ा सबसे पहले रखें। यहाँ दुश्मन को देख लेना बाकी सब पर भारी है।
State के अंदर blending
एक state एक साथ कई animations चला सकती है। हर एक की एक blend वैल्यू हो सकती है, बिल्कुल scripts.animate की तरह:
"walking": {
"animations": [
"idle",
{ "walk": "query.modified_move_speed" }
]
}धीमा golem अपने झूलने के ऊपर थोड़ा-सा walk दिखाता है। तेज़ golem पूरा walk दिखाता है।
कदम 2: इसे मॉब से जोड़ें
Controller को client entity के animations map में लिखा जाता है, बिल्कुल एक animation की तरह। फिर आप उसे scripts.animate से चलाते हैं:
"animations": {
"idle": "animation.ruby_golem.idle",
"walk": "animation.ruby_golem.walk",
"fists_up": "animation.ruby_golem.fists_up",
"look_at_target": "animation.common.look_at_target",
"move_controller": "controller.animation.ruby_golem.move"
},
"scripts": {
"animate": [
"look_at_target",
"move_controller"
]
}ध्यान दें कि idle और walk अब animate में नहीं हैं। अब इन्हें controller चलाता है। अगर आप इन्हें वहाँ छोड़ देंगे, तो ये दो बार चलेंगे।
आप कई controllers साथ-साथ चला सकते हैं। हर एक अपनी current state खुद रखता है। एक आम setup है: पैरों और शरीर के लिए एक controller, और बाँहों के लिए दूसरा।
कदम 3: एक alert state
चलिए golem को target मिलने पर मुट्ठियाँ उठाने वाला बनाते हैं। एक तीसरी state जोड़ें और बाकी दोनों states से उस तक एक दरवाज़ा:
"states": {
"idle": {
"animations": ["idle"],
"transitions": [
{ "alert": "query.has_target" },
{ "walking": "query.modified_move_speed > 0.1" }
],
"blend_transition": 0.2
},
"walking": {
"animations": ["walk"],
"transitions": [
{ "alert": "query.has_target" },
{ "idle": "query.modified_move_speed < 0.05" }
],
"blend_transition": 0.2
},
"alert": {
"animations": [
"fists_up",
{ "walk": "query.modified_move_speed" }
],
"transitions": [
{ "idle": "!query.has_target" }
],
"blend_transition": 0.3
}
}alert में golem अपनी मुट्ठियाँ ऊपर रखता है और आपका पीछा करते हुए चलता भी रहता है।
किसी animation के खत्म होने का इंतज़ार
कुछ animations एक बार, शुरू से आखिर तक चलने चाहिए, जैसे दहाड़ (roar)। इसमें दो queries मदद करती हैं:
| Query | कब true होती है |
|---|---|
query.all_animations_finished | State का हर animation अपने आखिर तक पहुँच चुका है |
query.any_animation_finished | उनमें से कम से कम एक अपने आखिर तक पहुँच चुका है |
"roar": {
"animations": ["roar"],
"transitions": [
{ "alert": "query.all_animations_finished" }
]
}ये सिर्फ़ उन animations के लिए काम करती हैं जो loop नहीं होते। Loop होने वाला animation कभी खत्म नहीं होता।
on_entry और on_exit
on_entry तब एक बार चलता है जब मॉब किसी state में आता है, और on_exit तब एक बार चलता है जब वह उससे निकलता है। रिसोर्स पैक में ये Molang चलाते हैं, जो variables सेट करने के काम आता है:
"alert": {
"on_entry": ["variable.times_alerted = (variable.times_alerted ?? 0) + 1;"],
"on_exit": ["variable.calm_since = query.life_time;"],
"animations": ["fists_up"],
"transitions": [{ "idle": "!query.has_target" }]
}बिहेवियर पैक में यही लिस्टें कमांड और entity events भी चला सकती हैं। Animation events देखें।
State variables
एक state variables से अपनी खुद की वैल्यू निकाल सकती है। इसका सबसे काम का हिस्सा है remap_curve: यह नंबरों की एक range को दूसरी range में बदल देता है।
"walking": {
"variables": {
"swing": {
"input": "query.modified_move_speed",
"remap_curve": {
"0.0": 0.3,
"1.0": 1.0
}
}
},
"animations": [{ "walk": "variable.swing" }]
}जब speed 0 होती है, तो variable.swing 0.3 होता है। जब speed 1 होती है, तो यह 1.0 होता है। बीच में गेम एक सीधी लाइन खींचता है। इसलिए धीमा golem भी थोड़ा-सा walk दिखाता है।
जब कुछ गड़बड़ हो
| आपको क्या दिखता है | सबसे संभावित वजह |
|---|---|
| कुछ भी नहीं चलता | Controller animations में है लेकिन scripts.animate में नहीं |
| कोई animation दुगनी ताकत से चलता है | वह scripts.animate में भी है और किसी controller state में भी |
| मॉब किसी state में अटक जाता है | उससे बाहर का कोई भी transition कभी true नहीं होता। उसके दरवाज़ों का Molang जाँचें |
| एक बार चलने वाला animation कभी खत्म नहीं होता | उसमें "loop": true है, इसलिए all_animations_finished कभी true नहीं होता |
| मॉब दो states के बीच झिलमिलाता है | अंदर और बाहर की जाँचें आपस में overlap करती हैं। दो अलग नंबर इस्तेमाल करें |
| Content Log कहता है कि कोई state नहीं मिली | कोई transition ऐसे state नाम की ओर इशारा करता है जिसमें typo है |
ज़्यादा मदद Troubleshooting में है।
आगे क्या
- Render controllers से textures चुनें और मॉडल के हिस्से छिपाएँ।
- Animation events से साउंड, particles और कमांड चलाएँ।
- Molang गाइड में Molang की और तरकीबें सीखें।