The Block · Unity 6
An Israeli GTA-style 3D mini open world built in Unity 6 (URP) and shipped as a desktop app for macOS and Windows. Four diagrams: what the game calls while you play, the order the engine calls it in every frame, what the Editor does long before the game runs, and the AI toolchain that drives all of it.
עולם פתוח קטן בתלת-ממד, ישראלי ובסגנון GTA, שנבנה ב-Unity 6 (URP) ונארז כאפליקציית שולחן עבודה ל-macOS ול-Windows. ארבעה תרשימים מסבירים אותו: במה המשחק משתמש בזמן שמשחקים בו, באיזה סדר המנוע קורא לכל חלק בכל פריים, מה קורה בעורך הרבה לפני שהמשחק בכלל רץ, ומהי שרשרת כלי ה-AI שמניעה את כל אלה.
1 - Runtime
1 - זמן ריצה
The whole game is one desktop process - a .app bundle on macOS, a
folder beside TheBlockUnity.exe on Windows. There is no server, no database, no
login and no LLM at runtime - and no network at all: nothing is fetched while you play, because
every mesh, texture, clip and scene is already inside the build. The game talks to Unity's own
subsystems and to nothing else.
כל המשחק הוא תהליך שולחני יחיד - חבילת .app ב-macOS, ותיקייה
שיושבת לצד TheBlockUnity.exe ב-Windows. אין שרת, אין בסיס נתונים, אין התחברות
ואין מודל שפה בזמן ריצה - ולמעשה אין רשת בכלל: שום דבר לא נמשך מהאינטרנט בזמן המשחק, מפני שכל
מודל, טקסטורה, קליפ אנימציה וסצנה כבר ארוזים בתוך הבילד עצמו. המשחק מדבר רק עם תת-המערכות של
Unity, ועם שום דבר מעבר להן.
Most of what is installed is Editor-side; six subsystems do work while the game is running. The
one API that reaches the disk is PlayerPrefs, and it holds eleven fixed keys plus
three that expand per item. It is also the only line in the diagram whose destination is
OS-specific: a plist under ~/Library/Preferences on macOS, a registry key under
HKCU\Software on Windows. Unity decides that, not the game.
רוב מה שמותקן בפרויקט חי בצד העורך בלבד; רק שש תת-מערכות עושות עבודה בפועל בזמן שהמשחק רץ.
ה-API היחיד שנוגע בדיסק הוא PlayerPrefs, והוא מחזיק אחד-עשר מפתחות קבועים ועוד
שלושה שמתרבים לפי מספר הפריטים (מכונית שנצבעה, שדרוג שנקנה). זו גם השורה היחידה בתרשים שהיעד
שלה משתנה בין מערכות הפעלה: קובץ plist תחת ~/Library/Preferences ב-macOS, ומפתח
ברג׳יסטרי תחת HKCU\Software ב-Windows. Unity היא שקובעת את זה, לא קוד המשחק.
UnityWebRequest anywhere in the codebase, and nothing that can 404.
UnityWebRequest אחת בכל הקוד, ואין שום דבר שיכול להיכשל בשגיאת 404.
One codebase, two Players. Nothing above is written twice: same C#, same
scenes, same assets, and Mono on both - IL2CPP for Windows wants the Visual
Studio toolchain on Windows itself, so a Mac host builds Mono or nothing. What genuinely
differs is the shader set, which recompiles Metal → Direct3D at build time;
that was the one real risk, and the runtime Shader.Find list carried across, which
is why the Windows build draws a city rather than magenta. The rest is packaging: macOS is a
universal binary (x86_64 + arm64) in a single bundle, Windows is an
Intel 64-bit folder that reaches ARM machines through emulation, and because neither is
code-signed each meets its own OS's gatekeeper - quarantine on macOS, SmartScreen on Windows.
בסיס קוד אחד, שני Players. שום דבר ממה שלמעלה לא נכתב פעמיים: אותו קוד C#,
אותן סצנות, אותם אסטים, ו-Mono בשתי הפלטפורמות - כדי לבנות IL2CPP ל-Windows
דרושה שרשרת הכלים של Visual Studio על מכונת Windows אמיתית, ולכן מארח Mac יכול לבנות Mono או
לא לבנות בכלל. מה שכן שונה באמת הוא סט השיידרים, שמתקמפל מחדש מ-Metal ל-Direct3D
בזמן הבנייה; זה היה הסיכון האמיתי היחיד במעבר, ורשימת Shader.Find של זמן הריצה
עברה בשלמותה - ולכן בילד ה-Windows מצייר עיר ולא משטחי מג׳נטה. כל השאר הוא אריזה בלבד: ב-macOS
זהו בינארי אוניברסלי (x86_64 יחד עם arm64) בתוך חבילה אחת, ב-Windows
זו תיקייה של Intel 64-bit שרצה על מכונות ARM דרך אמולציה, ומכיוון ששניהם אינם חתומים דיגיטלית
כל אחד מהם נתקל במנגנון ההגנה של מערכת ההפעלה שלו - הסגר (quarantine) ב-macOS, ו-SmartScreen
ב-Windows.
2 - Flow
2 - זרימה
The game has two scenes: Boot.unity, which is a bar and nothing else, and
World.unity, which is the entire city. BootLoader drives the handoff,
and the four numbers below were measured on the Player, not guessed.
למשחק יש שתי סצנות בלבד: Boot.unity, שאינה אלא פס טעינה, ו-World.unity,
שהיא כל העיר כולה. BootLoader אחראי על המעבר ביניהן, וארבעת המספרים שלמטה נמדדו על
הבילד הסופי עצמו, לא נוחשו.
SessionReset.Run() in Awake, before the load - a Quit to
Title comes back through this scene with the previous world's registries still populated.
SceneManager.LoadSceneAsync("World") with
allowSceneActivation = false. Unity stops a held load at
progress == 0.9, which maps cleanly onto a bar that caps itself at 99 %.
~2.2 s, and it is one blocked frame: deserializing a 7.8 MB scene.
Awake in the world at once - then
the texture upload, ~1.9 s, and the first frame with real geometry.
GameFlow shows the title menu at Time.timeScale = 0.
The title screen is not a scene: it is a UI Toolkit overlay on the loaded,
frozen city, so it costs nothing to leave.
SessionReset.Run() בתוך Awake, לפני תחילת הטעינה -
מפני שיציאה מהמשחק חזרה לתפריט הראשי עוברת שוב דרך הסצנה הזו, כשהרישומים של העולם הקודם עדיין
מלאים בנתונים ישנים.
SceneManager.LoadSceneAsync("World") עם
allowSceneActivation = false. Unity עוצרת טעינה מוחזקת בדיוק ב-progress ==
0.9, וזה מתמפה יפה לפס התקדמות שנעצר מעצמו על 99%. השלב אורך כ-2.2 שניות,
והוא פריים חסום אחד ארוך: פענוח הסריאליזציה של סצנה במשקל 7.8 MB.
Awake בעולם רצות
בבת אחת - ואחריה העלאת הטקסטורות לזיכרון הכרטיס, כ-1.9 שניות, ואז הפריים
הראשון עם גאומטריה אמיתית על המסך.
GameFlow מציג את התפריט הראשי בזמן ש-Time.timeScale = 0.
מסך הפתיחה אינו סצנה נפרדת: הוא שכבת UI Toolkit שמצוירת מעל העיר הטעונה
והקפואה, ולכן היציאה ממנו אל תוך המשחק אינה עולה זמן טעינה כלל.
Every panel in UI/Menus is dumb: it draws itself and raises a callback.
GameFlow owns all the decisions - who is on screen, what Esc does, and
when the clock starts. Continue reads PlayerPrefs and restores the
unlocked mission; New Game clears it. Then timeScale goes to 1 and the loop
below starts running for real.
כל פאנל בתיקייה UI/Menus הוא "טיפש" בכוונה: הוא רק מצייר את עצמו ומרים callback
כשלוחצים עליו. GameFlow הוא זה שמחזיק את כל ההחלטות - מי מוצג על המסך, מה מקש
Esc עושה בכל רגע, ומתי שעון המשחק מתחיל לרוץ. המשך משחק קורא את
PlayerPrefs ומשחזר את המשימה האחרונה שנפתחה; משחק חדש מוחק אותם. משם
timeScale עולה ל-1 והלולאה שמתוארת למטה מתחילה לרוץ באמת.
[DefaultExecutionOrder(1000)] to run last within its slot.
[DefaultExecutionOrder(1000)] מפורש כדי לרוץ אחרון
בתוך המשבצת שלו.
Three systems worth naming, because they are what the boxes above are mostly running:
CampaignRunner is the campaign's single reactor - cursor, police rules, retry key,
payout, HUD lines - and owns no gameplay of its own; a mission spawns its own actors and is only
ever asked for a MissionStatus. CrimeWatch and Heat hold
the wanted level, and PoliceSystem spawns cop cars that drive on PhysX wheels while
the officer who gets out walks on a NavMeshAgent. TrafficSystem and
CrowdSpawner keep the city populated around the player and recycle everything
behind them.
שלוש מערכות ראויות לשם מפורש, מפני שהן מה שהתיבות שלמעלה מריצות רוב הזמן:
CampaignRunner הוא הריאקטור היחיד של הקמפיין - הסמן על המפה, חוקי המשטרה, מקש
הניסיון החוזר, התשלום בסוף המשימה ושורות ה-HUD - ואין לו גיימפליי משל עצמו; כל משימה יוצרת את
השחקנים והאובייקטים שלה, ונשאלת רק על MissionStatus - האם היא רצה, הצליחה או
נכשלה. CrimeWatch ו-Heat יחד מחזיקים את רמת המבוקשות, ו-PoliceSystem
מייצר ניידות שנוסעות על גלגלי PhysX, בעוד שהשוטר שיוצא מהנידת הולך על NavMeshAgent.
TrafficSystem ו-CrowdSpawner דואגים שהעיר תהיה מאוכלסת סביב השחקן,
וממחזרים כל מכונית והולך רגל שנשארו מאחוריו.
3 - Editor time
3 - זמן עורך
In a browser build, loading art is a runtime problem. In Unity it is an import problem,
and that is where most of this project's tooling lives: 54 Editor scripts, 20,602
lines, exposing a 52-item The Block menu. Those builders
are the reason the scene is reproducible - the city, the cars, the HUD, the missions and the
police are all generated by a menu item from constants in TheBlockConfig, never
dragged into place by hand.
בבילד לדפדפן, טעינת האמנות היא בעיה של זמן ריצה. ב-Unity זו בעיה של ייבוא, ושם יושב רוב
הכלים שנכתבו לפרויקט הזה: 54 סקריפטים של העורך, 20,602 שורות, שחושפים
תפריט The Block בן 52 פריטים. הבנאים האלה הם הסיבה שהסצנה ניתנת
לשחזור מלא - העיר, המכוניות, ה-HUD, המשימות והמשטרה כולם נוצרים בלחיצה על פריט תפריט, מתוך
קבועים שיושבים ב-TheBlockConfig, ואף אחד מהם לא נגרר למקומו ביד.
.glb have no importer of their own, so they stay uncompressed
until Compress Textures extracts them and
Rebind Compressed Textures points every prefab and material at the extracted copy;
and importers, not menu passes, hold the settings - a Library wipe re-imports from the
.meta, so anything applied once by hand quietly reverts. The last step is the one
place the two platforms are not symmetric: the macOS Player is scripted -
PlayerBuilder pins the scene list and the output folder, and refuses to run when
the active target is not StandaloneOSX - while the Windows Player is a platform
switch plus File ▸ Build Settings, with the output folder typed into a save panel
by hand.
.glb אין importer משלהן, ולכן הן נשארות ללא דחיסה עד ש-Compress
Textures מחלץ אותן לקבצים נפרדים ו-Rebind Compressed Textures מפנה כל
prefab וכל חומר אל העותק המחולץ; ובנוסף, ה-importer הוא זה שמחזיק את ההגדרות ולא מעבר תפריט
חד-פעמי - מחיקה של תיקיית Library מייבאת הכול מחדש מתוך קובצי ה-.meta,
ולכן כל הגדרה שהוחלה פעם אחת ביד פשוט חוזרת בשקט למצבה הקודם. הצעד האחרון הוא המקום היחיד שבו
שתי הפלטפורמות אינן סימטריות: ה-Player של macOS נבנה מתוך סקריפט - PlayerBuilder
מקבע את רשימת הסצנות ואת תיקיית הפלט, ומסרב לרוץ אם היעד הפעיל אינו StandaloneOSX -
בעוד שה-Player של Windows נבנה בהחלפת פלטפורמה ידנית ואז File ▸ Build Settings,
כשתיקיית הפלט מוקלדת ביד בחלון השמירה.
4 - Toolchain
4 - שרשרת הכלים
The course's subject is building with AI, so this is not a footnote: the Editor, Blender and the measurement runs are all driven from one Claude Code session over the Model Context Protocol. Two MCP servers are connected, and each is a real process on the machine rather than a cloud service - nothing here is a paid tier: no Unity Cloud, no Asset Store, no Unity AI credits.
נושא הקורס הוא בנייה בעזרת AI, ולכן זו לא הערת שוליים אלא חלק מהארכיטקטורה: העורך של Unity, Blender והרצות המדידה מונעים כולם מתוך סשן אחד של Claude Code, דרך Model Context Protocol - פרוטוקול שמאפשר למודל להפעיל כלים חיצוניים. שני שרתי MCP מחוברים, וכל אחד מהם הוא תהליך אמיתי שרץ על המחשב עצמו ולא שירות ענן - שום דבר כאן אינו שירות בתשלום: לא Unity Cloud, לא Asset Store, ולא קרדיטים של Unity AI.
PerfProbe and reduced by perf-report.py - and
FrameWatchdog stays compiled into development builds to catch the hitch that only
happens when nobody is watching. Source control is git + Git LFS to a private GitHub repo; the
kanban board is pushed to Trello's REST API from a JSON source of truth.
PerfProbe וצומצם לדוח על ידי
perf-report.py - ו-FrameWatchdog נשאר מקומפל בתוך בילדים של פיתוח
כדי לתפוס בדיוק את הקפיצה שקורית רק כשאף אחד לא מסתכל. ניהול הגרסאות הוא git יחד עם Git LFS
אל מאגר GitHub פרטי; ולוח הקנבן נדחף אל ה-REST API של Trello מתוך קובץ JSON שהוא מקור האמת.
Where the two engines meet. Physics constants do not port: PhysX is not
Rapier, so every mass, friction and suspension number here was re-derived by feel. What ported
is the game - the map, the missions, the payouts and the feel - through
TheBlockConfig, one static class of constants that every Editor builder reads.
איפה שני המנועים נפגשים. קבועי פיזיקה אינם ניתנים להעברה: PhysX אינו Rapier,
ולכן כל ערך של מסה, חיכוך ומתלה כאן נגזר מחדש לפי תחושת נהיגה ולא הועתק. מה שכן עבר בשלמותו
הוא המשחק עצמו - המפה, המשימות, התשלומים והתחושה הכללית - דרך TheBlockConfig,
מחלקה סטטית אחת של קבועים שכל בנאי בעורך קורא ממנה.
Inventory
מלאי
| Name | What it is | When it is called |
|---|---|---|
| Unity 6000.5.8f1 | The engine and its frame loop; Mono scripting backend, macOS and Windows Standalone | From launch to quit - it calls the game, not the reverse |
| URP 17.5 | Universal Render Pipeline on Metal (macOS) or Direct3D (Windows); one main directional light, no bloom | Last step of every frame; DayNightCycle rewrites its lighting |
| PhysX | Rigidbody, WheelCollider, colliders, raycasts, ragdolls |
FixedUpdate at a fixed 0.02 s step - 50 Hz |
| Input System 1.20 | Polled directly through Keyboard.current - no callbacks, no rebinding |
Every Update, in whichever mode owns input |
| Mecanim (Animator) | Humanoid state machines for the player, pedestrians and cops | Engine-driven, between Update and LateUpdate |
| AI Navigation 2.0 | NavMesh baked from the city; NavMeshAgent on foot actors |
Pedestrian wandering; a cop leaving the car to make an arrest |
| UI Toolkit | HUD, map, title, pause, settings, shop, paint - built in C#, zero UXML/USS | Panels on demand; HUD latches every frame in LateUpdate |
| Audio + AudioMixer | Master plus 6 buses; 27 clips across Voice / Music / Engine / Ambient / Sfx | Per game event; the mixer is built by an Editor tool, not by hand |
AudioClip.Create |
The UI cues, synthesised to PCM once and cached as ordinary clips | First time each cue is asked for, then never again |
RenderTexture |
A second orthographic camera renders the minimap | LateUpdate, before the main camera draws |
PlayerPrefs |
The save: mission unlocks, character, and every settings toggle. A plist on macOS, a registry key on Windows | On every change - 11 fixed theblock.* keys, plus one per painted car and per power-up |
ProfilerRecorder |
FrameWatchdog and PerfProbe read the engine's own counters |
Development builds only, behind DEVELOPMENT_BUILD |
| שם | מה זה | מתי זה נקרא |
|---|---|---|
| Unity 6000.5.8f1 | המנוע ולולאת הפריים שלו; מנגנון סקריפטים Mono, ובילד Standalone ל-macOS ול-Windows | מרגע ההפעלה ועד היציאה - הוא קורא למשחק, לא להפך |
| URP 17.5 | Universal Render Pipeline מעל Metal (macOS) או Direct3D (Windows); אור כיווני ראשי אחד, בלי bloom | השלב האחרון בכל פריים; DayNightCycle משכתב את התאורה שלו לפי שעת היום |
| PhysX | Rigidbody, WheelCollider, קוליידרים, קרני raycast ובובות ragdoll |
ב-FixedUpdate, בצעד קבוע של 0.02 שנייה - כלומר 50 פעמים בשנייה |
| Input System 1.20 | נדגם ישירות דרך Keyboard.current - בלי callbacks ובלי מיפוי מקשים מחדש |
בכל Update, במצב שמחזיק כרגע את הקלט (נהיגה, הליכה, תפריט) |
| Mecanim (Animator) | מכונות מצבים לדמויות Humanoid - השחקן, הולכי הרגל והשוטרים | מונע על ידי המנוע, בין Update ל-LateUpdate |
| AI Navigation 2.0 | NavMesh שנאפה מגאומטריית העיר; NavMeshAgent על כל דמות שהולכת ברגל |
שיטוט של הולכי רגל; ושוטר שיוצא מהניידת כדי לבצע מעצר |
| UI Toolkit | HUD, מפה, מסך פתיחה, השהיה, הגדרות, חנות וצביעה - הכול בנוי בקוד C#, בלי UXML/USS | פאנלים לפי דרישה; ה-HUD מתעדכן בכל פריים בתוך LateUpdate |
| Audio + AudioMixer | ערוץ Master ועוד 6 ערוצים; 27 קליפים המחולקים ל-Voice / Music / Engine / Ambient / Sfx | לפי אירועי משחק; המערבל עצמו נבנה על ידי כלי בעורך, לא ביד |
AudioClip.Create |
צלילי הממשק, שמסונתזים ל-PCM פעם אחת ונשמרים במטמון ככל קליפ רגיל | בפעם הראשונה שמבקשים כל צליל, ואחר כך אף פעם לא שוב |
RenderTexture |
מצלמה אורתוגרפית שנייה שמרנדרת את המפה הקטנה | ב-LateUpdate, לפני שהמצלמה הראשית מציירת |
PlayerPrefs |
קובץ השמירה: משימות שנפתחו, הדמות הנבחרת וכל מתגי ההגדרות. קובץ plist ב-macOS, מפתח רג׳יסטרי ב-Windows | בכל שינוי - 11 מפתחות theblock.* קבועים, ועוד אחד לכל מכונית שנצבעה ולכל שדרוג |
ProfilerRecorder |
FrameWatchdog ו-PerfProbe קוראים את מוני הביצועים של המנוע עצמו |
בבילדים של פיתוח בלבד, מאחורי DEVELOPMENT_BUILD |
| Name | What it is | When it runs |
|---|---|---|
| The Block menu | 52 menu items over 54 Editor scripts that generate the entire scene from code | On demand - Build World, Build Menus, Build Police Car, … |
| glTFast 6.19 + Draco 5.4 | glTF/GLB import: meshes, materials, Draco-compressed geometry | Asset import, in the Editor. Never at runtime |
| Custom AssetPostprocessors | Audio, texture and character import settings that survive a Library wipe | Automatically, on every (re)import |
| Splines 2.9 | Road and lot curves used while generating the world | WorldBuilder only - build time, not play time |
| MCP for Unity 10.1 | Local JSON-RPC bridge that lets Claude Code drive the Editor | Throughout development, 127.0.0.1:8080 |
BuildPipeline.BuildPlayer |
Scripted macOS build, release and development, with the scene list pinned; the Windows Player is built from the stock dialog | The Block ▸ Build macOS Player; Windows: switch platform, then File ▸ Build Settings |
| git + Git LFS | Version control; LFS carries every model, texture and clip | Every commit - the ledger records the hash per unit |
| Trello REST API | The kanban board, pushed from a JSON source of truth - 117 cards | tools/kanban/push-to-trello.mjs, on demand |
| שם | מה זה | מתי זה רץ |
|---|---|---|
| תפריט The Block | 52 פריטי תפריט מעל 54 סקריפטים של העורך, שמייצרים את כל הסצנה מתוך קוד | לפי דרישה - Build World, Build Menus, Build Police Car, … |
| glTFast 6.19 + Draco 5.4 | ייבוא glTF/GLB: גאומטריה, חומרים וגאומטריה דחוסה ב-Draco | בזמן ייבוא האסט, בתוך העורך. לעולם לא בזמן ריצה |
| AssetPostprocessors מותאמים | הגדרות ייבוא לשמע, לטקסטורות ולדמויות ששורדות מחיקה של תיקיית Library |
אוטומטית, בכל ייבוא וייבוא מחדש |
| Splines 2.9 | עקומות של כבישים ומגרשי חנייה, שמשמשות בזמן יצירת העולם | ב-WorldBuilder בלבד - בזמן בנייה, לא בזמן משחק |
| MCP for Unity 10.1 | גשר JSON-RPC מקומי שמאפשר ל-Claude Code להפעיל את העורך | לאורך כל הפיתוח, על 127.0.0.1:8080 |
BuildPipeline.BuildPlayer |
בנייה מתוסרטת ל-macOS, בגרסת release ובגרסת פיתוח, עם רשימת סצנות מקובעת; ה-Player של Windows נבנה מחלון הבנייה הרגיל | The Block ▸ Build macOS Player; ל-Windows: החלפת פלטפורמה ואז File ▸ Build Settings |
| git + Git LFS | ניהול גרסאות; LFS נושא כל מודל, טקסטורה וקליפ | בכל קומיט - היומן רושם את ה-hash של כל יחידת עבודה |
| Trello REST API | לוח הקנבן, שנדחף מתוך קובץ JSON שהוא מקור האמת - 117 כרטיסים | tools/kanban/push-to-trello.mjs, לפי דרישה |
| Name | What it is | When it runs |
|---|---|---|
| Claude Code (Opus 5) | Writes the C#, drives every tool below, and maintains the project's decision ledger | Continuously, through the whole port |
| Blender + Blender MCP | Mesh repair, decimation, merges and FBX→GLB, driven over MCP | Whenever a model needs work Unity's importer cannot do |
tools/*.py |
Headless Blender scripts: decimate, convert, prep props, build the falafel stand | Once per asset, from the shell |
| Mixamo | Humanoid rigs and animation clips; imported as Humanoid so the bone prefix drops | Sourcing only |
| Sketchfab · Quaternius · Kenney | CC0 districts, vehicles and street props | Sourcing only |
perf-sweep.sh + perf-report.py |
Launches the built Player 44 times unattended and reduces the CSVs | Once per performance question |
pixel-diff.py |
Compares two renders against a measured noise floor - animated water differs from itself | When a visual change has to be proven, not claimed |
| שם | מה זה | מתי זה רץ |
|---|---|---|
| Claude Code (Opus 5) | כותב את קוד ה-C#, מפעיל את כל הכלים שלמטה, ומתחזק את יומן ההחלטות של הפרויקט | ברציפות, לאורך כל תהליך ההמרה למנוע החדש |
| Blender + Blender MCP | תיקון רשתות, הפחתת פוליגונים, מיזוגים והמרת FBX ל-GLB, הכול מונע דרך MCP | בכל פעם שמודל דורש טיפול שה-importer של Unity לא יודע לעשות |
tools/*.py |
סקריפטים של Blender ללא ממשק: הפחתה, המרה, הכנת אביזרים ובניית דוכן הפלאפל | פעם אחת לכל אסט, משורת הפקודה |
| Mixamo | שלדים וקליפים של אנימציה לדמויות; מיובאים כ-Humanoid כדי שקידומת שמות העצמות תיפול | לצורך מקורות בלבד |
| Sketchfab · Quaternius · Kenney | שכונות, כלי רכב ואביזרי רחוב ברישיון CC0 | לצורך מקורות בלבד |
perf-sweep.sh + perf-report.py |
מריץ את הבילד הבנוי 44 פעמים ללא השגחה, ומצמצם את קובצי ה-CSV לדוח אחד | פעם אחת לכל שאלת ביצועים |
pixel-diff.py |
משווה שני רינדורים מול רצפת רעש מדודה - מים מונפשים שונים אפילו מעצמם | כששינוי חזותי צריך להיות מוכח ולא רק מוצהר |