Cave: शुरूआती मार्गदर्शिका

Back to Learn

Cave: प्रारंभिक मार्गदर्शिका

Lesson 13 of 19 • 25 XP

Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

अब समझते हैं कि Cave में कैरेक्टर और एनिमेशन कैसे काम करते हैं। एक कैरेक्टर सिर्फ एक 3D मॉडल नहीं होता जो लेवल में चलता है। असली गेम सेटअप में, यह आमतौर पर फिजिक्स, मूवमेंट लॉजिक, एक दृष्टिगत मेष, एक आर्मेचर, एनिमेशन, और कोड या Logic Bricks का संयोजन होता है जो तय करता है कि कौन सी एनिमेशन चलनी चाहिए।

इसे व्यवहारिक बनाने के लिए, हम Cave के स्टार्टर प्रोजेक्ट्स के डिफ़ॉल्ट Player टेम्प्लेट का मुख्य संदर्भ के रूप में उपयोग करेंगे। यदि आप Third Person Game या Top Down Game बनाते हैं, तो Cave एक ऐसा प्लेयर जनरेट करता है जो पहले से ही चलता है, एक दृश्य एनिमेटेड कैरेक्टर है, और बेसिक लोकोमOTION एनिमेशन चलाता है।

image.png

यह पाठ आपको दिखाएगा कि वह सेटअप कैसे व्यवस्थित है और आप Python से एनिमेशन को कैसे नियंत्रित कर सकते हैं।

आप सीखेंगे:

  • स्टार्टर Player टेम्प्लेट कैसे बना है।
  • क्यों दृश्य मेष रूट प्लेयर एंटिटी के बजाय एक चाइल्ड एंटिटी है।
  • Animation Component क्या करता है।
  • Python से animator कैसे प्राप्त करें (Logic Bricks के लिए भी समान लॉजिक लागू होता है)।
  • नाम से एनिमेशन कैसे चलाएं।
  • ब्लेंडिंग, लेयर्स, और बोन फिल्टर्स कैसे काम करते हैं।
  • एनिमेशन कॉलबैक्स और सॉकेट्स सिस्टम में कैसे फिट होते हैं।

Player टेम्प्लेट संरचना

स्टार्टर प्रोजेक्ट में, Player एक Entity Template है। इसका मतलब है कि प्लेयर सेटअप पुन: उपयोग योग्य है और कई सीन में रखा जा सकता है।

संरचना मोटे तौर पर इस प्रकार है:

image.png

सटीक चाइल्ड्स आपके प्रोजेक्ट विकल्पों के आधार पर भिन्न हो सकते हैं, लेकिन महत्वपूर्ण विचार यह है कि रूट Player एंटिटी गेमप्ले सेटअप का मालिक है, जबकि चाइल्ड Mesh एंटिटी दृश्य एनिमेटेड कैरेक्टर की।

स्टार्टर एनिमी भी इसी विचार का उपयोग करता है। एनिमी रूट एंटिटी के पास कैरेक्टर फिजिक्स और व्यवहार होता है, और उसका चाइल्ड Mesh एंटिटी दृश्य मेष और Animation Component रखता है।

रूट Player एंटिटी

रूट Player एंटिटी गेमप्ले कैरेक्टर का प्रतिनिधित्व करता है। इसमें आमतौर पर शामिल होते हैं:

  • एक Transform Component
  • एक Character Component
  • 플레이यर मूवमेंट, UI, एनिमेशन सहायक, और अन्य गेमप्ले लॉजिक के लिए Python Components।
  • स्वास्थ्य या वैकल्पिक व्यवहार सेटिंग्स जैसी प्रॉपर्टीज।
  • कैमरा, UI, दृश्य मेष, और हेल्पर ऑब्जेक्ट्स के लिए चाइल्ड्स।

Character Component विशेष रूप से महत्वपूर्ण है क्योंकि यह कैरेक्टर-शैली फिजिक्स को संभालता है: चलना, कूदना, टक्कर, ढलान, और दुनिया के खिलाफ मूवमेंट। इसका मतलब है कि रूट Player मुख्य रूप से गेमप्ले और फिजिक्स के लिए जिम्मेदार है।

Mesh चाइल्ड एंटिटी

प्लेयर टेम्प्लेट के अंदर, एक चाइल्ड एंटिटी है जिसका नाम Mesh है। इस चाइल्ड में आमतौर पर होते हैं:

  • एक Transform Component
  • एक या अधिक Mesh Components
  • एक Animation Component

Mesh Component कैरेक्टर को उसका दृश्य 3D मॉडल और मटेरियल देता है। अगर कैरेक्टर एक से अधिक मटेरियल का उपयोग करता है, तो Cave इसे कई Mesh Components के साथ दिखा सकता है, जैसा कि इम्पोर्टिंग लेसन में मल्टीमटेरियल नियम समझाया गया है।

Animation Component वह है जो आर्मेचर का मूल्यांकन करता है और एनिमेशन चलाता है।

सरल तरीके से:

एंटिटी मुख्य ज़िम्मेदारी
Player फिजिक्स, मूवमेंट, गेमप्ले लॉजिक, प्रॉपर्टीज।
Player -> Mesh दृश्य मॉडल, मटेरियल, आर्मेचर एनिमेशन।

यह पृथक्करण जान-बूझकर किया गया है।

Mesh क्यों चाइल्ड एंटिटी है

आप सोच सकते हैं कि मेष को सीधे रूट Player एंटिटी पर क्यों नहीं रखा गया है।

कारण यह है कि फिजिक्स कैरेक्टर और दृश्य एनिमेटेड कैरेक्टर को अक्सर अलग ट्रांसफॉर्म्स की आवश्यकता होती है।

रूट Player ट्रांसफॉर्म गेमप्ले शरीर का प्रतिनिधित्व करता है। यह वह चीज़ है जो दुनिया में घूमती है, दीवारों से टकराती है, और Character Component को रखती है। चाइल्ड Mesh ट्रांसफॉर्म दिखाता है कि कैरेक्टर कैसा दिखता है।

यह पृथक्करण कई स्थितियों में उपयोगी है:

  • मेष को फिजिक्स कैप्सूल की तुलना में अलग पैमाना चाहिए हो सकता है।
  • मेष को कैरेक्टर की टक्कर के साथ संरेखित करने के लिए छोटा ऑफसेट चाहिए हो सकता है।
  • मेष को मूवमेंट बॉडी से स्वतंत्र रूप से घुमाया जा सकता है
  • मेष को मूवमेंट दिशा की ओर देखना चाहिए जबकि रूट गेमप्ले ओरिएंटेशन बनाए रखता है।
  • मेष को सामने की ओर बने रहना चाहिए जबकि प्लेयर साइडवेज़ चलता है।

उदाहरण के लिए, कल्पना करें कि प्लेयर बाएं तरफ चल रहा है। यदि आपके पास सही "walk left" एनिमेशन है, तो आप चाहते हैं कि कैरेक्टर मेष सामने की ओर देखता रहे जबकि एनिमेशन साइडवेज़ मूवमेंट को संभालता है। लेकिन यदि आपके पास साइडवेज़ एनिमेशन नहीं है, तो आप चाहेंगे कि मेष बाएं की ओर घूमें ताकि कैरेक्टर दृश्य रूप से उस दिशा में चले।

दोनों मामले वैध हैं।

वे अलग-अलग ट्रांसफॉर्म्स की आवश्यकता रखते हैं:

ट्रांसफॉर्म नियंत्रित करता है
रूट Player ट्रांसफॉर्म फिजिक्स पोजीशन, गेमप्ले शरीर, दुनिया में मूवमेंट।
चाइल्ड Mesh ट्रांसफॉर्म दृश्य ओरिएंटेशन, पैमाना, ऑफसेट, एनिमेशन प्रस्तुति।

इसी कारण से स्टार्टर प्लेयर और एनिमी एनिमेटेड मेष को चाइल्ड एंटिटी के रूप में रखते हैं।

Animation Component क्या करता है

Animation Component मुख्य घटक है जिसका उपयोग एंटिटी पर स्केलेटल एनिमेशन चलाने के लिए किया जाता है।

इसे चाहिए:

  • एक Armature
  • एक डिफ़ॉल्ट Animation
  • उसी एंटिटी पर वैध Mesh Component (या कई) होना चाहिए।

आर्मेचर कंकाल को परिभाषित करता है। एनिमेशन बताती है कि वह कंकाल समय के साथ कैसे चलता है। Animation Component अंतिम एनिमेटेड पोज़ को मूल्यांकन करता है और इसे दृश्य कैरेक्टर पर लागू करता है।

डिफ़ॉल्ट स्टार्टर प्लेयर में, Mesh चाइल्ड निम्नलिखित का उपयोग करता है:

  • Proto Mesh
  • Proto Mat
  • Proto Armature
  • p-idle डिफ़ॉल्ट एनिमेशन के रूप में (idle animation)

वे स्टार्टर एसेट्स आपको तुरंत कार्यशील एनिमेटेड कैरेक्टर जांचने देते हैं।

Armatures, Animations, और Retargeting

  • Armature कैरेक्टर की कंकाल है। यह हड्डियों को समाहित करता है जिनका मेष पालन करता है।
  • Animation समय के साथ हड्डियों की गति को संग्रहीत करता है।

Animation Component इन भागों को जोड़ता है:

भाग अर्थ
मेष दृश्य कैरेक्टर मॉडल।
आर्मेचर कैरेक्टर के अंदर कंकाल।
एनिमेशन गति, जैसे idle, walk, run, या fall।
Animation Component वह कॉम्पोनेंट जो एंटिटी पर एनिमेशन चलाता है।

Cave संभव होने पर एनिमेशन को रिटारगेट भी कर सकता है। यदि चल रही एनिमेशन एक अलग संगत आर्मेचर की है, तो Animation Component उस गति को वर्तमान आर्मेचर पर लागू करने के लिए रिटारगेटिंग का उपयोग कर सकता है।

रिटारगेटिंग उपयोगी है जब आप संगत कैरेक्टर्स के बीच एनिमेशन पुन: उपयोग करना चाहते हैं, लेकिन यह अभी भी आयात किए गए रिग की गुणवत्ता और संगतता पर निर्भर करता है। यदि एनिमेशन मुड़ी हुई, ऑफसेट या अजीब लगती है, तो स्रोत रिग, आयातित आर्मेचर, और रिटारगेटिंग सेटअप की जांच करें।


Python से Animator प्राप्त करना

अब देखते हैं कि हम लॉजिक के माध्यम से कैरेक्टर्स को कैसे एनिमेट कर सकते हैं।

Cave प्रोजेक्ट्स में, यह आम प्रथा है कि प्लेयर गेमप्ले लॉजिक रूट Player एंटिटी पर रखा जाए, फिर उस कोड से Mesh चाइल्ड तक पहुंचा जाए। डिफ़ॉल्ट स्टार्टर स्क्रिप्ट इस विचार का पालन करती हैं।

यह मूल पैटर्न है:

import cave

class PlayerAnimationExample(cave.Component):
    def start(self, scene: cave.Scene):
        self.mesh : cave.Entity = self.entity.getChild("Mesh")
        self.animator : cave.AnimationComponent = self.mesh.get("Animation")

    def update(self):
        # उदाहरण: idle एनिमेशन चलाना।
        self.animator.playByName("p-idle", blend=0.2, loop=True)

इस उदाहरण में:

  • self.entity रूट Player एंटिटी है।
  • getChild("Mesh") दृश्य चाइल्ड एंटिटी ढूंढता है।
  • self.mesh.get("Animation") Animation Component प्राप्त करता है।
  • वेरिएबल को animator कहा जाता है, जो Cave स्क्रिप्ट्स में सामान्य नामांकन प्रथा है।
  • playByName(...) नाम से एनिमेशन एसेट चलाता है।

यह वह मूल कनेक्शन है जिसकी आपको कोड के माध्यम से एनिमेशन नियंत्रित करने से पहले आवश्यकता होती है।

नाम से एनिमेशन चलाना

सबसे आम तरीका जो आप उपयोग करेंगे वह है playByName

इसका मूल उपयोग इस तरह दिखता है:

self.animator.playByName("p-walk", blend=0.2, loop=True)

महत्वपूर्ण पैरामीटर हैं:

पैरामीटर अर्थ
anim चलाने के लिए एनिमेशन एसेट का नाम।
blend सेकंड में, Cave को नई एनिमेशन में ब्लेंड करने में कितना समय लगे।
loop क्या एनिमेशन दोहराई जानी चाहिए।
layer कौन सी एनिमेशन लेयर एनिमेशन चलाएगी।

उदाहरण:

self.animator.playByName("p-idle", blend=0.2, loop=True)
self.animator.playByName("p-walk", blend=0.2, loop=True)
self.animator.playByName("p-run", blend=0.2, loop=True)
self.animator.playByName("p-fall", blend=0.2, loop=True)

ये वही कॉल्स हैं जो डिफ़ॉल्ट प्लेयर और एनिमी स्क्रिप्ट्स उपयोग करते हैं।

एक सरल लोकोमOTION उदाहरण

एक आम प्लेयर एनिमेशन सेटअप इस प्रकार है:

  • कैरेक्टर खड़ा होने पर idle चलाएं।
  • कैरेक्टर चलने पर walk चलाएं।
  • कैरेक्टर दौड़ते समय run चलाएं।
  • कैरेक्टर जमीन पर नहीं होने पर fall चलाएं।

यहाँ एक सरलीकृत उदाहरण है:

import cave

class SimplePlayerAnimator(cave.Component):
    def start(self, scene: cave.Scene):
        self.character : cave.CharacterComponent = self.entity.get("Character")

        self.mesh : cave.Entity = self.entity.getChild("Mesh")
        self.meshTransform : cave.TransformComponent = self.mesh.getTransform() if self.mesh else None
        self.animator      : cave.AnimationComponent = self.mesh.get("Animation") if self.mesh else None

    def update(self):
        if self.animator is None or self.character is None:
            return

        direction = self.character.getWalkDirection()
        isMoving = direction.length() > 0
        isRunning = False # इसे अपनी इनपुट या गेमप्ले कंडी션 से प्रतिस्थापित करें।

if self.character.onGround():
            if isMoving:
                if isRunning:
                    self.animator.playByName("p-run", blend=0.2, loop=True)
                else:
                    self.animator.playByName("p-walk", blend=0.2, loop=True)
            else:
                self.animator.playByName("p-idle", blend=0.2, loop=True)
        else:
            self.animator.playByName("p-fall", blend=0.2, loop=True)

यह उदाहरण जानबूझकर सरल है। असली स्टार्टर कंट्रोलर इनपुट, मूवमेंट दिशा, जंपिंग, वैकल्पिक पॉइंट-एंड-क्लिक व्यवहार, और मेष रोटेशन भी संभालता है, लेकिन एनीमेशन की अवधारणा यही है।

मूवमेंट की दिशा की ओर मेष को घुमाना

क्योंकि दृश्य Mesh एंटीटी की अपनी ट्रांसफॉर्म होती है, आप इसे रूट Player से अलग से घुमा सकते हैं।

स्टार्टर प्लेयर ऐसा करता है जब कैरेक्टर मूव करता है:

if direction.length() > 0 and self.meshTransform:
    self.meshTransform.lookAtSmooth(
        self.entity.getTransform().transformDirection(-direction),
        6.0 * cave.getDeltaTime()
    )

महत्वपूर्ण विचार सही गणित नहीं है। महत्वपूर्ण बात यह है कि गेमप्ले बॉडी और दृश्य मेष को अलग-अलग नियंत्रित किया जा सकता है।

यह आपको चुनने की अनुमति देता है कि कैरेक्टर किस दिशा की ओर देखना चाहिए:

  • मूवमेंट की दिशा की ओर देखना।
  • स्ट्रेफिंग करते हुए आगे की ओर देखते रहना।
  • इच्छित दिशा की ओर धीरे-धीरे घुमना।
  • विभिन्न गेमप्ले मोड्स के लिए अलग दृश्य अभिविन्यास नियमों का उपयोग करना।

यह मुख्य कारणों में से एक है कि स्टार्टर कैरेक्टर में एक चाइल्ड Mesh एंटीटी होती है।

एनीमेशन ब्लेंडिंग

एनीमेशन ब्लेंडिंग ट्रांजिशन को स्मूथ बनाती है।

ब्लेंडिंग के बिना, एक एनीमेशन से दूसरे पर स्विच तुरंत हो सकता है। ब्लेंडिंग के साथ, Cave एक ही लेयर पर एनीमेशनों के बीच धीरे-धीरे ट्रांजिशन कर सकता है।

उदाहरण के लिए:

# इससे:
self.animator.playByName("p-idle", blend=0.2, loop=True)

# इसमें:
self.animator.playByName("p-walk", blend=0.2, loop=True)

यहाँ, blend=0.2 का मतलब है Cave नई एनीमेशन में 0.2 सेकंड में ब्लेंड करेगा।

यह कैरेक्टर्स के लिए विशेष रूप से महत्वपूर्ण है। एक प्लेयर कड़क एनीमेशन पॉप्स को बहुत आसानी से पहचान सकता है, भले ही वह एक प्रोटोटाइप में हो।

अच्छे शुरुआती ब्लेंड मान आमतौर पर छोटे होते हैं:

  • बहुत तेज ट्रांजिशन के लिए 0.1
  • सामान्य मूवमेंट ट्रांजिशन के लिए 0.2
  • धीमी, भारी ट्रांजिशन के लिए 0.4 या ज्यादा।

आप इसे महसूस करके ठीक कर सकते हैं।

एनीमेशन लेयर्स

Cave कई एनीमेशन लेयर्स समर्थित करता है। हर लेयर अपनी एनीमेशन चला सकती है, और ऊँचे लेयर्स नीचे के ऊपर स्टैक हो सकते हैं। आप किसी भी लेयर में एनीमेशन चला सकते हैं।

डिफ़ॉल्ट लोकॉमोशन एनीमेशन आमतौर पर लेयर 0 पर चलता है।

उदाहरण:

self.animator.playByName("p-walk", blend=0.2, layer=0, loop=True)

अगर आपके पास ऊपरी शरीर की एक्शन एनीमेशन है, जैसे हमला, निशाना लगाना, या रीलोड, तो आप इसे किसी दूसरे लेयर पर चला सकते हैं:

self.animator.playByName("Attack", blend=0.1, layer=1, loop=False)

विचार यह है:

लेयर सामान्य उद्देश्य
लेयर 0 पूर्ण शरीर की लोकॉमोशन, जैसे idle, walk, run, jump, fall।
लेयर 1 ऊपरी शरीर की क्रियाएँ, जैसे attack, aim, reload, हथियार पकड़ना।

यह कैरेक्टर को चलते रहने देते हुए ऊपरी लेयर पर एक्शन जोड़ने की अनुमति देता है।

लेयर वेट्स

हर लेयर का एक वेट होता है, जो नियंत्रित करता है कि उस लेयर का कितना प्रभाव है।

आप इसे Python से बदल सकते हैं:

self.animator.setLayerWeight(1, 1.0)

आप इसे पढ़ भी सकते हैं:

weight = self.animator.getLayerWeight(1)

वेट 1.0 का मतलब है लेयर पूरी तरह से सक्रिय है। वेट 0.0 का मतलब कोई दृश्य प्रभाव नहीं है।

लेयर वेट उपयोगी होते हैं जब आप किसी एक्शन लेयर को धीरे-धीरे फीका करना चाहते हैं, जैसे धीरे-धीरे हथियार उठाना, निशाना लगाना, या किसी खास स्टांस में ब्लेंड करना।

यह उल्लेखनीय है कि ब्लेंड पैरामीटर केवल एक ही लेयर में एनीमेशन के बीच ब्लेंड करता है। और हम अलग-अलग लेयर्स पर चल रही एनीमेशन को ब्लेंड नहीं करेंगे। तो अगर आपके पास लेयर 0 पर एक एनीमेशन चल रही है, और फिर अचानक लेयर 1 पर एक एनीमेशन चलाते हैं, तो ब्लेंड वैल्यू जो भी हो, वे उनके बीच ब्लेंड नहीं करेंगे। यह तब ब्लेंड करेगा जब लेयर 1 पर पहले से ही कोई दूसरी एनीमेशन चल रही हो। अगर आप लेयर्स के बीच ब्लेंड करना चाहते हैं, तो आपको कस्टम लॉजिक बनानी होगी जो लेयर वेट का उपयोग करे।

बोन फ़िल्टर्स

बोन फ़िल्टर्स नियंत्रित करते हैं कि कौन से बोन किस लेयर द्वारा प्रभावित होते हैं और हर बोन को कितना प्रभाव मिलता है।

यह वही है जो ऊपरी शरीर की एनीमेशन को संभव बनाता है।

उदाहरण के लिए, आप चाह सकते हैं:

  • लेयर 0 पूरे शरीर को नियंत्रित करे।
  • लेयर 1 केवल रीढ़, बाहें, हाथ, और हथियार की हड्डियों को नियंत्रित करे।

Python में, आप किसी लेयर के लिए एक फ़िल्टर बना सकते हैं और एक बोन और उसके बच्चों को प्रभाव असाइन कर सकते हैं:

def setupUpperBodyLayer(self):
    armature = self.animator.armature.get()
    spine = armature.getBone("mixamorig:Spine")

    upperBody = self.animator.createLayerFilter(1)
    upperBody.defaultBlend = 0.0
    upperBody.setToBone(spine, 1.0, recursive=True)

इस उदाहरण में:

  • defaultBlend = 0.0 का मतलब है कि डिफ़ॉल्ट रूप से लेयर किसी भी बोन को प्रभावित नहीं करता।
  • setToBone(spine, 1.0, recursive=True) का मतलब है रीढ़ और उसके बच्चे पूरी तरह से प्रभावित होते हैं।
  • लेयर 1 अब ऊपरी शरीर के एनीमेशनों के लिए इस्तेमाल किया जा सकता है।

आपके बोन नाम उस आर्मेचर पर निर्भर करते हैं जिसे आपने इम्पोर्ट किया है। हमेशा अपने आर्मेचर को जांचें और अपने कैरेक्टर के लिए सही बोन नामों का उपयोग करें।

व्यावहारिक लेयर उदाहरण

कल्पना करें कि एक थर्ड-पर्सन कैरेक्टर है जो चलते हुए हमला भी कर सकता है।

एक संभावित सेटअप है:

लेयर यह क्या संभालता है
लेयर 0 Idle, walk, run, fall।
लेयर 1 ऊपरी शरीर का हमला।

कोड कुछ इस तरह हो सकता है:

import cave

class CombatAnimator(cave.Component):
    def start(self, scene: cave.Scene):
        self.mesh = self.entity.getChild("Mesh")
        self.animator : cave.AnimationComponent = self.mesh.get("Animation") if self.mesh else None

        if self.animator:
            armature = self.animator.armature.get()
            spine = armature.getBone("mixamorig:Spine")

            upperBody = self.animator.createLayerFilter(1)
            upperBody.defaultBlend = 0.0
            upperBody.setToBone(spine, 1.0, recursive=True)
            self.animator.setLayerWeight(1, 1.0)

    def playWalk(self):
        self.animator.playByName("p-walk", blend=0.2, layer=0, loop=True)

    def playAttack(self):
        self.animator.playByName("Attack", blend=0.1, layer=1, loop=False)

यह उदाहरण मानता है कि आपके पास Attack नामक एक एनीमेशन एसेट है। यदि आपकी प्रोजेक्ट में कोई अलग एनीमेशन नाम है, तो कृपया उस नाम का उपयोग करें।

महत्वपूर्ण विचार यह है कि लोकॉमोशन लेयर 0 पर रहता है, जबकि हमला लेयर 1 पर चलता है और केवल उन हड्डियों को प्रभावित करता है जो फ़िल्टर किए गए हैं।

एनीमेशन कॉलबैक्स

एनीमेशन विशेष समयों पर Python कोड चला सकते हैं।

Cave नीचे दिए गए कॉलबैक्स को सपोर्ट करता है:

  • एनीमेशन शुरू होने पर।
  • एनीमेशन समाप्त होने पर।
  • एक विशेष एनीमेशन फ्रेम पर।

कॉलबैक्स तब उपयोगी होते हैं जब एनीमेशन को गेमप्ले या इफेक्ट्स को ट्रिगर करना हो।

उदाहरण:

  • फुटस्टेप साउंड बजाना।
  • कदम पर धूल उत्पन्न करना।
  • हमला फ्रेम पर डैमेज लागू करना।
  • हथियार ट्रेल शुरू करना।
  • पार्टिकल इफेक्ट ट्रिगर करना।
  • लॉजिक को सूचित करना कि एनीमेशन खत्म हो गया।

एनीमेशन आमतौर पर सहीタイमिंग जानते हैं बजाय कोड के। अगर एक तलवार को डैमेज तब देना है जब स्विंग लक्ष्य क्षेत्र तक पहुँचे, तो एनीमेशन कॉलबैक उस गेमप्ले पल को सही फ्रेम पर रख सकता है।

फुटस्टेप कॉलबैक उदाहरण

स्टार्टर प्रोजेक्ट्स में वॉक और रन एनीमेशन्स में फुटस्टेप कॉलबैक्स शामिल हो सकते हैं। इनकी जांच करना एक व्यावहारिक एनीमेशन कॉलबैक को देखने का अच्छा तरीका है।

सिद्धांत सरल है:

  1. एनीमेशन जानता है कब पैर जमीन छूता है।
  2. कॉलबैक उस फ्रेम पर रखा जाता है।
  3. कॉलबैक ध्वनि बजाता है या एक छोटा इफेक्ट उत्पन्न करता है।

एनीमेशन कॉलबैक के अंदर, Cave उपयोगी वेरिएबल प्रदान करता है जैसे:

  • entity, स्वामी एंटीटी।
  • animator, Animation Component।
  • handle, चल रही एनीमेशन लेयर/हैंडलर।

एक बहुत छोटा फुटस्टेप कॉलबैक इस तरह दिख सकता है:

cave.playSound("Footstep Grass", volume=0.5)

आप बाद में इस विचार का विस्तार कर सकते हैं ताकि जमीन के पदार्थ, कैरेक्टर की गति या वर्तमान स्थिति के आधार पर अलग-अलग आवाज़ें चुनी जा सकें।

पुन: उपयोगी एनीमेशन कॉलबैक्स

कॉलबैक्स एनीमेशन एसेट के लिए होते हैं।

इसका मतलब है कि यदि कई एंटीटीज एक ही एनीमेशन चलाते हैं, तो कॉलबैक उन हर एंटीटी के लिए चल सकता है जो इसका उपयोग करता है।

यह कॉलबैक्स को पुन: उपयोगी बनाता है। उदाहरण के लिए, एक ही वॉक एनीमेशन हर उस कैरेक्टर के लिए फुटस्टेप साउंड ट्रिगर कर सकता है जो इसे चलाता है, जब तक कि कॉलबैक कोड स्वामी एंटीटी को सही ढंग से उपयोग करता है।

एनीमेशन टाइमिंग स्टोर करता है। एंटीटी संदर्भ प्रदान करती है।

उन्नत पोज़ कॉलबैक्स

Cave Python के माध्यम से पोस्ट-इवैल्यूएशन कॉलबैक्स भी सपोर्ट करता है। ये तब होते हैं जब Animation Component आर्मेचर पोज़ को इवैल्यूएट कर चुका होता है।

यह एक उन्नत फीचर है, लेकिन इसे इस्तेमाल किया जा सकता है:

  • इनवर्स काइनेमैटिक्स।
  • सिर का निशाना लगाना।
  • हथियार का निशाना लगाना।
  • पैर की प्लेसमेंट।
  • अंतिम पोज़ समायोजन।

स्टार्टर Player Toolkit में Foot IK उदाहरण शामिल है जो इस अवधारणा का उपयोग करता है। यह Mesh चाइल्ड को प्राप्त करता है, Animation कॉम्पोनेन्ट को प्राप्त करता है, फिर एक मेथड को इस तरह रजिस्टर करता है:

self.animator.addPostEvaluationCallback(self.postEvaluation)

आपको तुरंत IK सिस्टम लिखने की जरूरत नहीं है, लेकिन यह जानना उपयोगी है कि Cave सामान्य एनीमेशन प्लेबैक के बाद Python को अंतिम पोज़ समायोजित करने देता है।

Animation Socket Component

Animation Socket Component एक चाइल्ड एंटीटी को एक पैरेंट एनीमेटेड एंटीटी की बोन के साथ फॉलो करने देता है।

चाइल्ड एंटीटी को एक ऐसे पैरेंट के अंतर्गत होना चाहिए जिसमें Animation Component हो। फिर socket एक बोन चुन सकता है और उस बोन से स्थिति, रोटेशन, और वैकल्पिक रूप से स्केल कॉपी कर सकता है, आवश्यकतानुसार ऑफसेट के साथ।

Sockets का उपयोग एनिमेटेड कैरेक्टर्स से चीजें जोड़ने के लिए किया जाता है:

  • एक हाथ में तलवार।
  • एक हाथ में बंदूक।
  • एक हाथ में ढाल।
  • एक सिर पर हेलमेट।
  • रीढ़ की हड्डी पर बैकपैक।
  • एक हाथ में लगाई गई प्रॉप।

उदाहरण के लिए, यदि एक कैरेक्टर तलवार पकड़े होता है, तो तलवार एक चाइल्ड एंटिटी हो सकती है जिसमें Animation Socket Component होता है जो हाथ की हड्डी का पालन करता है। जैसे-जैसे कैरेक्टर हमला करता है, दौड़ता है, या स्थिर रहता है, तलवार सही एनीमेटेड स्थिति से जुड़ी रहती है।

वह बातें जो आपको याद रखनी चाहिए

  • स्टार्टर प्लेयर एक टेम्पलेट होता है जिसमें एक रूट Player एंटिटी और एक चाइल्ड Mesh एंटिटी होती है।
  • रूट Player आमतौर पर फिजिक्स, मूवमेंट, प्रॉपर्टीज़, और गेमप्ले लॉजिक संभालता है।
  • चाइल्ड Mesh आमतौर पर दृश्यमान मॉडल, मटेरियल, आर्मेचर, और Animation Component को संभालता है।
  • यह विभाजन फिजिक्स बॉडी और विज़ुअल कैरेक्टर को अलग ट्रांसफॉर्म देता है।
  • Animation Component आर्मेचर और एनीमेशन एसेट्स का उपयोग करके स्केलेटल एनीमेशन चलाता है।
  • Python में, Animation Component को आमतौर पर animator कहा जाता है।
  • playByName नाम से एनीमेशन एसेट चलाता है और ब्लेंडिंग, लूपिंग, और लेयर्स को सपोर्ट करता है।
  • लेयर्स एक साथ कई एनीमेशन को स्टैक करने देते हैं।
  • बोन फ़िल्टर्स एक लेयर को कंकाल के केवल एक हिस्से को प्रभावित करने देते हैं।
  • एनीमेशन कॉलबैक्स एनीमेशन के समय को गेमप्ले इवेंट्स से जोड़ते हैं।
  • एनीमेशन सॉकेट्स प्रॉप्स को एनीमेटेड हड्डियों से जोड़ते हैं।

जब आप स्टार्टर Player या Enemy टेम्पलेट का निरीक्षण करते हैं, तो इस संरचना को अपने नक्शे के रूप में उपयोग करें: रूट एंटिटी गेमप्ले के लिए, चाइल्ड Mesh एंटिटी दृश्य और एनीमेशन के लिए।