The Block · Unity 6

APIs, tools & libraries - and the flow between them

ממשקי API, כלים וספריות - והזרימה ביניהם

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 - זמן ריצה

What the app actually calls while you play

במה האפליקציה באמת משתמשת בזמן המשחק

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 היא שקובעת את זה, לא קוד המשחק.

The Block macOS .app · Windows folder Standalone, Mono 2.1 GB each launch One process - no server · no request · no LLM Unity engine loop 60 fps target, vSync off URP 17.5 Metal · Direct3D 1 main light PhysX cars, bodies 50 Hz step Input polled keys Keyboard Mecanim + NavMesh rigs, agents UI Toolkit HUD, menus C#, no UXML Audio 7 mixer buses 27 clips the one call that reaches the disk PlayerPrefs theblock.unlocked · theblock.cash · theblock.character · … 11 keys - mission unlocks, cash, settings. The only state that outlives the process. The Block ‏חבילת macOS · תיקיית Windows Standalone, Mono 2.1 GB כל אחת הפעלה תהליך אחד - בלי שרת · בלי בקשות רשת · בלי מודל שפה לולאת המנוע של Unity יעד 60 fps, ‏vSync כבוי URP 17.5 Metal · Direct3D אור ראשי אחד PhysX רכבים, גופים צעד 50 Hz קלט דגימת מקשים Keyboard Mecanim + NavMesh שלדים, סוכנים UI Toolkit ‏HUD, תפריטים ‏C#‎, בלי UXML שמע 7 ערוצי מערבל 27 קליפים הקריאה היחידה שמגיעה לדיסק PlayerPrefs theblock.unlocked · theblock.cash · theblock.character · … 11 מפתחות - פתיחת משימות, כסף, הגדרות. המצב היחיד ששורד אחרי סגירת התהליך.
A browser build has to fetch its world; this one does not. Everything the game needs was resolved at import and build time (diagram 3), so at play time there is no loader, no UnityWebRequest anywhere in the codebase, and nothing that can 404.
בילד לדפדפן חייב למשוך את העולם שלו מהרשת תוך כדי משחק; הבילד הזה לא. כל מה שהמשחק צריך כבר נפתר בזמן הייבוא ובזמן הבנייה (תרשים 3), ולכן בזמן משחק אין מנגנון טעינה, אין ולו קריאת 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 - זרימה

Which API is called, and when

איזה API נקרא, ומתי

Phase A - boot, behind the loading bar

שלב א׳ - עלייה, מאחורי פס הטעינה

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 אחראי על המעבר ביניהן, וארבעת המספרים שלמטה נמדדו על הבילד הסופי עצמו, לא נוחשו.

  1. ~1.9 s - Unity's own startup: Metal or Direct3D, Mono, PhysX, subsystems. No script of mine has run yet.
  2. SessionReset.Run() in Awake, before the load - a Quit to Title comes back through this scene with the previous world's registries still populated.
  3. 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.
  4. Activation - 245 ms for every Awake in the world at once - then the texture upload, ~1.9 s, and the first frame with real geometry.
  5. 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.
  1. כ-1.9 שניות - העלייה של Unity עצמה: אתחול Metal או Direct3D, ‏Mono, ‏PhysX ושאר תת-המערכות. בשלב הזה אף שורת קוד שלי עוד לא רצה.
  2. קריאה ל-SessionReset.Run() בתוך Awake, לפני תחילת הטעינה - מפני שיציאה מהמשחק חזרה לתפריט הראשי עוברת שוב דרך הסצנה הזו, כשהרישומים של העולם הקודם עדיין מלאים בנתונים ישנים.
  3. קריאה ל-SceneManager.LoadSceneAsync("World") עם allowSceneActivation = false. ‏Unity עוצרת טעינה מוחזקת בדיוק ב-progress == 0.9, וזה מתמפה יפה לפס התקדמות שנעצר מעצמו על 99%. השלב אורך כ-2.2 שניות, והוא פריים חסום אחד ארוך: פענוח הסריאליזציה של סצנה במשקל 7.8 MB.
  4. ההפעלה עצמה - 245 מילישניות שבהן כל קריאות ה-Awake בעולם רצות בבת אחת - ואחריה העלאת הטקסטורות לזיכרון הכרטיס, כ-1.9 שניות, ואז הפריים הראשון עם גאומטריה אמיתית על המסך.
  5. ‏GameFlow מציג את התפריט הראשי בזמן ש-Time.timeScale = 0. מסך הפתיחה אינו סצנה נפרדת: הוא שכבת UI Toolkit שמצוירת מעל העיר הטעונה והקפואה, ולכן היציאה ממנו אל תוך המשחק אינה עולה זמן טעינה כלל.

Phase B - menu

שלב ב׳ - תפריט

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 והלולאה שמתוארת למטה מתחילה לרוץ באמת.

Phase C - every frame

שלב ג׳ - כל פריים ופריים

1 FixedUpdate 0–n times, 50 Hz CarController 2 PhysX solve contacts, wheels OnCollisionEnter 3 Update input · missions · AI CampaignRunner 4 animation engine, not script Animator · Agent 5 LateUpdate camera · HUD · map FollowCamera 6 URP render minimap RT, screen Camera.Render the engine schedules the next frame - nothing in this project writes the loop 1 FixedUpdate 0–n פעמים, 50 Hz CarController 2 פתרון PhysX מגעים, גלגלים OnCollisionEnter 3 Update קלט · משימות · AI CampaignRunner 4 אנימציה המנוע, לא סקריפט Animator · Agent 5 LateUpdate מצלמה · HUD · מפה FollowCamera 6 רינדור URP מפה קטנה, ואז המסך Camera.Render המנוע מתזמן את הפריים הבא - שום דבר בפרויקט הזה לא כותב את הלולאה
This order is Unity's, not mine: a script does not call the next system, it registers a method in one of these slots. That is the whole architectural difference from a hand-written frame loop, and it decides where code has to live. Wheels and throttle are in FixedUpdate (box 1) because a force applied at frame rate is a different car on a fast machine; the follow camera and the HUD are in LateUpdate (box 5) because reading a transform in the same slot that writes it costs a frame of lag. Ten scripts sit in box 1, nine in box 5, and exactly one - the skinning watchdog - needed an explicit [DefaultExecutionOrder(1000)] to run last within its slot.
הסדר הזה שייך ל-Unity, לא לי: סקריפט אף פעם לא קורא בעצמו לתת-המערכת הבאה, הוא רק רושם מתודה באחת המשבצות שבתרשים. זה כל ההבדל הארכיטקטוני בין מנוע לבין לולאת פריים שכותבים ביד, וזה מה שקובע היכן כל פיסת קוד חייבת לשבת. הגלגלים והגז יושבים ב-FixedUpdate (תיבה 1) מפני שכוח שמופעל בקצב הפריימים מתנהג כמו מכונית אחרת לגמרי על מחשב מהיר יותר; מצלמת המעקב וה-HUD יושבים ב-LateUpdate (תיבה 5) מפני שקריאת מיקום באותה משבצת שגם כותבת אותו גורמת לפיגור של פריים שלם. עשרה סקריפטים יושבים בתיבה 1, תשעה בתיבה 5, ובדיוק אחד - שומר הראש של ה-skinning - נזקק ל-[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 - זמן עורך

The pipeline that runs before the game ever does

הצינור שרץ עוד לפני שהמשחק בכלל מופעל

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, ואף אחד מהם לא נגרר למקומו ביד.

on import extract + BC7 rebind 52 .glb / .fbx Sketchfab · Mixamo, CC0 Assets/Models glTFast + Draco meshes, materials Humanoid avatars TextureCompressor glTF textures ship raw + PrefabTextureRebinder 38 prefabs cars · people · props Assets/Prefabs The Block ▸ Build … - 52 menu items 54 Editor scripts · 20,602 lines · every object placed from code WorldBuilder · CarBuilder · CrowdBuilder · HudBuilder · MissionBuilder · … World.unity one scene, 7.8 MB + NavMesh bake (AI Navigation) Build Player BuildPipeline.BuildPlayer StandaloneOSX · StandaloneWindows64 Mono · 2.1 GB · 1.09 GiB zipped בעת הייבוא חילוץ + BC7 קישור מחדש 52 קבצי glb / fbx Sketchfab · Mixamo, CC0 Assets/Models glTFast + Draco גאומטריה וחומרים אווטארים Humanoid TextureCompressor טקסטורות glTF מגיעות ללא דחיסה + PrefabTextureRebinder 38 prefabs רכבים · דמויות · אביזרים Assets/Prefabs ‏The Block ▸ Build … - 52 פריטי תפריט 54 סקריפטים של העורך · 20,602 שורות · כל אובייקט ממוקם מתוך קוד WorldBuilder · CarBuilder · CrowdBuilder · HudBuilder · MissionBuilder · … World.unity סצנה אחת, 7.8 MB + אפיית NavMesh ‏(AI Navigation) בניית Player BuildPipeline.BuildPlayer StandaloneOSX · StandaloneWindows64 Mono · 2.1 GB · 1.09 GiB בקובץ zip
Two Unity behaviours forced the middle of this chain and are worth calling out: textures that arrive inside a .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.
שתי התנהגויות של Unity הן שהכתיבו את אמצע השרשרת הזו, ושתיהן שוות הסבר: לטקסטורות שמגיעות בתוך קובץ .glb אין importer משלהן, ולכן הן נשארות ללא דחיסה עד ש-Compress Textures מחלץ אותן לקבצים נפרדים ו-Rebind Compressed Textures מפנה כל prefab וכל חומר אל העותק המחולץ; ובנוסף, ה-importer הוא זה שמחזיק את ההגדרות ולא מעבר תפריט חד-פעמי - מחיקה של תיקיית Library מייבאת הכול מחדש מתוך קובצי ה-.meta, ולכן כל הגדרה שהוחלה פעם אחת ביד פשוט חוזרת בשקט למצבה הקודם. הצעד האחרון הוא המקום היחיד שבו שתי הפלטפורמות אינן סימטריות: ה-Player של macOS נבנה מתוך סקריפט - PlayerBuilder מקבע את רשימת הסצנות ואת תיקיית הפלט, ומסרב לרוץ אם היעד הפעיל אינו StandaloneOSX - בעוד שה-Player של Windows נבנה בהחלפת פלטפורמה ידנית ואז File ▸ Build Settings, כשתיקיית הפלט מוקלדת ביד בחלון השמירה.

4 - Toolchain

4 - שרשרת הכלים

How the work gets done

איך העבודה עצמה נעשית

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.

Claude Code (Opus 5) - the AI pair-programmer writes the C#, drives the Editor and Blender over MCP, runs the CLIs, keeps the decision ledger MCP for Unity JSON-RPC, HTTP local 127.0.0.1:8080 Unity Editor menu items · scene · console 6000.5.8f1, URP Blender MCP socket to a live Blender TCP 9876 Blender + tools/*.py decimate · merge · convert decimate-glb · blend-to-glb perf-sweep.sh launches the Player, headless 44 runs, unattended PerfProbe in the Player frame ms, triangles, memory ProfilerRecorder → CSV ‏Claude Code ‏(Opus 5) - שותף התכנות מבוסס ה-AI כותב את קוד ה-C#‎, מפעיל את העורך ואת Blender דרך MCP, מריץ את כלי שורת הפקודה, ומתחזק את יומן ההחלטות MCP for Unity ‏JSON-RPC מעל HTTP מקומי 127.0.0.1:8080 עורך Unity פריטי תפריט · סצנה · קונסולה 6000.5.8f1, URP Blender MCP סוקט אל Blender פתוח TCP 9876 Blender + tools/*.py הפחתת פוליגונים · מיזוג · המרה decimate-glb · blend-to-glb perf-sweep.sh מריץ את הבילד ללא ממשק 44 הרצות, ללא השגחה ‏PerfProbe בתוך הבילד מ״ש לפריים, משולשים, זיכרון ProfilerRecorder → CSV
The right-hand column is the rule this project runs on: the Editor lies about performance, so every number that decided a trade-off was taken from a real macOS Player by 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.
העמודה הימנית בתרשים היא הכלל שהפרויקט הזה עובד לפיו: העורך משקר בכל הנוגע לביצועים, ולכן כל מספר שהכריע פשרה נלקח מבילד macOS אמיתי בעזרת 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

מלאי

Every API, tool and library, and when it runs

כל API, כלי וספרייה - ומתי כל אחד מהם רץ

Runtime - inside the shipped app

זמן ריצה - בתוך האפליקציה הארוזה

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

Editor & toolchain - on my machine

העורך ושרשרת הכלים - על המחשב שלי

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, לפי דרישה

Content pipeline - offline, never shipped as code

צינור התוכן - עובד לא מקוון, ולעולם לא נשלח כקוד

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 משווה שני רינדורים מול רצפת רעש מדודה - מים מונפשים שונים אפילו מעצמם כששינוי חזותי צריך להיות מוכח ולא רק מוצהר