This repository now includes Phase 1 and Phase 2 foundations for a Unity co-op survival horror prototype targeting WebGL + Mobile.
Assets/
└── HorrorCoopGame/
├── Scenes/
├── Scripts/
│ ├── Networking/
│ ├── Player/
│ ├── Interaction/
│ ├── Building/
│ └── AI/
├── Prefabs/
├── ScriptableObjects/
├── UI/
└── TouchControls/
Use Unity Hub to install and manage the Unity Editor version listed in
ProjectSettings/ProjectVersion.txt. On Linux, install Unity Hub through Unity's
package repositories so regular system updates can keep it current.
Install curl if it is not already available:
sudo apt install curlAdd the Unity Hub signing key and stable repository (amd64 only):
sudo install -d /etc/apt/keyrings
curl -fsSL https://hub.unity3d.com/linux/keys/public | sudo gpg --dearmor -o /etc/apt/keyrings/unityhub.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/unityhub.gpg] https://hub.unity3d.com/linux/repos/deb stable main" | sudo tee /etc/apt/sources.list.d/unityhub.listUpdate the package cache and install Unity Hub:
sudo apt update
sudo apt install unityhubTo install the Linux beta channel instead, use the unstable distribution in a
separate source list entry:
sudo install -d /etc/apt/keyrings
curl -fsSL https://hub.unity3d.com/linux/keys/public | sudo gpg --dearmor -o /etc/apt/keyrings/unityhub.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/unityhub.gpg] https://hub.unity3d.com/linux/repos/deb unstable main" | sudo tee /etc/apt/sources.list.d/unityhub-beta.list
sudo apt update
sudo apt install unityhubConfirm /etc/apt/keyrings exists, the installing user or group can write to it,
and /etc/apt/keyrings/unityhub.gpg is readable after creation.
Add Unity's RPM signing key and stable repository:
sudo rpm --import https://hub.unity3d.com/linux/keys/public
sudo tee /etc/yum.repos.d/unityhub.repo >/dev/null <<'EOF'
[unityhub]
name=Unity Hub
baseurl=https://hub.unity3d.com/linux/repos/rpm/stable
enabled=1
gpgcheck=1
gpgkey=https://hub.unity3d.com/linux/keys/public
EOFInstall Unity Hub with the package manager available on your distribution:
sudo dnf install unityhub
# or
sudo yum install unityhubFor beta builds, replace stable with unstable in the repository baseurl.
Use the same package manager to update or remove Unity Hub:
sudo dnf update unityhub
sudo dnf remove unityhub
# or replace dnf with yum on older systemsOn Ubuntu, remove Unity Hub with:
sudo apt remove unityhubAssets/HorrorCoopGame/Scripts/Networking/NetworkWebSocketSetup.csAssets/HorrorCoopGame/Scripts/Networking/RelayManager.csAssets/HorrorCoopGame/Scripts/Networking/NetworkMenuUI.csAssets/HorrorCoopGame/Scripts/Networking/NetworkStatusUI.cs
Assets/HorrorCoopGame/Scripts/Player/PlayerController.csAssets/HorrorCoopGame/Scripts/Player/PlayerStats.cs
Assets/HorrorCoopGame/Scripts/Interaction/ItemData.cs(ScriptableObject)Assets/HorrorCoopGame/Scripts/Interaction/IInteractable.csAssets/HorrorCoopGame/Scripts/Interaction/NetworkedPoolManager.csAssets/HorrorCoopGame/Scripts/Interaction/ScrapPile.csAssets/HorrorCoopGame/Scripts/Interaction/InventorySystem.csAssets/HorrorCoopGame/Scripts/Interaction/PlayerInteractionRaycast.csAssets/HorrorCoopGame/Scripts/Interaction/InventoryGridUI.cs
Assets/HorrorCoopGame/Scripts/Building/BuildableData.cs(ScriptableObject)Assets/HorrorCoopGame/Scripts/Building/BuildingManager.cs(snap-to-grid ghost + ServerRpc place)Assets/HorrorCoopGame/Scripts/Building/StructureHealth.cs
Assets/HorrorCoopGame/Scripts/Vehicle/VehicleRepair.cs(CarBattery + Alternator + SparkPlugs)
Assets/HorrorCoopGame/Scripts/AI/EnemyAI.cs(state machine + throttled NavMesh updates)Assets/HorrorCoopGame/Scripts/AI/SanityDrain.cs(darkness drain + audio hallucinations)
Assets/HorrorCoopGame/Scripts/Environment/DayNightCycle.cs(baked-lighting friendly, throttled+lerped lighting samples)Assets/HorrorCoopGame/Scripts/Environment/PerformantFlashlight.cs(shadowless spotlight)Assets/HorrorCoopGame/Scripts/Environment/PerformanceBootstrap.cs(runtime quality/FPS auto-tuner, mobile-first WebGL-aware)Assets/HorrorCoopGame/Scripts/UI/ResponsiveCanvasScaler.cs(1920x1080 reference, adaptive match)
The prototype is tuned for WebGL in a browser with mobile as the priority target.
Add PerformanceBootstrap to a GameObject in your first-loaded scene. It auto-detects mobile (including mobile browsers via SystemInfo.deviceType == Handheld) and applies:
Application.targetFrameRate(60 desktop / 60 mobile by default; configurable)QualitySettings.vSyncCount = 0so the target FPS actually takes effect (WebGL relies on browser rAF)Screen.sleepTimeout = NeverSleepso phones don't lock mid-sessionTime.maximumDeltaTimecap so a long browser frame doesn't snowball into a physics death-spiral- Mobile: shadows disabled, low shadow resolution + distance, reduced pixel-light count, reduced LOD bias, mipmap streaming bias, no anisotropy/MSAA, no realtime reflection probes, cheaper fixed timestep
PlayerControllerlow-pass filters move + look input and exponentially smooths camera pitch/yaw. Touch-stick jitter and one-off WebGL frame spikes no longer translate directly into camera/character snapping. Smooth times are per-platform inspector fields.DayNightCycleevaluates lighting gradients on a throttled interval and smoothly lerps the displayed sun/ambient color and sun rotation between samples — cheap on mobile, visually smoother than per-frame evaluation.EnemyAIadaptively throttles destination updates (slower when no players are in detection range), usessqrMagnitudeto avoid per-ticksqrt, and caches its transform.PlayerInteractionRaycastthrottles physics raycasts/overlap queries (~12 Hz default) while still refreshing instantly on interact press, so prompts stay responsive without per-frame physics queries.
Assets/HorrorCoopGame/Scripts/Game/GamePhase.cs(Lobby / Playing / Victory / Defeat enum)Assets/HorrorCoopGame/Scripts/Game/GameManager.cs(server-authoritative phase + win/loss detection)Assets/HorrorCoopGame/Scripts/UI/GameHUD.cs(health/stamina/sanity bars, repair progress, clock, phase banner, panel toggles)Assets/HorrorCoopGame/Scripts/UI/PauseMenuUI.cs(host start, resume, leave session)
- Spawn a single
GameManagerNetworkObjectin the gameplay scene (host spawns it; clients receive it via replication). - Add a
GameHUDCanvas (useResponsiveCanvasScaler) with:- Three filled
Images wired tohealthBarFill,staminaBarFill,sanityBarFill. - A full-screen black
Imageinside aCanvasGroupwired tosanityVignette. - TMP text fields for
repairProgressText,clockText,phaseBannerText, andendScreenText. - Child
GameObjects forinventoryPanel(hostingInventoryGridUI),pausePanel(hostingPauseMenuUI), andendScreenPanel.
- Three filled
- Add
InventoryandPauseactions to yourInputActions(e.g.TabandEscape) and bind them toGameHUD.OnInventory/GameHUD.OnPauseviaPlayerInputsend-messages, or callToggleInventory()/TogglePause()from on-screen buttons for mobile. - The host clicks Start Game on
PauseMenuUIto transition the round fromLobbytoPlaying. Victory triggers whenVehicleRepair.IsRepairedbecomes true; defeat triggers when every connected player has 0 health (after a short grace period).
- Install packages:
- Input System
- Netcode for GameObjects
- Relay + Lobby (services)
- Input System On-Screen Controls
- Create
InputActionswith actions:Move (Vector2),Look (Vector2),Sprint,Jump,Interact,BuildMode. - Add
PlayerInputto the player prefab and set behavior to Invoke Unity Events or Send Messages matching methods inPlayerController. - Create a
TouchControlsCanvas(Canvas Scaler: Scale With Screen Size, Reference Resolution 1920x1080). - Add controls under
TouchControlsCanvas:- Left:
On-Screen Stickbound toMove - Right: drag zone (
OnScreenStickor custom delta binding) bound toLook - Buttons:
On-Screen ButtonforJump,Interact,BuildMode, and optionalSprint
- Left:
- Assign the
TouchControlsCanvasreference onPlayerController. - At runtime,
PlayerControllerauto-enables touch UI only on mobile (Application.isMobilePlatform) and keeps desktop/WebGL keyboard+mouse flow active.
- Create a
NetworkManagerprefab withUnityTransport. - Add
NetworkWebSocketSetupon the same object to forceUnityTransport.UseWebSockets = true(required for WebGL browser clients). - Add
RelayManagerto a bootstrap scene object and wireNetworkManagerreference. - Build menu UI and attach
NetworkMenuUIwith Host/Join buttons, join code input, status label, and optional join-code/player-count/disconnect fields. - Add
NetworkStatusUIto an in-game HUD if you want connection status, relay join code, player count, and disconnect controls visible after the menu closes.