क्या होता है जब Time.time यूनिटी में बहुत बड़ी हो जाती है?


37

जैसा कि यहाँ कहा गया है :

Time.time

इस फ्रेम की शुरुआत में समय (केवल पढ़ें)। खेल की शुरुआत के बाद से सेकंड में यह समय है।

और जैसा कि मुझे पता है कि समय नाव में संग्रहीत है। तो, मेरा सवाल यह है कि जब समय का मूल्य बहुत बड़ा हो जाएगा तो क्या होगा? क्या यह ओवरफ्लो हो सकता है? क्या यह सटीकता खो देगा और कीड़े पैदा करेगा? खेल सिर्फ दुर्घटना या क्या होगा?



5
@AlexandreVaillancourt मुझे लगता है कि यहां एक उपयोगी सवाल है अगर हम इसे "जब समय बहुत बड़ा हो जाता है तो क्या समस्याएं हैं?" अकेले "अतिप्रवाह" पर शाब्दिक ध्यान केंद्रित करने का विरोध किया। मैंने आपकी प्रतिक्रिया को संबोधित करने का प्रयास करने के लिए इन पंक्तियों के साथ प्रश्न को संपादित किया है।
DMGregory

2
@DMGregory लेकिन सवाल का जवाब दिया गया और पहले से ही स्वीकार कर लिया गया ... मैं मानता हूं कि आपके संपादन एक अधिक उपयोगी प्रश्न के लिए तैयार हैं, बस थोड़ा देर से।
MichaelHouse

मैंने संपादन को वाक्यांशित करने का प्रयास किया ताकि स्वीकृत उत्तर अभी भी संपादित संस्करण का सही उत्तर हो। (आखिरकार, यह पहले से ही सटीक मुद्दों के बारे में बात करता है) मैं अपराध नहीं करूंगा अगर यह वापस आ गया है।
DMGregory

जवाबों:


62

एकल-सटीक फ्लोट का उपयोग करने से समय की सटीकता के नुकसान का वास्तविक जोखिम है

यह अभी भी 97 दिनों के लिए निकटतम दूसरे के लिए सटीकता बनाए रखेगा । लेकिन खेलों में हम अक्सर एक फ्रेम अवधि के क्रम पर सटीकता की परवाह करते हैं।

सेकंड में एक एकल-सटीक फ्लोट समय मान लगभग 9 घंटों के बाद मिलीसेकंड सटीकता खोना शुरू कर देता है ।

यह पहले से ही एक नाटक सत्र के लिए संभावना के दायरे से बाहर नहीं है, या जब आप काम / स्कूल या सो रहे हैं तो "एएफके" खेल को छोड़ दें। (यह एक कारण है कि किसी खेल का परीक्षण करने का एक सामान्य तरीका यह है कि इसे रात भर चलाया जाए और जांच की जाए कि यह अभी भी सुबह सही तरीके से खेलता है)

आधुनिक कंसोल पर, जहां खेल अक्सर निलंबित होते हैं और पूरी तरह से बंद होने के बजाय खेल सत्रों के बीच फिर से शुरू हो जाते हैं, खेल के नज़रिए से "सिंगल सेशन" के लिए यह अप्रत्याशित नहीं है, जब शॉर्ट ब्रेक में खेला जाता है, तब भी रनटाइम के 9 घंटे से अधिक हो सकता है।

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

चूँकि fixedDeltaTimeआप एक ही मान रखते हैं, जो गतिशील रूप से फ्रेम से फ्रेम में बदलने के बजाय, आप स्थिरता की मजबूत गारंटी प्राप्त करने के लिए समय-संवेदनशील व्यवहार को फिक्स्डयूडेट में रख सकते हैं। deltaTimeस्वचालित रूप से इन विधियों में उचित निश्चित डेल्टा लौटाएगा। हालांकि फिक्स्ड और फ्रेम अपडेट के बीच एक बीट फ्रीक्वेंसी हो सकती है, आप इसे इंटरपोलेशन के जरिए सुचारू कर सकते हैं

आप जो बचना चाहते हैं, वह एक टाइमस्टैम्प को दूसरे से घटाकर अवधि की गणना कर रहा है । खेलने के घंटों के बाद यह भयावह निरस्तीकरण का कारण बन सकता है, जिससे आपको दौड़ में जल्दी निकलने की तुलना में बहुत कम सटीकता की ओर जाता है। यदि आपके सिस्टम के लिए टाइमस्टैम्प की तुलना करना महत्वपूर्ण है, तो आप अन्य तरीकों का उपयोग करके अपने स्वयं के उच्च-रिज़ॉल्यूशन समय मान उत्पन्न कर सकते हैं, जैसे System.Diagnostics.Stopwatchकि Time.time


अवास्तविक खेल कोड और ब्लूप्रिंट दोनों में एकल-सटीक फ्लोट के रूप में खेल के समय को उजागर करने का विकल्प चुनता है । आप रियल टाइम में टाइमस्टैम्प के साथ इसके आसपास काम कर सकते हैं और अपना खुद का समय पतला कर सकते हैं, जैसा कि आप यूनिटी में करेंगे। (बस यह देखें कि अवास्तविक का टाइमस्टैम्प प्रकार 32-बिट युग पर आधारित है )। यदि आप चुनते हैं तो असत्य में C # के लिए एक्सटेंशन मौजूद हैं।
DMGregory

[Ms] के लिए, आप १६ ४ --४ - ३२६। बैंड के आसपास सटीकता खोना शुरू करते हैं। यही है, आप 4h30min के बाद परिशुद्धता को ढीला कर सकते हैं , 9h के बाद आप निश्चित रूप से उस पर भरोसा नहीं कर सकते।
xmedeko

तकनीकी रूप से 4.5-9 घंटों के बीच, आपके पास 0.98 मिलीसेकंड के भीतर सटीकता है - मैंने उस बिंदु को ध्वजांकित करने के लिए चुना जिस पर त्रुटि 1.00 मिलीसेकंड से अधिक है। लेकिन इस बिंदु को अच्छी तरह से लिया गया है - सभी तरह से सटीक गिरावट आती है, इसलिए अधिक सटीकता की आवश्यकता वाले कोड को पहले भी दुर्व्यवहार करना शुरू हो सकता है।
DMGregory

16

फ्लोट का अधिकतम मूल्य 3.40282347 * 10 ^ 38 है, जो सेकंड में मापा जाने पर 10 ^ 31 साल के बराबर होता है (या मिलीसेकंड में मापा जाने पर 28 साल)। मेरा विश्वास करो, यह अतिप्रवाह नहीं होगा।

केवल एक चीज जो प्रकट हो सकती है वह अशुद्धि है। लेकिन एकल सटीक फ्लोटिंग पॉइंट संख्या में 7-8 दशमलव अंकों की सटीकता होती है। अगर सेकंड्स को मापने के लिए इसका उपयोग किया जाता है, तो यह लगभग 194 दिनों के लिए सटीक है। यदि मिलीसेकंड को मापना केवल 4,5 घंटे के लिए सही है। तो यह पूरी तरह से आपकी जरूरत की सटीकता पर निर्भर करता है और अगर आपको मिलीसेकंड (जो आप शायद नहीं करते हैं) के लिए सटीक होने की आवश्यकता है, तो आपको वैकल्पिक तरीके खोजने की आवश्यकता हो सकती है।


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

1
@ Draco18s एकता के उपाय को परिभाषित करने के तरीके पर निर्भर करता है, लेकिन अगर वे प्रत्येक फ्रेम के लिए एक समय बिंदु लेते हैं और उन दो को घटाते हैं जो मुझे लगता है कि उत्तर निश्चित हां है।
ल्यूकजी

7
यह जवाब बिल्कुल भी सही नहीं है। आप एक प्रयोग चला सकते हैं। आप लूप में एक-एक करके फ्लोट कर सकते हैं। 10 000 000 तक पहुंचने के बाद यह वेतन वृद्धि रोक देगा। कारण यह है कि आप फ्लोट के साथ काम करते समय छोटी संख्या को बड़ी संख्या में सही ढंग से नहीं जोड़ सकते हैं। सही उत्तर एक @DMGregory
सीगल ने

2
@ सैगुल कहीं नहीं मैं वेतन वृद्धि के बारे में लिखता हूं। यह एक तथ्य है कि एक फ्लोट द्वारा प्रतिनिधित्व करने वाली अधिकतम संख्या 3,4 * 10 ^ 38 है, ताकि सख्त अर्थों में ओवरफ्लोिंग के नियमों का पालन किया जा सके (जैसा कि ओपी द्वारा माना जाता है)। मैं यह नहीं देखता कि खड़ा होने के कारण उत्तर गलत क्यों होगा?
ल्यूकजी

2
@Seagull मुझे लगता है कि ल्यूक का जवाब सही है (एडिट्स में सुधार से पहले भी) - उसका जवाब और मेरा सिर्फ जरूरतों के विभिन्न वर्गों को संदर्भित करता है। मुझे फ्लोट प्रिसिजन के बारे में जानकारी देना और मामलों को सीमित करना पसंद है, जबकि ल्यूक के मुद्दे पर थोड़ा और अधिक मोटे तौर पर सटीक सटीक आवश्यकताओं पर जोर देने के साथ दिखता है।
DMGregory

12

आपके खेल को कितनी सटीकता की आवश्यकता है?

32-बिट फ्लोट में सटीक के 24 बिट्स होते हैं। दूसरे शब्दों में, समय t पर, सटीकता 23 2 -23 × t है। (यह बिल्कुल सही नहीं है, लेकिन यह करीब है, और सटीक विवरण बहुत दिलचस्प नहीं हैं।)

  • यदि आपको 1ms परिशुद्धता की आवश्यकता है, तो 1ms 23 2 -23 = 8400 s = 2h 20 मीटर के बाद, 32-बिट फ्लोट अब स्वीकार्य नहीं है। अधिकांश खेलों के लिए 1ms की सटीकता आवश्यक नहीं है, लेकिन इसे संगीत अनुप्रयोगों के लिए आवश्यक माना जाता है।

  • यदि आपका गेम 144 हर्ट्ज मॉनिटर पर चलता है, और आप फ्रेम-सटीक ग्राफिक्स चाहते हैं, तो 1 H 144 हर्ट्ज 58 2 -23 = 58000 s = 16h के बाद, 32-बिट फ्लोट अब स्वीकार्य नहीं है। 16h एक खेल को चलाने के लिए एक लंबा समय है, लेकिन यह समझ से बाहर नहीं है। मुझे यकीन है कि हम में से एक महत्वपूर्ण प्रतिशत ने एक ही खंड में 16 घंटे तक एक खेल चलाया है - भले ही क्योंकि हमने खेल को छोड़ दिया और कुछ नींद मिली। उस समय, एनिमेशन और भौतिकी अद्यतन 144Hz से कम हो जाएंगे।

यदि यूनिटी की Time.deltaTimeगणना उच्च परिशुद्धता वाली घड़ी से की जाती है, तो आप इसका उपयोग कर सकते हैं और फिर भी पूरी सटीकता प्राप्त कर सकते हैं। मुझे नहीं पता कि यह सच है या नहीं।

पक्षीय लेख

विंडोज पर गेम और अन्य प्रोग्राम अक्सर GetTickCount()समय का पता लगाने के लिए उपयोग करते हैं। चूंकि यह मिलीसेकंड की गणना करने के लिए 32-बिट पूर्णांक का उपयोग करता है, यह लगभग 50 दिनों तक घूमता है, यदि आप अपने कंप्यूटर को उस समय तक छोड़ देते हैं। मुझे संदेह है कि यदि आप उन्हें 50-दिवसीय निशान पर खेल रहे थे, तो कई खेल विचित्र तरीके से लटकाएंगे, दुर्घटनाग्रस्त या दुर्व्यवहार करेंगे।

विंडोज की तरह, इंटीग्रर्स GetTickCount()में अतिप्रवाह का खतरा होता है, जबकि फ्लोट्स, जैसे कि यूनिटी के Time.timeपास सटीक खोने का जोखिम होता है।


10

अन्य उत्तर केवल अटकलें हैं, इसलिए मैंने एक सरल एकता परियोजना लिखी और इसे थोड़ी देर के लिए चलने दिया। कुछ घंटों के बाद यह परिणाम है:

  • UnityEngine.Time.timeसटीकता खो देता है बल्कि जल्दी। जैसा कि अपेक्षित था, 4 घंटे के लिए खेल चलाने के बाद मान 1 मिलीसेकंड से कूद जाते हैं, और उसके बाद अशुद्धि बढ़ जाती है।
  • UnityEngine.Time.deltaTimeएकता घंटों चलने के बाद भी अपनी प्रारंभिक उप-मिलीसेकंड सटीकता रखती है। इस प्रकार यह वस्तुतः गारंटी है कि deltaTimeएक प्लेटफ़ॉर्म-निर्भर उच्च रिज़ॉल्यूशन काउंटर (जो आमतौर पर 10-1000 वर्षों के बाद अतिप्रवाह) से प्राप्त होता है। एक छोटा जोखिम बना हुआ है जो deltaTimeअभी भी कुछ प्लेटफार्मों पर सटीक खो देगा।

समय की अशुद्धि सब कुछ के लिए एक मुद्दा है जो निर्भर करता है UnityEngine.Time.time। एक विशिष्ट उदाहरण रोटेशन (जैसे एक पवनचक्की) है, जो आमतौर पर आधारित है UnityEngine.Mathf.Sin(UnityEngine.Time.time*rotationSpeed)। यहां तक ​​कि एक मुद्दे का अधिक है _Timeजो स्पष्ट रूप से shaders द्वारा एनिमेशन के लिए उपयोग किया जाता है। ध्यान देने योग्य होने से पहले अशुद्धि कितनी अधिक होनी चाहिए? 20-30 एमएस सटीकता (2 दिन) वह बिंदु होना चाहिए, जहां लोग इस मुद्दे से अवगत हों, और ध्यान दें। 50-100 एमएस (5-10 दिन) संवेदनशील लोगों को जो समस्या के बारे में नहीं जानते हैं, वे इसे समझाना शुरू कर देंगे। 200-300 एमएस (20-30 दिन) से समस्या स्पष्ट हो जाएगी।

अब तक मैं की सटीकता का परीक्षण नहीं किया _SinTime, _CosTimeऔर Unity_DeltaTimeइसलिए मैं इन पर कोई टिप्पणी नहीं कर सकते हैं।

यह वह स्क्रिप्ट है जिसे मैंने परीक्षण के लिए उपयोग किया है। यह एक UI.Textतत्व से जुड़ा हुआ है , परियोजना की प्लेयर सेटिंग्स पृष्ठभूमि में प्रोजेक्ट को चलाने की अनुमति देती है, और गुणवत्ता सेटिंग्स में VSync हर दूसरे वी ब्लैंक पर सेट है:

public class Time : UnityEngine.MonoBehaviour {
    void Start () {
        LastTime = (double)UnityEngine.Time.time;
        StartTime =  System.DateTime.Now;
        LastPrintTime =  System.DateTime.Now;
    }
    double LastTime;
    System.DateTime StartTime;
    System.DateTime LastPrintTime;
    void Update () {
        double deltaTimeError = (double)UnityEngine.Time.deltaTime - ((double)UnityEngine.Time.time - LastTime);
        if (System.DateTime.Now - LastPrintTime  > System.TimeSpan.FromMilliseconds(1000))
        {
            GetComponent<UnityEngine.UI.Text>().text = "StartTime: " + StartTime.ToLongTimeString()
                + "\nCurrentTime: " + System.DateTime.Now.ToLongTimeString()
                + "\n\nTime.deltaTime: " + UnityEngine.Time.deltaTime.ToString("0.000000")
                + "\nTime.time - LastTime: " + ((float)(UnityEngine.Time.time - LastTime)).ToString("0.000000")
                + "\nAbsolute Error: " +  System.Math.Abs(deltaTimeError).ToString("0.000E0");
            LastPrintTime = System.DateTime.Now;
        }
        LastTime = UnityEngine.Time.time;       
    }
}

यहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें

यदि आप 0.033203मूल्य के बारे में सोच रहे हैं , तो मुझे पूरा यकीन है कि वास्तव में 0.033203125, जिसमें बाइनरी फ्लोटिंग पॉइंट प्रतिनिधित्व है 001111010000100000000000000000000मंटिसा में कई एस नोटिस ।

समाधान

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.