मैं यूनिटी का उपयोग करके किसी 3 डी ऑब्जेक्ट की सतह पर खिलाड़ी के आंदोलन को कैसे रोक सकता हूं?


16

मैं मारियो गैलेक्सी या ज्योमेट्री वॉर्स 3 के समान एक प्रभाव पैदा करने की कोशिश कर रहा हूं, जहां खिलाड़ी "ग्रह" के चारों ओर चलता है, गुरुत्वाकर्षण को समायोजित करने के लिए लगता है और वे वस्तु के किनारे से नहीं गिरते हैं क्योंकि वे गुरुत्वाकर्षण को पसंद करेंगे एक ही दिशा में तय किया गया था।

यहाँ छवि विवरण दर्ज करें
(स्रोत: gameskinny.com )

ज्यामिति के युद्ध ३

मैं उस चीज के करीब कुछ लागू करने में कामयाब रहा, जो मैं एक दृष्टिकोण का उपयोग करने के लिए देख रहा हूं, जहां उस वस्तु को जहां गुरुत्वाकर्षण होना चाहिए, अन्य कठोर निकायों को अपनी ओर आकर्षित करता है, लेकिन अंतर्निहित एकता के लिए भौतिकी इंजन में उपयोग करके, AddForce और पसंद के साथ आंदोलन को लागू करना, मैं सिर्फ सही महसूस करने के लिए आंदोलन नहीं कर सका। मैं खिलाड़ी को वस्तु की सतह से उड़ना शुरू किए बिना तेजी से आगे बढ़ने के लिए नहीं मिल सकता था और मुझे इसके लिए समायोजित करने के लिए लागू बल और गुरुत्वाकर्षण का एक अच्छा संतुलन नहीं मिला। मेरा वर्तमान कार्यान्वयन यहाँ जो पाया गया उसका एक रूपांतर है

मुझे ऐसा लगता है कि समाधान शायद तब भी भौतिक विज्ञान का उपयोग करेगा ताकि खिलाड़ी को सतह पर छोड़ दिया जा सके यदि वे सतह को छोड़ दें, लेकिन एक बार खिलाड़ी को मैदान में उतारने के बाद खिलाड़ी को सतह पर लाने और भौतिकी को बंद करने का एक तरीका होगा और अन्य माध्यमों से खिलाड़ी को नियंत्रित करें, लेकिन मुझे यकीन नहीं है।

खिलाड़ी को वस्तुओं की सतह पर स्नैप करने के लिए मुझे किस तरह का दृष्टिकोण रखना चाहिए? ध्यान दें कि समाधान 3 डी अंतरिक्ष में काम करना चाहिए (2 डी के विपरीत) और एकता के मुफ्त संस्करण का उपयोग करके इसे लागू करने में सक्षम होना चाहिए।



मैंने दीवारों पर चलने के बारे में सोचा भी नहीं था। मैं देख लेता हूँ और देखता हूँ कि क्या ये मदद करते हैं।
स्पार्टनडोनट

1
यदि यह प्रश्न विशेष रूप से 3 डी यूनिटी में ऐसा करने के बारे में है, तो इसे संपादन के साथ स्पष्ट किया जाना चाहिए। (यह उस मौजूदा के एक सटीक डुप्लिकेट नहीं होगा ।)
Anko

यही मेरी सामान्य भावना भी है - मैं यह देखने जा रहा हूं कि क्या मैं उस समाधान को 3 डी में ढाल सकता हूं और इसे उत्तर के रूप में पोस्ट कर सकता हूं (या यदि कोई व्यक्ति मुझे उस पंच को हरा सकता है जो मैं उसके साथ भी ठीक हूं)। मैं कोशिश करूँगा और उस पर अधिक स्पष्ट होने के लिए अपने प्रश्न को अपडेट करूंगा।
SpartanDonut

संभावित रूप से उपयोगी: youtube.com/watch?v=JMWnufriQx4
ssb

जवाबों:


7

मैं इस बात को पूरा करने में कामयाब रहा कि मुझे क्या चाहिए, मुख्य रूप से इस ब्लॉग पोस्ट की सहायता से सतह के टुकड़े के टुकड़े के लिए और खिलाड़ी के आंदोलन और कैमरे के लिए अपने स्वयं के विचारों के साथ आया।

एक वस्तु की सतह के लिए तड़क खिलाड़ी

मूल सेटअप में एक बड़ा गोला (दुनिया) और एक छोटा गोला (खिलाड़ी) होता है, जिसमें दोनों गोलक होते हैं जो उनसे जुड़े होते हैं।

जो काम किया जा रहा है वह निम्नलिखित दो विधियों में था:

private void UpdatePlayerTransform(Vector3 movementDirection)
{                
    RaycastHit hitInfo;

    if (GetRaycastDownAtNewPosition(movementDirection, out hitInfo))
    {
        Quaternion targetRotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
        Quaternion finalRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, float.PositiveInfinity);

        transform.rotation = finalRotation;
        transform.position = hitInfo.point + hitInfo.normal * .5f;
    }
}

private bool GetRaycastDownAtNewPosition(Vector3 movementDirection, out RaycastHit hitInfo)
{
    Vector3 newPosition = transform.position;
    Ray ray = new Ray(transform.position + movementDirection * Speed, -transform.up);        

    if (Physics.Raycast(ray, out hitInfo, float.PositiveInfinity, WorldLayerMask))
    {
        return true;
    }

    return false;
}

Vector3 movementDirectionपैरामीटर बस के रूप में यह लग रहा है, दिशा हम करते समय इस उदाहरण में अपेक्षाकृत सरल समाप्त हो गया इस फ्रेम में हमारे खिलाड़ी ले जाया जा रहा है, और है कि वेक्टर गणना करते समय, जा रहे हैं, मुझे पहली बार में यह पता लगाने के लिए एक सा मुश्किल था। उस पर और बाद में, लेकिन बस ध्यान रखें कि यह उस दिशा में एक सामान्यीकृत वेक्टर है जो खिलाड़ी इस फ्रेम को आगे बढ़ा रहा है।

के माध्यम से कदम रखते हुए, पहली चीज जो हम जांचते हैं कि क्या एक किरण, काल्पनिक भविष्य की स्थिति में उत्पन्न होती है, जो नीचे वेक्टर (-transform.up) के खिलाड़ियों के लिए निर्देशित होती है, वर्ल्डलाइयरमास्क का उपयोग करके दुनिया को हिट करती है जो स्क्रिप्ट का एक सार्वजनिक लेयरमास्क संपत्ति है। यदि आप अधिक जटिल टकराव या कई परतें चाहते हैं तो आपको अपनी खुद की लेयर मास्क का निर्माण करना होगा। यदि रेकास्ट सफलतापूर्वक कुछ हिट करता है तो हिटइन्फो का उपयोग खिलाड़ी की नई स्थिति और रोटेशन की गणना करने के लिए सामान्य और हिट बिंदु प्राप्त करने के लिए किया जाता है जो ऑब्जेक्ट पर सही होना चाहिए। प्रश्न में खिलाड़ी वस्तु के आकार और उत्पत्ति के आधार पर खिलाड़ी की स्थिति को बंद करना आवश्यक हो सकता है।

अंत में, यह वास्तव में केवल परीक्षण किया गया है और संभावना केवल सरल वस्तुओं जैसे कि गोले पर अच्छी तरह से काम करती है। जैसा कि ब्लॉग पोस्ट मैं सुझाव के अपने समाधान के आधार पर आधारित है, आप अधिक जटिल इलाकों में जाने पर बहुत अधिक अच्छे संक्रमण प्राप्त करने के लिए कई किरणों का प्रदर्शन करने और अपनी स्थिति और रोटेशन के लिए उन्हें औसत करना चाहते हैं। ऐसे अन्य नुकसान भी हो सकते हैं जिनके बारे में मैंने इस बिंदु पर नहीं सोचा था।

कैमरा और आंदोलन

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

मेरी जरूरतों के लिए अच्छी तरह से काम करने के लिए एक कैमरा होना चाहिए जो पूरी तरह से खिलाड़ियों की स्थिति के आधार पर खिलाड़ी का पालन करता है। नतीजतन, भले ही कैमरा तकनीकी रूप से घूम रहा था, दबाने पर हमेशा खिलाड़ी को स्क्रीन के शीर्ष की ओर, नीचे की ओर नीचे की ओर ले जाया जाता था, और इसी तरह बाएं और दाएं के साथ।

ऐसा करने के लिए, निम्नलिखित को कैमरे पर निष्पादित किया गया था जहां लक्ष्य वस्तु खिलाड़ी थी:

private void FixedUpdate()
{
    // Calculate and set camera position
    Vector3 desiredPosition = this.target.TransformPoint(0, this.height, -this.distance);
    this.transform.position = Vector3.Lerp(this.transform.position, desiredPosition, Time.deltaTime * this.damping);

    // Calculate and set camera rotation
    Quaternion desiredRotation = Quaternion.LookRotation(this.target.position - this.transform.position, this.target.up);
    this.transform.rotation = Quaternion.Slerp(this.transform.rotation, desiredRotation, Time.deltaTime * this.rotationDamping);
}

अंत में, खिलाड़ी को स्थानांतरित करने के लिए, हमने मुख्य कैमरे के रूपांतरण का लाभ उठाया ताकि हमारे नियंत्रण के साथ ऊपर, नीचे की ओर नीचे बढ़ें, आदि और यह यहाँ है कि हम UpdatePlayerTransform कहते हैं, जो हमारी स्थिति को विश्व ऑब्जेक्ट में तड़क जाएगा।

void Update () 
{        
    Vector3 movementDirection = Vector3.zero;
    if (Input.GetAxisRaw("Vertical") > 0)
    {
        movementDirection += cameraTransform.up;
    }
    else if (Input.GetAxisRaw("Vertical") < 0)
    {
        movementDirection += -cameraTransform.up;
    }

    if (Input.GetAxisRaw("Horizontal") > 0)
    {
        movementDirection += cameraTransform.right;
    }
    else if (Input.GetAxisRaw("Horizontal") < 0)
    {
        movementDirection += -cameraTransform.right;
    }

    movementDirection.Normalize();

    UpdatePlayerTransform(movementDirection);
}

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


3

मुझे लगता है कि यह विचार काम करेगा:

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

अब, किस बिंदु के आधार पर ग्रह के सामान्य वेक्टर की गणना की जानी चाहिए?

सबसे आसान उत्तर (जो मुझे पूरा यकीन है कि ठीक काम करेगा) न्यूटन की विधि के समान है : जब ऑब्जेक्ट पहली बार स्पॉन करते हैं, तो आप ग्रह पर उनके सभी प्रारंभिक पदों को जानते हैं। प्रत्येक ऑब्जेक्ट के upवेक्टर को निर्धारित करने के लिए उस प्रारंभिक स्थिति का उपयोग करें । स्पष्ट रूप से गुरुत्वाकर्षण विपरीत दिशा में (ओर down) होगा। अगले फ्रेम में, गुरुत्वाकर्षण को लागू करने से पहले, ऑब्जेक्ट की नई स्थिति से पुरानी downवेक्टर की ओर एक किरण डालें । upवेक्टर के निर्धारण के नए संदर्भ के रूप में ग्रह के साथ उस किरण के चौराहे का उपयोग करें । कुछ भी नहीं होने के कारण किरण के दुर्लभ मामले का मतलब है कि कुछ बुरी तरह से गलत हो गया है और आपको अपनी वस्तु को वापस उसी स्थान पर ले जाना चाहिए जहां वह पिछले फ्रेम में थी।

यह भी ध्यान दें कि इस पद्धति का उपयोग करते हुए, आगे के खिलाड़ी की उत्पत्ति ग्रह से होती है, इससे भी बदतर स्थिति बन जाती है। इसलिए प्रत्येक खिलाड़ी के पैरों के चारों ओर उनके मूल के रूप में उपयोग करना बेहतर है। मैं अनुमान लगा रहा हूं, लेकिन मुझे लगता है कि मूल के रूप में पैरों का उपयोग करना भी आसान हैंडलिंग और खिलाड़ी के नेविगेशन का परिणाम होगा।


एक अंतिम नोट: बेहतर परिणामों के लिए, आप निम्न कार्य भी कर सकते हैं: प्रत्येक फ्रेम में खिलाड़ी के मूवमेंट पर नज़र रखें (उदाहरण के लिए current_position - last_position)। फिर उसे दबाना movement_vectorताकि वह वस्तु की लंबाई upशून्य हो। चलो इस नए वेक्टर कहते हैं reference_movement। पिछले reference_pointद्वारा स्थानांतरित करें reference_movementऔर इस नए बिंदु का उपयोग किरण अनुरेखण मूल के रूप में करें। (और अगर) किरण ग्रह reference_pointसे टकराती है , तो उस हिट बिंदु पर चली जाती है। अंत में, नए upवेक्टर की गणना इस नए से करें reference_point

कुछ छद्म कोड इसे योग करने के लिए:

update_up_vector(player:object, planet:mesh)
{
    up_vector        = normalize(planet.up);
    reference_point  = ray_trace (object.old_position, -up_vector, planet);
    movement         = object.position - object.old_position;
    movement_clamped = movement - up_vector * dot (movement, up_vector);

    reference_point  += movement_clamped;
    reference_point  = ray_trace (reference_point, -up_vector, planet);
    player.up        = normal_vector(mesh, reference_point);
}

2

यह पोस्ट मददगार हो सकती है। इसका सार यह है कि आप वर्ण नियंत्रकों का उपयोग नहीं करते हैं, लेकिन भौतिकी इंजन का उपयोग करके अपना स्वयं का बनाते हैं। फिर आप खिलाड़ी को नीचे की ओर से लगाए गए मानदंडों का उपयोग करके उन्हें मेष की सतह पर उन्मुख करते हैं।

यहाँ एक अच्छा अवलोकन है तकनीक है। वेब खोज शब्दों के साथ बहुत अधिक संसाधन हैं जैसे "3 डी ऑब्जेक्ट्स मारियो गैलेक्सी पर एकता चलना"।

एकता 3.x से एक डेमो प्रोजेक्ट भी है जिसमें एक चलने वाला इंजन था, एक सैनिक और एक कुत्ते के साथ और एक दृश्य में। इसने 3D वस्तुओं गैलेक्सी -स्टाइल पर चलने का प्रदर्शन किया । इसे रनवेविजन द्वारा हरकत प्रणाली कहा जाता है ।


1
पहली नज़र में डेमो बहुत अच्छी तरह से काम नहीं करता है और एकता पैकेज त्रुटियों का निर्माण किया है। मैं देखूंगा कि क्या मैं यह काम कर सकता हूं लेकिन अधिक पूर्ण उत्तर की सराहना की जाएगी।
स्पार्टनडोनट

2

रोटेशन

इस सवाल का जवाब answer.unity3d.com पर चेकआउट करें (वास्तव में खुद से पूछा)। उद्धरण:

पहला काम एक वेक्टर प्राप्त करना है जो परिभाषित करता है। अपनी ड्राइंग से, आप इसे दो में से एक तरीके से कर सकते हैं। आप ग्रह को एक क्षेत्र के रूप में मान सकते हैं और उपयोग कर सकते हैं। दूसरा तरीका Collider.Raycast () का उपयोग करना है और यह 'hit.normal' का उपयोग करता है।

यहाँ वह कोड है जो उसने मुझे सुझाया है:

var up : Vector3 = transform.position - planet.position;
transform.rotation = Quaternion.FromToRotation(transform.up, up) * transform.rotation;

कॉल करें कि हर अपडेट, और आपको इसे काम करना चाहिए। (ध्यान दें कि कोड यूनिटीस्क्रिप्ट में है )। C #
में समान कोड :

Vector3 up = transform.position - planet.position;
transform.rotation = Quaternion.FromToRotation(transform.up, up) * transform.rotation;

गुरुत्वाकर्षण

गुरुत्वाकर्षण के लिए, आप मेरी "ग्रह भौतिकी तकनीक" का उपयोग कर सकते हैं, जिसे मैंने अपने प्रश्न में वर्णित किया है, लेकिन यह वास्तव में अनुकूलित नहीं है। यह मेरे दिमाग में बस कुछ था।
मैं आपको सुझाव देता हूं कि आप गुरुत्वाकर्षण के लिए अपनी प्रणाली बनाएं।

यहाँ सेबस्टियन लैगु द्वारा एक यूट्यूब ट्यूटोरियल है । यह एक बहुत अच्छी तरह से काम कर समाधान है।

संपादित करें: एकता में, संपादित करें > प्रोजेक्ट सेटिंग्स > भौतिकी पर जाएं और ग्रेविटी के लिए सभी मानों को 0 पर सेट करें (या सभी वस्तुओं से रिजिडबॉडी को हटा दें ), अंतर्निर्मित गुरुत्वाकर्षण को रोकने के लिए (जो सिर्फ खिलाड़ी को नीचे खींचता है) साथ संघर्ष करने के लिए कस्टम समाधान। (इसे बंद करें)


खिलाड़ी को किसी ग्रह के केंद्र में लाना (और उनके अनुसार उन्हें घुमाना) पास-गोलाकार ग्रहों के लिए अच्छा काम करता है, लेकिन मैं कल्पना कर सकता हूं कि यह कम गोलाकार वस्तुओं के लिए गलत हो रहा है, जैसे कि रॉकेट के आकार का मारियो पहले जीआईएफ में कूद रहा है।
अंको

आप एक क्यूब बना सकते हैं जो केवल एक्स-एक्सिस के चारों ओर घूमने के लिए प्रतिबंधित है, उदाहरण के लिए, गैर-गोलाकार वस्तु के अंदर, और खिलाड़ी के हिलने पर इसे स्थानांतरित करें, ताकि यह खिलाड़ी के नीचे हमेशा सीधा रहे, और फिर खिलाड़ी को खींचे घन के नीचे। कोशिश करो।
डैनियल केविस्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.