اصل ماجرا
در Unity برای اشیای کوتاهمدت مثل ذرات یا گلولهها، استفاده از Object Pooling میتونه خود یک گلوگاه بشه. مقاله نشان میدهد که با ساختار دادهای مبتنی بر struct و NativeArray، پردازش توسط Jobهای Burst انجام میشود و تخصیص حافظه حذف میشود. این روش باعث حذف GC، بهبود کشمحوری و استفاده بهینه از چند هستهای میشود.
متن کامل ترجمهشده
در تلاش برای عملکرد، جمع آوری اشیاء به مدت طولانی یک تکنیک پایه در توسعه بازی بوده است، به ویژه در Unity. ایده ساده است: استفاده دوباره از GameObjects پیش اختصاص داده شده برای اجتناب از برقراری و جمع آوری زباله (GC) انقباضات است. با این حال، برای اغلب اغلب، عناصر کوتاه عمر مانند انفجار ذرات، گلوله ها، یا بسیاری از شاخص های بصری، جمع آوری GameObjects نابینا می تواند به طور منحصر به فرد تبدیل شود. در حالی که ممکن است بلافاصله تماس های فوری را جلوگیری کند، اغلب فقط GC را با جمع آوری اشاره ها، کمک به فزاینده شدن حافظه، و ایجاد محتوای مهم GameObject برقراری که در هسته خود، فقط داده های واقعی است.این آموزشگاه یک رویکرد مبتنی بر داده ها را بررسی می کند: استفاده از ساختار C# در NativeArrays، پردازش شده توسط کارهای جمع آوری برش، برای رسیدن به عملکرد برتر با تفکر دوباره در مورد چگونگی مدیریت عناصر بازی انتقال یافته است. طراحی کد و راه رفتن: یک رویکرد مبتنی بر داده ها به جای GameObjects، ما بر داده های خام که عناصر انتقال یافته ما را تعریف می کند تمرکز می کنیم. بگذارید یک بمب یا یک قطعه را در نظر بگیریم. چه چیزی واقعا نیاز دارد؟ یک موقعیت، سرعت، و یک عمر باقی مانده است. 1. The struct: Your Lightweight Data Container The foundation is a simple C# struct. Structs are value types, meaning they are stored directly where they are declared, avoiding managed heapocations for individual instances. This is crucial for GCThe NativeArray: Unmanaged, Contiguous Memory Next، ما نیاز به یک راه برای ذخیره کردن بسیاری از این ساختار های ProjectileData به طور موثر. NativeArray URL_0 برای این کار مناسب است. آن را به یک بلوک متصل از حافظه غیر مدیریت، که به این معنی آن را از جمع کننده زباله به طور کامل عبور می کند و یک محل کیش عالی ارائه می دهد. شما به طور معمول مدیریت این NativeArray از یک MonoBehaviour، اختصاص آن را یک بار و اختصاص آن را هنگامی که دیگر لازم نیست: با استفاده از Unity.Collections; با استفاده از UnityEngine; کلاس عمومی ProjectileManager : MonoBehaur { خصوصی NativeArrayURL_1 _ileArray; خصوصی const intMaxProjectiles = 1000; خالی OnEnable() { // اختصاص یک بار، برایبه طور مداوم); // همه گلوله ها را به عنوان غیر فعال آغاز کنید (int i = 0; i < MaxProjectiles; i++) { _projectileArray[i] = new ProjectileData { IsActive = false }; } void OnDisable() { if (_projectileArray.IsCreated) { _projectileArray.Dispose(); // Remember to dispose unmanaged memory } } } // … منطق به “spawn” گلوله ها با پیدا کردن یک غیر فعال است و تنظیم داده های آن } 3. The Burst-Compiled Job: Processing Data Direct Now for processing. Instead of looping through GameObjects and calling methods on components, we create a Burst-compiled job that directly manipulates the data within the NativeArray. using Unity.Burstبا توجه به این که در این مقاله می خوانیم، می توانیم به این نکته اشاره کرد که در این مقاله می توانیم به این نکته اشاره کرد که در این مقاله می توانیم به این نکته اشاره کرد که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکته اشاره کنیم که در این مقاله می توانیم به این نکتهبرنامه ریزی(MaxProjectiles، 64)؛ // 64 با استفاده از چیزی مانند Graphics.DrawMeshInstanced // و یا ECS Hybrid Renderer، از GameObject Instantiation به طور کامل اجتناب می کند. // خلاصه با استفاده از این رویکرد مبتنی بر داده ها، شما بر روی عمده اصلی GameObjects، اجزای، و عمده ای از کارهای مدیریت می پردازید. - مزایای عمیق است: - Zero GC Allocations: structsandNativeArrays خارج از عمده ای که مدیریت می شود کار می کنند. - عملکرد فوق العاده: NativeArrays دارای حافظه دوستانه و همراهی را فراهم می کند.- اندازه گیری: سیستم وظیفه به طور خودکار بار کار را در سراسر هسته های CPU موجود توزیع می کند، اجازه می دهد تعداد ذرات بزرگ یا تعامل های پیچیده بدون کاهش عملکرد را. - تحسین واقعی: شما فقط جمع آوری زباله را متوقف نمی کنید؛ شما آن را برای این مسیر های گرم حذف می کنید، که منجر به نرخ فریم نرم تر و عملکرد قابل پیش بینی تر می شود. در حالی که این نماد یک توپ نقره ای برای هر سناریو نیست، برای عناصر بازی با سرعت بالا و بیهوده که در آن هر میلی ثانیه و بیتی حساب می شود، ارزشمند است. ساختار ها، NativeArrays، و کارهای Burst را به طور واقعی به حداکثر عملکرد از سیستم وظیفه ی Unity بزنید و بازی های ایجاد کنید که مرزهای پاسخگویی و مقیاس را گسترش می دهند.
چرا مهمه؟
پولینگ ساده فقط فراخوانی Instantiate رو کم میکنه، اما هنوز اشیای مدیریتشده و جمعآوری زباله رو نگه میداره؛ در پروژههای پر ذره یا پرگلوله، این باعث لگ و پاره شدن فریم میشود. توسعهدهندگان بازی، بهویژه کسانی که با Unity کار میکنند، تحت تأثیر این روش قرار میگیرند چون میتوانند فریمریت ثابتتری داشته باشند. خواننده باید این خبر را جدی بگیرد چون با تغییر به ساختار دادهای میتواند هزینههای حافظه و زمان پردازش را بهطور چشمگیری کاهش دهد.
به درد کی میخوره؟
• توسعهدهندگان Unity • برنامهنویسان گیمپلی • مهندسان بهینهسازی عملکرد • تیمهای فنی بازیهای موبایل
تو عمل چی کار کنیم؟
بعد از مطالعه میتوانید یک NativeArray برای دادههای موقت مثل ذرات یا گلولهها بسازید و یک Job Burst‑کامپایلشده برای بهروزرسانی موقعیت و زمان عمر بنویسید. این کار باعث میشود بازیتان بدون توقفهای GC اجرا شود و میتوانید تعداد اشیای همزمان را بهطور قابلتوجهی افزایش دهید.
نظر Blue IT News
پیشنهاد میشود قبل از پیادهسازی، یک پروفایل ساده بگیرید تا ببینید هزینه GC چقدر است؛ سپس به تدریج بخشهای پرسرعت را به Data‑Oriented تبدیل کنید.
این صفحه ترجمه و تفسیر کاملی از گزارش اصلی Dev است که توسط تیم تحریریه بلو آی تی نیوز به فارسی ترجمه و تحلیل شده. برای مشاهده نسخه اصلی، به منبع مراجعه کنید.