Repository navigation
Module 2 improvements - #57
Merged
Merged
Conversation
PlasticBucket.prefab.meta and PF_Pop_House1.prefab.meta each still contained an unresolved rename/rename conflict block from 5b918e6. Unity cannot parse a GUID out of them ("The GUID inside '...' cannot be extracted by the YAML Parser"), which aborts an Android player build during IL post-processing with a double fault and a Mono process hang. Each file keeps its own HEAD-side GUID, chosen from what the live scenes actually reference: b4626cd6089bbfa41a12442e228be28f PlasticBucket - 3 live scenes aa4a993eaa7f10d4ab43e873f4ffd8ba PF_Pop_House1 - 2 live scenes The third GUID appearing in both blocks, 936550419afe37f44af3bf7b596ae57f, is referenced by nothing outside the conflict markers themselves and is dropped. Picking the other side would have silently broken every reference to the prefab. These were the only two .meta files in Assets/ carrying conflict markers.
Gameplay and UI pass over the household vector control module.
New:
Module2HUD in-headset HUD, added to M2Manager at runtime
Module2Text every player-facing string in one place
Module2Localization Module 2's string table, backed by Module2Text.tsv
Module2Interaction scene-wide interaction repairs applied at runtime, so
they need no prefab or scene edits
LaoFontTool editor tool that regenerates the Lao TMP font asset with
full coverage of the Lao block
Lao_SomVang Full SDF the regenerated font asset
Reworked: M2Manager, Jar, WaterButton, FishCon, TrashBin, SwatterHand,
MosquitoSpawn and Mosquto.
SendRecieveData now null-checks both managers before reading the score, instead
of assuming GameManager.instance. Module 2 has M2Manager and no GameManager, so
the old code threw a NullReferenceException whenever that scene reached the GAME
state. Adding the new components from M2Manager at runtime keeps these changes
out of Module_2_MainScene.unity, which is a ~1.1 MB serialized file that cannot
be merged when two people touch it.
Committed replacements for the per-machine helpers that were living in .git/info/exclude, so that building and sideloading no longer depends on untracked files. Tools/build.sh <1|2|tut2> [--clean] build a module into an APK Tools/deploy.sh <1|2|tut2> install it on an attached Quest, launch Tools/build-and-deploy.sh <1|2|tut2> both There is no separate packaging step: Unity's player build writes the signed .apk directly, debug-signed, which is what sideloading needs. Modules are built one at a time for now. Scenes are resolved by filename rather than a fixed path, so the folder reorganisations this repo keeps going through do not break the scripts, and each build contains only that module's scene rather than whatever EditorBuildSettings happens to hold. build.sh checks libil2cpp.so inside the finished APK and re-runs itself with --clean if it finds a stub; deploy.sh refuses to install one. A build that crashes part-way can leave the IL2CPP cache holding a few-KB libil2cpp.so, and every later incremental build then reuses it while still reporting result=Succeeded. The APK installs, starts the engine and dies, because it contains no compiled C# at all - so the build report alone is not enough to trust a build. deploy.sh also distinguishes the headset failure modes that otherwise look alike: an empty adb device list means developer mode is off rather than a cable fault, "unauthorized" means the on-headset prompt is still pending, and Horizon OS refuses to launch while the headset is asleep or a system dialog is open. The editor version is read from ProjectSettings/ProjectVersion.txt instead of being hardcoded, and adb is found inside the editor's bundled Android SDK. README documents all of this, including headset setup and troubleshooting.
The tip test cast 1.2 m along the container's up axis against the Ground layer only. The Lao house floor is on the Wall layer, so a vase on the indoor desk emptied only when held inverted below knee height; at chest height nothing happened. Found by playtesting through the harness. Pouring now triggers once the container is tilted past pourAngle (110 deg); the splash is placed on the ground mask or, failing that, the nearest surface below.
… round end Playtesting (harness) found a normal clear-the-sites run ended by bites after ~28 s: 8 bites in 5 s while covering a jar. Mosquitoes emerge 0.3 m above open containers - where the player is working - and up to 30 home in, each biting every 4 s. - M2Manager.biteGracePeriod (2.5 s): bites inside it are ignored. - Mosquito.firstBiteDelay (3 s): a freshly emerged mosquito cannot bite. - Score, site clears, swats and binned trash are ignored once the round has ended; the debrief showed 'Action score 40, 3/6' while the live state kept counting to 60 and 4/6. The completion bonus goes through a private path.
At 2.5 s the swarm, which out-flies a walking player, still landed a bite at the maximum rate and ended an efficient clear (4/6 sites, no swatting) at 42 s. Found by harness replay.
…thout bites The wrist menu has always spawned a repellent tube and the debrief tells players 'protection alone does not reduce the swarm', but the cream did nothing except play a particle effect. Now: - Cream: holding the tube and squeezing (trigger) it onto the other hand - nozzle ray or within applyRadius (0.2 m) - calls M2Manager.ApplyRepellent. The holding hand never counts. - M2Manager.repellentDuration (30 s): bites are ignored while active; toasts on apply and when it wears off; re-applying refreshes it. - Mosquitoes within attract range veer away from a protected player. - HUD shows the time left beside the bite count. - New strings in Module2Text.tsv (Lao column left for translation). Protection does not touch the breeding sites, so it cannot move source reduction.
…d card Harness screenshots showed the toast stack (from +170 down) drawn over the objective arrow and distance label (+150/+108), and the end-card subtitle starting inside the title's box (-94 vs title bottom -112). - Objective arrow/label move to the free top-centre band (+268/+226); the label narrows to 320 so it cannot reach the sites counter. - Toasts start at +200. - End subtitle at -116 with room for three lines; stats follow at -214.
The consequence line plus a random fact runs to four lines; in a 90-high box it overflowed into the stats line and the restart footer (harness screenshot of a BitesReached debrief).
A five-line consequence + fact still touched the restart footer; facts vary in length and Lao runs longer, so shrink to fit (23 -> min 15).
None of the Trash-tagged objects had a Rigidbody or XRGrabInteractable, so a player could not pick any of them up and TrashBin never fired - every debrief read 'Rubbish 0'. Found by trying to pick up a cup in the harness. Module2Interaction now adds a light Rigidbody + XRGrabInteractable to litter before tuning grabbables.
…start Litter is authored partly sunk into the terrain. With a Rigidbody added, the solver depenetrated a banana leaf at 8.4 m/s on frame 1 and it flew 3 m up (harness trace). Cap maxDepenetrationVelocity at 0.3 m/s so embedded pieces settle onto the surface instead.
XRI restores the lid's kinematic flag on release, so a lid dropped or thrown anywhere but on its jar froze in the air for 1.5 s and then teleported home (harness: thrown lid hung at y 0.40). Make it dynamic on release; the existing return-home path makes it kinematic again.
The watch sits under the left hand, so DontDestroyOnLoad (root objects only) never took effect and logged a warning on every scene load, and the 'destroy duplicate' branch could only ever misfire. The rig and watch are rebuilt with the scene; UIHand now simply tracks the current instance.
The previous fix preferred groundLayerMask, which is the terrain - under the house floor - so an indoor vase splashed 8 cm below the floor, invisible (harness). Use the nearest non-trigger surface below, skipping the container itself and the player's CharacterController.
Only PF_VaseWithFlowers has waterSplashEffect assigned; (2), (3) and (4) emptied with sound but no visible splash (harness). Containers without their own effect now use the one that is set.
…of release builds
Module2Text.tsv imported as a plain file (.tsv is not a text-asset extension), so
Resources.Load<TextAsset> always returned null and every string fell back to the built-in
English. Renamed it to .txt (same GUID, TextScriptImporter); it now loads 44 keys. Nothing
visible changes today because the Lao column is still empty, but Lao wording would have been
silently ignored.
The briefing's live input readout ("actions:0 ...") was on in the scene. It now also requires a
development build or the editor, so a release APK never shows it to children.
The racket prefab has gravity off and XRI restores that on release, so a dropped racket kept the speed it left the hand with and drifted away for good. FlySwatterUi then refused a new one because one "already" existed. The wrist button was the only way to get a swatter, so the player was left without one for the rest of the round. SwatterHand now forces gravity on detach and gets the same continuous collision the scene's other grabbables get (it is spawned after Module2Interaction has run). FlySwatterUi only refuses while a racket is actually held; otherwise it replaces any loose one.
Mosquitoes lived until swatted, so covering jars only stopped new ones spawning: 30 stayed alive with 5 of 6 sites open, and 25 were still buzzing on the "House is clear" card. The bite limiter was one global grace period, so 30 mosquitoes bit no faster than one. The debrief says fewer containers means fewer bites; play did not show it. - Mosquito.Retire(): stop seeking, fly away from the player for 2.5 s, then leave. - MosquitoSpawn retires the excess (nearest the player first, 2 per check) when the swarm is bigger than the open sites support, counting only mosquitoes that are not already leaving. - A full clear sends the whole swarm away. - M2Manager.CurrentBiteGrace = biteGracePeriod x sites / sites-still-open, capped at maxBiteGraceMultiplier (4). With every site open it is the unchanged 5 s.
… with ChooseSiteSubset switched off the GameObject of every site it left out, so a round's furniture changed with the dice: jars, vases and the fish bowl simply vanished with nothing to explain the gap. Each site now implements IBreedingSite.ShowResolved and is shown as if it had been dealt with, without any score or toast: - Jar: lid on, no lid left lying around. - WaterButton (vase): water off. - FishCon: fish in the bowl. The single fish ball is then hidden, since it would do nothing when dropped in. Anything that does not implement the interface still falls back to being switched off.
…osquitoes The swarm is sustained by the open sites, but nothing on screen said so. BreedingSiteFx, added by M2Manager to each site the round uses, puts a few pale wrigglers swimming on the water and a slow column of small mosquitoes rising from it. Clearing the site shrinks the wrigglers away and lets the last mosquitoes drift off; the component then removes itself. Built at runtime, so no scene or prefab changes: - Wrigglers are primitive meshes on two joints, one flat colour (Resources/Module2/M2_SiteLarva). - The mosquitoes are the game's own mosquito, baked once from the prefab's skinned mesh and scaled down, so they read as the same animal as the swarm. Falls back to dark specks (M2_SiteMote) if the prefab or bake is unavailable. - Water is found per site type (jar's flat disc, vase's Water child, the fish bowl's own mesh), and sizes follow the water's radius so a vase gets fewer, smaller ones. - M2Manager.showSiteFx turns it off. Mosquito_Female.fbx is now Read/Write so BakeMesh can be used in a player build; the editor does not need it, which is why this is worth checking on the headset.
The rig's ContinuousTurnProvider had Enable Turn Around on, so any stick direction in the back quarter snapped the view round 180 degrees. A thumb drifting slightly down while turning flipped the player, which felt like turning could not complete a full circle.
The menu was shown only while a ray along the watch's up axis hit the 8 cm sphere on the camera or the 1 cm one on the other hand's fingertip. On a headset that left two ways in: aim the wrist to within ten degrees of the eyes, or touch the watch - and the second closed the menu the moment the finger left the ray to reach a button, so the swatter could not be picked. It now opens when the watch face is turned to within 35 degrees of the eyes (staying until 55) or when the other fingertip touches the watch, and stays open while that fingertip is within 20 cm of the menu, with a half-second linger so tracking jitter cannot make it flicker.
… origin The swatter and the cream were spawned at a point fixed 30 cm in front of the rig's origin. In the editor the head is always above that origin and facing along it; on a headset the player has stepped away and turned round, so the tool they had just asked for could appear behind them (0.9 m away and 178 degrees off for a player turned 150 degrees). The point is now moved to 40 cm ahead of and 30 cm below the eyes before each spawn.
RomeXO10
force-pushed
the
module-2-improvements
branch
from
October 6, 2026 02:17
b6d8c08 to
16f46e6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.