مسئلهای که باید حل میکردم
پنجرهٔ خرید، هشدار کمبود سکه و تنظیمات نباید هر کدوم چرخهٔ باز و بستهشدن متفاوتی بسازند. من رفتار مشترکی لازم داشتم که از متن و کار خود پنجره جدا باشد.
پیادهسازی در نسخهٔ فعلی
PopupController.OpenPopup بین نمونهٔ داخل صحنه و prefab تفاوت میگذارد. OpenAnimated و CloseAnimated حرکت و CanvasGroupها را کنترل میکنند؛ FinishClose طبق تنظیم یا نمونه را حذف میکنه یا غیرفعال میکنه.
تصمیم و هزینهٔ طراحی
کلیک بیرون با مستطیل پنل بررسی میشود و BringToFront ترتیب نمایش را اصلاح میکنه. PopupTextBinder متن را میگیرد، بنابراین نمایش مشترک به معنای پیام یکسان نیست.
مرزهای فعلی
شناسایی خودکار دکمهٔ بستن از نام یا برچسب، یک قرارداد شکننده هست. برای پنجرهٔ خاص باید سیمکشی آن را دید؛ حدس از اسم جای تأیید واقعی صحنه را نمیگیرد.
پنجرهٔ صحنه با نمونهٔ ساختهشده فرق داره
برای پنجرهٔ تنظیماتی که از قبل در صحنه هست، نگه داشتن همان نمونه پس از بسته شدن میتواند مناسب باشد. برای پیام ساختهشده از prefab، باقی گذاشتن هر نمونه ممکنه اشیای زائد بسازد. OpenPopup این دو حالت را با popupRoot.scene.IsValid تشخیص میدهد، برای prefab نمونه میسازد و destroyOnClose را بر اساس همین تفاوت میگذارد. این سیاست مالکیت مهم هست: ورودی پنجره فقط ظاهر آن را تعیین نمیکنه، بلکه روش پایان عمر آن را نیز مشخص میکنه. اگر parent داده بشه، شیء صحنه تنها در شرایط مشخص دوباره والدگذاری میشود.
CloseAnimated از اجرای همزمان بسته شدن دوباره با isClosing جلوگیری میکنه و انیمیشن فعال قبلی را متوقف میکنه. در FinishClose، click catcher بیرونی پاک میشود، alpha و مقیاس پایه برمیگردند و رخداد Closed منتشر میشود؛ سپس نمونه نابود یا غیرفعال میشود. ترتیب رخداد نسبت به نابودی برای مصرفکننده مهم هست، چون callback هنوز در همان چرخهٔ اجرای بستن فراخوانی میشود. یک پنجرهٔ بستهشونده نباید فقط کوچک بشه و در پسزمینه ورودی را ببلعد؛ تمیز کردن لایهٔ دریافت کلیک بخشی از رفتار رابط هست، نه جزئیات تزئینی انیمیشن.
OnPointerClick با RectangleContainsScreenPoint بررسی میکنه لمس بیرون panel بوده یا نه. این بررسی به مرجع درست panel و دوربین رویداد وابسته هست. همچنین WireButtons میتواند بر اساس closeOnAnyButtonClick همهٔ دکمهها را به بستن وصل کنه یا از قرارداد نام و متن برای پیدا کردن دکمهٔ بستن استفاده کنه. برای پنجرهای با چند عمل، این انتخاب باید آگاهانه باشد؛ دکمهٔ خرید و دکمهٔ خروج نقش یکسان ندارند. کلاس عمومی حرکت و پاکسازی را مشترک میکنه، اما معتبر بودن خرید، دریافت جایزه یا اقدام تنظیمات همچنان در سرویس و اتصال مخصوص همان پنجره تعیین میشود.
چیزی که از این مرحله یاد گرفتم
من ترجیح دادم چرخهٔ نمایش پنجره یک بار روشن بشه. بعد هر پیام بتواند دلیل و عمل خودش را داشته باشد، بدون اینکه منطق حرکت و تمیزکاری را دوباره بنویسم.
مثال عملی چرخهٔ پنجرهٔ رابط
اگر بخواهی چرخهٔ پنجرهٔ رابط را در یک پروژهٔ کوچک بررسی کنی، بهتر است از یک موقعیت محدود شروع کنی. یک پنجرهٔ تأیید را باز کن، ببند و دوباره با اطلاعات تازه باز کن. ورودی را ثابت نگه دار و نتیجهٔ مورد انتظار را پیش از اجرای نسخه بنویس. این کار کمک میکند تفاوت میان رفتار منطقی و چیزی که صرفاً روی صفحه دیده میشود روشن بماند. سناریوی این بخش آموزشی است و ادعای نتیجهٔ واقعی یک آزمایش روی کاربران دلو ندارد.
خطای رایج و علت آن
شنوندهٔ باقیمانده از دفعهٔ قبل ممکن است تأیید را چند بار اجرا کند. این خطا معمولاً وقتی پنهان میماند که فقط مسیر موفق و ظاهر نهایی را ببینیم. برای پیدا کردن علت، آخرین وضعیت درست را از نخستین وضعیت نادرست جدا کن و ببین تغییر دقیقاً در کدام مرز رخ داده است. آمادهسازی، نمایش، پاسخ و آزادسازی هر پنجره مسئولیتهای قابل تفکیک هستند. اگر این تفاوت در قرارداد مشخص نباشد، اصلاح یک نشانه ممکن است همان مسئله را در بخش دیگری دوباره ایجاد کند.
چطور نتیجه را بررسی کنیم؟
باز و بسته شدن مکرر نباید تعداد callbackها یا محتوای قدیمی را افزایش دهد. اجرای یکباره برای نتیجهگیری کافی نیست؛ یک بار مسیر معمول و بار دیگر همان موقعیت را با ورودی مرزی یا تکرار اقدام بررسی کن. اگر نتیجه فرق دارد، ورودی و شرایط اجرا را همراه خروجی نگه دار تا مقایسه قابل بازسازی باشد. جدول زیر خلاصهٔ مشخصات همین سناریو است و برای ثبت نتیجهٔ بررسی به کار میآید.
| بخش بررسی | آنچه باید ثبت شود |
|---|---|
| موقعیت آزمایشی | یک پنجرهٔ تأیید را باز کن، ببند و دوباره با اطلاعات تازه باز کن. |
| ریسک اصلی | شنوندهٔ باقیمانده از دفعهٔ قبل ممکن است تأیید را چند بار اجرا کند. |
| روش بررسی | باز و بسته شدن مکرر نباید تعداد callbackها یا محتوای قدیمی را افزایش دهد. |
| مرز نتیجهگیری | آمادهسازی، نمایش، پاسخ و آزادسازی هر پنجره مسئولیتهای قابل تفکیک هستند. |
پرسشهای کاربردی دربارهٔ چرخهٔ پنجرهٔ رابط
از کجا شروع کنم؟
از همان موقعیت محدود این مطلب شروع کن: یک پنجرهٔ تأیید را باز کن، ببند و دوباره با اطلاعات تازه باز کن. ابتدا نتیجهٔ مورد انتظار را مشخص کن و بعد سراغ پیادهسازی یا ابزار برو. وقتی مسیر پایه قابل توضیح و بررسی شد، میتوان حالتهای بیشتری اضافه کرد. ساخت همهٔ حالتها از ابتدا، فهم علت خطا را سختتر میکند.
چه زمانی میتوانم بگویم این بخش درست کار میکند؟
زمانی که رفتار در موقعیت تعریفشده با قرارداد سازگار باشد و محدودیتهای آن روشن بمانند. باز و بسته شدن مکرر نباید تعداد callbackها یا محتوای قدیمی را افزایش دهد. موفقیت در این آزمون دربارهٔ همان سناریو شاهد میدهد؛ از آن نمیتوان بدون بررسی دربارهٔ همهٔ دستگاهها، همهٔ قوانین محلی یا همهٔ حجمهای داده نتیجه گرفت. آمادهسازی، نمایش، پاسخ و آزادسازی هر پنجره مسئولیتهای قابل تفکیک هستند.
برای ادامهٔ همین موضوع، هستهٔ مشترک دلو؛ یک میز برای چند بازی و بازی دلو را ببین. زمینهٔ ساخت این پروژهها و معرفی سازنده در صفحهٔ کیان پاک نعمت آمده است.




