कंटेंट पर जाएँ
charmotion

Rive स्टेट मशीन: इनपुट, ट्रिगर और मूड

Charmotion टीम द्वारा · अपडेट:

गाइड का कवर इलस्ट्रेशन: Rive State Machine: Inputs, Triggers & Moods, Charmotion डेमो कैरेक्टर के साथ

Rive स्टेट मशीन एक .riv फ़ाइल के अंदर का graph है जो तय करता है कि कौन सा एनिमेशन कब चलेगा। स्टेट में एनिमेशन होते हैं, transitions उन्हें जोड़ते हैं, और transitions पर लगी conditions वे values पढ़ती हैं जो आपका code सेट करता है। इन values के लिए Rive अब Data Binding (view models) की सलाह देता है; पुराने नंबर, बूलियन और ट्रिगर इनपुट अब भी काम करते हैं।

मुख्य बातें

  • स्टेट में एनिमेशन होते हैं; conditions वाले transitions तय करते हैं कि उनके बीच कब जाना है।
  • इनपुट तीन तरह के होते हैं: number, boolean और ट्रिगर।
  • लगातार चलने वाले लूप के लिए numbers या booleans और वन-शॉट रिएक्शन (एक बार चलने वाला रिएक्शन) के लिए ट्रिगर इस्तेमाल करें।
  • इनपुट अब deprecated हैं और उनकी जगह Data Binding की सलाह दी जाती है, लेकिन मौजूदा फ़ाइलें काम करती रहती हैं।

Rive स्टेट मशीन क्या है?

स्टेट मशीन किसी Rive file की logic layer है। यह timeline एनिमेशन के ऊपर बैठती है और हर फ़्रेम पर एक सवाल का जवाब देती है: अभी क्या चलना चाहिए?

  • स्टेट में आमतौर पर एक ही एनिमेशन होता है, जैसे idle लूप, या कई एनिमेशन का blend।
  • Transitions स्टेट के बीच के तीर हैं। हर एक की एक duration हो सकती है, जिससे Rive जाने वाले और आने वाले एनिमेशन को cut करने के बजाय blend करता है।
  • Transitions पर लगी Conditions एनिमेशन के बाहर से वैल्यू पढ़ती हैं, जैसे "mood बराबर 5" या "success फ़ायर हुआ"।
  • खास स्टेट: Entry सबसे पहले चलता है, Any State से transition वहीं से फ़ायर हो सकता है जहाँ मशीन अभी है, और Exit किसी layer को खत्म करता है।
  • Layers की मदद से कई स्टेट ग्राफ़ एक साथ चल सकते हैं, जैसे एक layer पर शरीर की मूवमेंट और दूसरी पर पलक झपकना।

आपका ऐप कभी भी एनिमेशन को नाम से नहीं चलाता। वह वैल्यू बदलता है और स्टेट मशीन उस पर रिएक्ट करती है। इससे एनिमेशन का लॉजिक फ़ाइल के अंदर ही रहता है, जहाँ डिज़ाइनर बिना code बदले उसे ट्यून कर सकता है।

स्टेट मशीन settle भी हो सकती है: जब रनटाइम पता लगा लेता है कि आगे कुछ नहीं बदलेगा, तो वह आगे बढ़ना रोक देता है, जिससे स्थिर अंतिम स्टेट के लिए काम बचता है।

नंबर, बूलियन और ट्रिगर इनपुट क्या होते हैं?

इनपुट वह मूल तरीका है जिससे code स्टेट मशीन से बात करता है। ये तीन तरह के होते हैं:

प्रकारक्या रखता हैआम इस्तेमाल
Numberएक float जिसे आप सेट करते और पढ़ते हैंकई स्टेट में से चुनना, लेवल, प्रोग्रेस
Booleantrue या falseचालू/बंद स्टेट, जैसे hovered या muted
ट्रिगरएक पल का इवेंट जिसे आप फ़ायर करते हैंवन-शॉट रिएक्शन: success, error, tap

ट्रिगर बनाम बूलियन सबसे आम सवाल है। बूलियन तब तक true रहता है जब तक आप उसे false न करें, इसलिए यह लंबे समय तक रहने वाली स्थितियों के लिए सही है। ट्रिगर को वह transition इस्तेमाल कर लेता है जो उसे पढ़ता है, इसलिए वह एक बार फ़ायर होकर खुद रीसेट हो जाता है। जहाँ आप वरना बूलियन को true करके तुरंत false करते, वहाँ ट्रिगर इस्तेमाल करें।

कई परस्पर अलग लूप में से चुनने का सबसे साफ़ तरीका नंबर इनपुट है। 0 से 9 तक वैल्यू वाला एक mood नंबर उन दस बूलियन की जगह ले लेता है जिन्हें आपको खुद तालमेल में रखना पड़ता।

वेब पर legacy API stateMachineInputs() से इनपुट लौटाता है। ट्रिगर में fire() होता है; नंबर और बूलियन में value property होती है:

import { Rive } from "@rive-app/webgl2";

const r = new Rive({
  src: "/character.riv",
  canvas: document.querySelector("canvas"),
  stateMachine: "CharacterStateMachine",
  autoplay: true,
  onLoad: () => {
    r.resizeDrawingSurfaceToCanvas();
    const inputs = r.stateMachineInputs("CharacterStateMachine");
    const mood = inputs.find((i) => i.name === "mood");
    const success = inputs.find((i) => i.name === "success");
    mood.value = 5;   // loading loop
    success.fire();   // one-shot reaction
  },
});

इनपुट को onLoad के अंदर query करें; फ़ाइल लोड होने से पहले वे मौजूद नहीं होते। ध्यान दें कि एकवचन stateMachine option ने web runtime v2.41.0 में stateMachines की जगह ली है।

लूपिंग स्टेट और वन-शॉट ट्रिगर में क्या फ़र्क है?

ज़्यादातर इंटरैक्टिव कैरेक्टर को दो तरह की मोशन चाहिए:

  • लूप किसी चल रही स्थिति को दिखाते हैं: idle, loading, listening, sleeping। इन्हें तब तक चलना चाहिए जब तक स्थिति बनी रहे, इसलिए इन्हें एक स्थायी वैल्यू (नंबर या बूलियन) से चुना जाता है।
  • वन-शॉट किसी इवेंट को दिखाते हैं: पेमेंट सफल हुआ, अपलोड फ़ेल हुआ, यूज़र ने हाँ कहा। ये एक बार चलते हैं और फिर मौजूदा लूप पर लौट जाते हैं, इसलिए इन्हें ट्रिगर से फ़ायर किया जाता है।

आम वायरिंग यह है: Any State से हर वन-शॉट तक एक transition, जो उसके ट्रिगर पर निर्भर हो, और वन-शॉट के अंत में एक exit transition, जो मौजूदा नंबर वैल्यू से मेल खाते लूप पर लौटे। ऐसा करने पर आपका code लूप सेट करना और रिएक्शन फ़ायर करना अलग-अलग कर सकता है, बिना यह ट्रैक किए कि अभी क्या चल रहा है।

छह वन-शॉट रिएक्शन: success, error, yes, no, enter और exit
वन-शॉट रिएक्शन ट्रिगर से फ़ायर होते हैं और खत्म होने पर मौजूदा मूड पर लौट आते हैं।

असल इस्तेमाल में दो बातें मायने रखती हैं। पहली, लूप से लूप वाले transitions को छोटी blend duration दें ताकि मूड बदलना झटके से नहीं, स्मूद दिखे। दूसरी, तय करें कि लूप बदलने से वन-शॉट बीच में रुके या नहीं। आमतौर पर नहीं रुकना चाहिए: अगर कोई request पूरी होती है और आप उसी फ़्रेम में success फ़ायर करते हैं और मूड वापस idle पर सेट करते हैं, तब भी आप चाहेंगे कि पूरा success रिएक्शन चले।

क्या Rive स्टेट मशीन के इनपुट deprecated हैं?

हाँ। Rive ने स्टेट मशीन इनपुट और रनटाइम पर इवेंट सुनने को deprecate कर दिया है और उसकी जगह data binding को अपनाया है। उसके रनटाइम docs में अब इनपुट वाले पेज deprecation नोटिस से शुरू होते हैं: नए प्रोजेक्ट के लिए data binding इस्तेमाल करें और मौजूदा प्रोजेक्ट को माइग्रेट करने की योजना बनाएँ।

Deprecated का मतलब खराब होना नहीं है। Rive की migration guide कहती है कि मौजूदा फ़ाइलों को अपडेट करने की ज़रूरत नहीं है, और इनपुट व इवेंट पहले की तरह काम करते रहेंगे। हालाँकि सपोर्ट हर रनटाइम में अलग है:

  • Web, React, Android और Flutter: इनपुट API अभी भी काम करते हैं।
  • Apple: इनपुट सिर्फ़ legacy Apple runtime में काम करते हैं। नया Apple runtime केवल data binding सपोर्ट करता है।
  • React Native: Nitro runtime v0.5 में इनपुट methods के लिए warnings दिखाता है और v0.6 में उन्हें हटा देता है।

किसी फ़ाइल को माइग्रेट करने के लिए उसे Rive editor में खोलें, main menu (तीन लाइन वाला आइकन) से Convert Inputs to View Models चुनें, फिर अपने code को अपडेट करें ताकि वह इनपुट की जगह व्यू मॉडल पर वैल्यू सेट करे।

Rive data binding क्या है?

Data binding एक view model (editor में परिभाषित typed properties का सेट) को फ़ाइल की किसी भी चीज़ से जोड़ता है: स्टेट मशीन conditions, text, colors, positions। आपके code को एक व्यू मॉडल instance मिलता है और वह उसकी properties सेट करता है।

इनपुट की तुलना में view model properties ज़्यादा types सपोर्ट करती हैं। इनपुट सिर्फ़ numbers, booleans और ट्रिगर तक सीमित हैं; view models इनके अलावा strings, enums, colors, nested view models, lists, images और artboards भी जोड़ते हैं। Properties को observe भी किया जा सकता है, जिससे एनिमेशन वैल्यू वापस आपके code को बता सकता है।

वेब पर, इनपुट वाले उदाहरण का यही काम data binding से कुछ ऐसा दिखता है:

const r = new Rive({
  src: "/character.riv",
  canvas: document.querySelector("canvas"),
  stateMachine: "CharacterStateMachine",
  autoplay: true,
  autoBind: true,
  onLoad: () => {
    const vmi = r.viewModelInstance;
    vmi.number("mood").value = 5;
    vmi.trigger("success").trigger();
    vmi.number("mood").on((event) => console.log(event));
  },
});

autoBind: true के साथ रनटाइम आपके लिए default view model instance बनाता और bind करता है। यहाँ property names यह मानकर लिखे गए हैं कि फ़ाइल के व्यू मॉडल में mood और success properties हैं। जिस फ़ाइल में सिर्फ़ इनपुट हैं उसमें व्यू मॉडल नहीं होता, इसलिए यह code कुछ नहीं ढूँढ पाएगा; ऐसी फ़ाइलों के लिए इनपुट API इस्तेमाल करें।

Charmotion का मूड इनपुट स्टेट से कैसे जुड़ता है?

Charmotion files ऊपर बताए गए लूप-प्लस-ट्रिगर पैटर्न को फ़ॉलो करती हैं, जिसमें CharacterStateMachine नाम की स्टेट मशीन पर एक नंबर इनपुट और छह ट्रिगर होते हैं।

moodलूपmoodलूप
0idle5loading
1happy6listening
2wave7talking
3thinking8sleeping
4sad9attention

मूड बदलाव 220 ms में blend होते हैं। ट्रिगर success, error, yes, no, enter और exit हर एक वन-शॉट चलाते हैं और फिर जो भी मूड सेट है उस पर लौट जाते हैं। exit कैरेक्टर को तब तक छिपा देता है जब तक enter फ़ायर न हो। मूड बदलाव कभी किसी वन-शॉट को बीच में नहीं काटते। दूसरी मशीन, LaunchStateMachine, एक बार लॉन्च इंट्रो चलाती है और फिर idle में रहती है।

success: एक ट्रिगर जो एक बार चलता है, फिर मौजूदा मूड पर लौट आता है।

हर Charmotion file दोनों तरीकों के साथ आती है: Data Binding के लिए autoBind: true के साथ CharacterViewModelMachine चुनें और viewModelInstance.number("mood") सेट करें या viewModelInstance.trigger("success") फ़ायर करें, या default CharacterStateMachine चुनें और ऊपर वाला इनपुट API इस्तेमाल करें। दोनों मशीनों में वही 10 लूप और 6 वन-शॉट हैं।

अक्सर पूछे जाने वाले सवाल

Rive स्टेट मशीन से एनिमेशन कैसे बदलें?

वह वैल्यू बदलें जिसे स्टेट मशीन के transitions सुन रहे हैं। कोई नंबर या बूलियन इनपुट, या view model property सेट करें, और मेल खाता transition नए स्टेट पर चला जाएगा। आप एनिमेशन को नाम से नहीं बुलाते; वैल्यू बदलने पर क्या चलेगा, यह फ़ाइल की transition conditions तय करती हैं।

Rive में ट्रिगर और बूलियन में क्या फ़र्क है?

ट्रिगर एक बार फ़ायर होता है और किसी transition के इस्तेमाल करने के बाद खुद रीसेट हो जाता है, इसलिए यह success या tap जैसे वन-शॉट इवेंट के लिए सही है। बूलियन अपनी वैल्यू तब तक रखता है जब तक आप उसे न बदलें, इसलिए यह hovered या muted जैसी लंबी स्थितियों के लिए सही है। इवेंट के लिए ट्रिगर और स्टेट के लिए बूलियन इस्तेमाल करें।

क्या मुझे अपनी Rive files को data binding पर माइग्रेट करना ज़रूरी है?

नहीं, तुरंत नहीं। Rive के अनुसार इनपुट वाली मौजूदा फ़ाइलें काम करती रहेंगी। माइग्रेट तब करें जब आपको नया Apple runtime, React Native Nitro v0.6+ या ज़्यादा property types चाहिए हों। editor का Convert Inputs to View Models कमांड फ़ाइल वाला हिस्सा संभाल लेता है; उसके बाद आप अपना runtime code अपडेट करें।

मेरा code स्टेट मशीन इनपुट क्यों नहीं ढूँढ पा रहा?

आमतौर पर इसलिए कि फ़ाइल अभी पूरी लोड नहीं हुई, या कोई नाम बिल्कुल मेल नहीं खाता। इनपुट को onLoad callback में query करें, जाँचें कि आपने सही स्टेट मशीन नाम दिया है, और इनपुट नामों को अक्षर-दर-अक्षर मिलाएँ, case और spaces समेत। view models में बदली गई फ़ाइलें अब इनपुट expose नहीं करतीं।

इस गाइड से झटपट जवाब

स्रोत

संबंधित गाइड