Compare commits
4 Commits
83544fe3d2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a4792759e6 | |||
| e2fa2ba8a9 | |||
| aa27725c4e | |||
| cf7d73ba08 |
159
README.md
Normal file
159
README.md
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<h1>ROLL'D</h1>
|
||||||
|
|
||||||
|
<p><strong>Browser-based marble MMO — multiplayer physics, real-time leaderboards, playable directly in your browser.</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img src="https://img.shields.io/badge/Unity-6000.0-black?style=for-the-badge&logo=unity&logoColor=white" alt="Unity 6" />
|
||||||
|
<img src="https://img.shields.io/badge/WebGL-build-E34F26?style=for-the-badge&logo=webgl&logoColor=white" alt="WebGL" />
|
||||||
|
<img src="https://img.shields.io/badge/Colyseus-0.17-6C47FF?style=for-the-badge&logo=node.js&logoColor=white" alt="Colyseus" />
|
||||||
|
<img src="https://img.shields.io/badge/React-19-61DAFB?style=for-the-badge&logo=react&logoColor=black" alt="React" />
|
||||||
|
<img src="https://img.shields.io/badge/Vite-5-646CFF?style=for-the-badge&logo=vite&logoColor=white" alt="Vite" />
|
||||||
|
<img src="https://img.shields.io/badge/Tailwind_CSS-3-38BDF8?style=for-the-badge&logo=tailwindcss&logoColor=white" alt="Tailwind" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="https://rolld.kerboul.me"><img src="https://img.shields.io/badge/Play_Now-rolld.kerboul.me-22c55e?style=for-the-badge&logo=googlechrome&logoColor=white" alt="Play Now" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What is ROLL'D?
|
||||||
|
|
||||||
|
ROLL'D is a multiplayer marble game that runs entirely in the browser via Unity WebGL. Players control a physics-based ball in a shared 3D arena, competing for distance, speed, and style. The game features real-time synchronisation at 60 Hz, in-game chat, and persistent leaderboards.
|
||||||
|
|
||||||
|
No install. No account. Just open the page and roll.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Real-time multiplayer** - up to 20 players per room, 60 Hz state sync via Colyseus WebSockets
|
||||||
|
- **Physics-based gameplay** - Unity Rigidbody, jump charge, gel pads (speed boosts), ball-to-ball bumps
|
||||||
|
- **Room lobby** - browse open rooms, create your own, choose your colour and name
|
||||||
|
- **In-game chat** - accessible in-game (T key) and on the dedicated website chat page
|
||||||
|
- **Live leaderboards** - distance, max speed, jumps, bumps, playtime, updated every 30 seconds
|
||||||
|
- **Spectator camera** - orbiting camera while in lobby or after disconnecting
|
||||||
|
- **WebGL-native** - no plugins, no downloads, runs in Chrome/Firefox/Edge
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
rolld/
|
||||||
|
├── game/ # Unity 6 project (WebGL build)
|
||||||
|
│ └── Assets/Scripts/
|
||||||
|
│ ├── Network/ # Colyseus SDK integration, schema, lobby UI
|
||||||
|
│ ├── Stats/ # StatsTracker - periodic HTTP upload
|
||||||
|
│ └── UI/ # IMGUI in-game HUD, chat, keybinds
|
||||||
|
│
|
||||||
|
├── rolld_backend/game/ # Colyseus 0.17 game server (Node.js)
|
||||||
|
│ └── src/
|
||||||
|
│ ├── rooms/ # ArenaRoom - game state machine
|
||||||
|
│ ├── schema/ # Colyseus schema (Player + GameState)
|
||||||
|
│ ├── stats/ # StatsManager - JSON persistence
|
||||||
|
│ └── chat/ # ChatManager - in-memory history
|
||||||
|
│
|
||||||
|
└── frontend/ # React + Vite + Tailwind SPA
|
||||||
|
└── src/
|
||||||
|
├── pages/ # Home, Stats leaderboard, Chat
|
||||||
|
└── components/ # NavBar, GameCanvas (Unity embed)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network flow
|
||||||
|
|
||||||
|
```
|
||||||
|
Browser
|
||||||
|
└── Unity WebGL (GameCanvas iframe)
|
||||||
|
└── Colyseus SDK (WebSocket wss://)
|
||||||
|
└── ArenaRoom (Node.js)
|
||||||
|
└── Broadcast state @60 Hz
|
||||||
|
|
||||||
|
Browser
|
||||||
|
└── React SPA
|
||||||
|
└── REST API (HTTPS)
|
||||||
|
├── GET /stats/leaderboard/:key
|
||||||
|
├── GET /chat/history?since=
|
||||||
|
└── POST /stats/update (from Unity every 30s)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tech stack
|
||||||
|
|
||||||
|
| Layer | Technology |
|
||||||
|
|---|---|
|
||||||
|
| Game engine | Unity 6 LTS, C# |
|
||||||
|
| Multiplayer | Colyseus 0.17 (Node.js + WebSocket) |
|
||||||
|
| Frontend | React 19, Vite 5, Tailwind CSS 3 |
|
||||||
|
| Deployment | Docker, Coolify, nginx |
|
||||||
|
| Self-hosted | Proxmox LXC, Gitea, Traefik reverse proxy |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Running locally
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js 20+
|
||||||
|
- Unity 6000.x (for game builds only)
|
||||||
|
|
||||||
|
### Game server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd rolld_backend/game
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Server starts on `ws://localhost:2567`.
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://localhost:5173`. The frontend points to the production game server by default - edit `src/pages/StatsPage.jsx` and `src/components/GameCanvas.jsx` to switch to localhost.
|
||||||
|
|
||||||
|
### Unity (optional)
|
||||||
|
|
||||||
|
Open `game/` in Unity 6. The server URL is hardcoded in `Assets/Scripts/Network/NetworkManager.cs`. Switch to `wss://game.rolld.kerboul.me` for prod or `ws://localhost:2567` for local testing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|---|---|
|
||||||
|
| WASD / Arrow keys | Move |
|
||||||
|
| Space (hold) | Charge jump |
|
||||||
|
| Space (release) | Jump |
|
||||||
|
| T | Open chat |
|
||||||
|
| Escape | Close chat |
|
||||||
|
| Tab | Show keybindings |
|
||||||
|
| Backtick (`) | Debug network info |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Live deployment
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img src="https://img.shields.io/badge/Frontend-rolld.kerboul.me-22c55e?style=flat-square&logo=nginx&logoColor=white" alt="Frontend" />
|
||||||
|
<img src="https://img.shields.io/badge/Game_server-game.rolld.kerboul.me-6C47FF?style=flat-square&logo=node.js&logoColor=white" alt="Game server" />
|
||||||
|
<img src="https://img.shields.io/badge/Self_hosted-Proxmox_homelab-E57000?style=flat-square&logo=proxmox&logoColor=white" alt="Self-hosted" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
The stack runs on a self-hosted Proxmox homelab cluster. Coolify handles container orchestration and auto-deployment on git push. Traefik manages HTTPS termination.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
MIT - do whatever you want with it.
|
||||||
Binary file not shown.
BIN
frontend/public/unity-build/Build/last_build.data
Normal file
BIN
frontend/public/unity-build/Build/last_build.data
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -3,8 +3,8 @@ import { useState, useEffect, useCallback } from 'react'
|
|||||||
// Check if Unity build files exist
|
// Check if Unity build files exist
|
||||||
const UNITY_BUILD_PATH = '/unity-build/Build'
|
const UNITY_BUILD_PATH = '/unity-build/Build'
|
||||||
// Cache-busting version — update this after each Unity build
|
// Cache-busting version — update this after each Unity build
|
||||||
const UNITY_BUILD_VERSION = '20260517b'
|
const UNITY_BUILD_VERSION = '20260518'
|
||||||
const BUILD_PREFIX = 'build_mai'
|
const BUILD_PREFIX = 'last_build'
|
||||||
const LOADER_URL = `${UNITY_BUILD_PATH}/${BUILD_PREFIX}.loader.js?v=${UNITY_BUILD_VERSION}`
|
const LOADER_URL = `${UNITY_BUILD_PATH}/${BUILD_PREFIX}.loader.js?v=${UNITY_BUILD_VERSION}`
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,17 @@ import { theme } from '../env'
|
|||||||
const SERVER = 'https://game.rolld.kerboul.me'
|
const SERVER = 'https://game.rolld.kerboul.me'
|
||||||
|
|
||||||
const TABS = [
|
const TABS = [
|
||||||
{ key: 'totalDistance', label: 'Distance', unit: 'm', format: v => Math.round(v).toLocaleString('fr-FR') },
|
{ key: 'totalDistance', label: 'Distance', unit: 'm', format: v => Math.round(v ?? 0).toLocaleString('fr-FR') },
|
||||||
{ key: 'maxSpeed', label: 'Vitesse max', unit: 'm/s', format: v => v.toFixed(1) },
|
{ key: 'maxSpeed', label: 'Vitesse max', unit: 'm/s', format: v => (v ?? 0).toFixed(1) },
|
||||||
{ key: 'totalJumps', label: 'Sauts', unit: '', format: v => v.toLocaleString('fr-FR') },
|
{ key: 'totalJumps', label: 'Sauts', unit: '', format: v => (v ?? 0).toLocaleString('fr-FR') },
|
||||||
{ key: 'bestRaceTime', label: 'Meilleur temps', unit: '', format: v => {
|
{ key: 'bumpsGiven', label: 'Bumps', unit: '', format: v => (v ?? 0).toLocaleString('fr-FR') },
|
||||||
const m = Math.floor(v / 60)
|
{ key: 'totalPlaytime',label: 'Temps de jeu',unit: '', format: v => {
|
||||||
const s = (v % 60).toFixed(2).padStart(5, '0')
|
const total = Math.round(v ?? 0)
|
||||||
return `${m}:${s}`
|
const h = Math.floor(total / 3600)
|
||||||
|
const m = Math.floor((total % 3600) / 60)
|
||||||
|
const s = total % 60
|
||||||
|
return h > 0 ? `${h}h ${m}m` : `${m}m ${s}s`
|
||||||
}},
|
}},
|
||||||
{ key: 'racesPlayed', label: 'Courses', unit: '', format: v => v.toLocaleString('fr-FR') },
|
|
||||||
{ key: 'bumpsGiven', label: 'Bumps', unit: '', format: v => v.toLocaleString('fr-FR') },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function StatsPage() {
|
export default function StatsPage() {
|
||||||
@@ -38,6 +39,7 @@ export default function StatsPage() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setRows([])
|
||||||
fetchLeaderboard(activeTab)
|
fetchLeaderboard(activeTab)
|
||||||
const id = setInterval(() => fetchLeaderboard(activeTab), 30_000)
|
const id = setInterval(() => fetchLeaderboard(activeTab), 30_000)
|
||||||
return () => clearInterval(id)
|
return () => clearInterval(id)
|
||||||
@@ -124,7 +126,7 @@ export default function StatsPage() {
|
|||||||
{row.name}
|
{row.name}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 text-right font-mono text-sm" style={{ color: theme.accentLight }}>
|
<td className="px-6 py-4 text-right font-mono text-sm" style={{ color: theme.accentLight }}>
|
||||||
{currentTab.format(row[activeTab])}
|
{currentTab.format(row.value)}
|
||||||
{currentTab.unit && <span className="text-rolld-muted ml-1">{currentTab.unit}</span>}
|
{currentTab.unit && <span className="text-rolld-muted ml-1">{currentTab.unit}</span>}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!134 &13400000
|
|
||||||
PhysicsMaterial:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_Name: Bouncy
|
|
||||||
serializedVersion: 2
|
|
||||||
m_DynamicFriction: 0.6
|
|
||||||
m_StaticFriction: 0.6
|
|
||||||
m_Bounciness: 0.74
|
|
||||||
m_FrictionCombine: 0
|
|
||||||
m_BounceCombine: 0
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 38ed95051af515848a7513429d4f0413
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 13400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!134 &13400000
|
|
||||||
PhysicsMaterial:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_Name: GelBleu
|
|
||||||
serializedVersion: 2
|
|
||||||
m_DynamicFriction: 0
|
|
||||||
m_StaticFriction: 0
|
|
||||||
m_Bounciness: 1
|
|
||||||
m_FrictionCombine: 1
|
|
||||||
m_BounceCombine: 3
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 458e6466a22c1204cb2e77d378867d7b
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 13400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!134 &13400000
|
|
||||||
PhysicsMaterial:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_Name: GelOrange
|
|
||||||
serializedVersion: 2
|
|
||||||
m_DynamicFriction: 0.6
|
|
||||||
m_StaticFriction: 0.6
|
|
||||||
m_Bounciness: 0.74
|
|
||||||
m_FrictionCombine: 0
|
|
||||||
m_BounceCombine: 0
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 61512ca9473715648874e2d1f555c50f
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 13400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!134 &13400000
|
|
||||||
PhysicsMaterial:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_Name: GelViolet
|
|
||||||
serializedVersion: 2
|
|
||||||
m_DynamicFriction: 1
|
|
||||||
m_StaticFriction: 1
|
|
||||||
m_Bounciness: 0
|
|
||||||
m_FrictionCombine: 3
|
|
||||||
m_BounceCombine: 0
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 86c56232f118b4c4caa7fc9d124fc344
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -8,8 +8,8 @@ Material:
|
|||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_Name: CheckpointMat
|
m_Name: CheckpointMat
|
||||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
m_Shader: {fileID: -6465566751694194690, guid: c52a5eb90c085474582a223ce9475866, type: 3}
|
||||||
m_Parent: {fileID: 0}
|
m_Parent: {fileID: -876546973899608171, guid: c52a5eb90c085474582a223ce9475866, type: 3}
|
||||||
m_ModifiedSerializedProperties: 0
|
m_ModifiedSerializedProperties: 0
|
||||||
m_ValidKeywords: []
|
m_ValidKeywords: []
|
||||||
m_InvalidKeywords: []
|
m_InvalidKeywords: []
|
||||||
@@ -22,63 +22,22 @@ Material:
|
|||||||
m_LockedProperties:
|
m_LockedProperties:
|
||||||
m_SavedProperties:
|
m_SavedProperties:
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_TexEnvs:
|
m_TexEnvs: []
|
||||||
- _BumpMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _DetailAlbedoMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _DetailMask:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _DetailNormalMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _EmissionMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _MainTex:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _MetallicGlossMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _OcclusionMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _ParallaxMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
m_Ints: []
|
m_Ints: []
|
||||||
m_Floats:
|
m_Floats: []
|
||||||
- _BumpScale: 1
|
m_Colors: []
|
||||||
- _Cutoff: 0.5
|
|
||||||
- _DetailNormalMapScale: 1
|
|
||||||
- _DstBlend: 0
|
|
||||||
- _GlossMapScale: 1
|
|
||||||
- _Glossiness: 0.5
|
|
||||||
- _GlossyReflections: 1
|
|
||||||
- _Metallic: 0
|
|
||||||
- _Mode: 0
|
|
||||||
- _OcclusionStrength: 1
|
|
||||||
- _Parallax: 0.02
|
|
||||||
- _SmoothnessTextureChannel: 0
|
|
||||||
- _SpecularHighlights: 1
|
|
||||||
- _SrcBlend: 1
|
|
||||||
- _UVSec: 0
|
|
||||||
- _ZWrite: 1
|
|
||||||
m_Colors:
|
|
||||||
- _Color: {r: 0.1, g: 0.9, b: 0.3, a: 1}
|
|
||||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
m_AllowLocking: 1
|
m_AllowLocking: 1
|
||||||
|
--- !u!114 &8924139153543123182
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Unity.ShaderGraph.Editor::UnityEditor.Rendering.BuiltIn.AssetVersion
|
||||||
|
version: 0
|
||||||
|
|||||||
Binary file not shown.
@@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!134 &13400000
|
|
||||||
PhysicsMaterial:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_Name: Normal
|
|
||||||
serializedVersion: 2
|
|
||||||
m_DynamicFriction: 0.6
|
|
||||||
m_StaticFriction: 0.6
|
|
||||||
m_Bounciness: 0
|
|
||||||
m_FrictionCombine: 0
|
|
||||||
m_BounceCombine: 0
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 36e82e5cf5450404999af634c1d3cbbd
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 13400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -180,20 +180,18 @@ public class PlayerController : MonoBehaviour
|
|||||||
// Update is called once per frame
|
// Update is called once per frame
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
// Toggle cursor lock/unlock avec clic droit (disabled when keybind menu is open)
|
// Cursor lock: right-click unlocks, left-click re-locks (disabled when any UI panel is open)
|
||||||
if (!KeyBindingUI.IsVisible && Mouse.current != null && Mouse.current.rightButton.wasPressedThisFrame)
|
if (!ChatUI.IsVisible && !KeyBindingUI.IsVisible && Mouse.current != null)
|
||||||
{
|
{
|
||||||
if (Cursor.lockState == CursorLockMode.Locked)
|
if (Cursor.lockState == CursorLockMode.Locked && Mouse.current.rightButton.wasPressedThisFrame)
|
||||||
{
|
{
|
||||||
Cursor.lockState = CursorLockMode.None;
|
Cursor.lockState = CursorLockMode.None;
|
||||||
Cursor.visible = true;
|
Cursor.visible = true;
|
||||||
Debug.Log("Cursor UNLOCKED");
|
|
||||||
}
|
}
|
||||||
else
|
else if (Cursor.lockState != CursorLockMode.Locked && Mouse.current.leftButton.wasPressedThisFrame)
|
||||||
{
|
{
|
||||||
Cursor.lockState = CursorLockMode.Locked;
|
Cursor.lockState = CursorLockMode.Locked;
|
||||||
Cursor.visible = false;
|
Cursor.visible = false;
|
||||||
Debug.Log("Cursor LOCKED");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,33 +372,19 @@ public class PlayerController : MonoBehaviour
|
|||||||
|
|
||||||
public void OnJump(InputAction.CallbackContext context)
|
public void OnJump(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
|
if (ChatUI.IsVisible) { isJumpPressed = false; jumpPressTime = 0f; return; }
|
||||||
|
|
||||||
if (context.started)
|
if (context.started)
|
||||||
{
|
{
|
||||||
isJumpPressed = true;
|
isJumpPressed = true;
|
||||||
jumpPressTime = 0f;
|
jumpPressTime = 0f;
|
||||||
StatsTracker.Instance?.RegisterJump();
|
StatsTracker.Instance?.RegisterJump();
|
||||||
Debug.Log("Jump Started");
|
|
||||||
}
|
|
||||||
else if (context.performed)
|
|
||||||
{
|
|
||||||
// Action validée (utile pour saut immédiat aussi)
|
|
||||||
Debug.Log("Jump Performed");
|
|
||||||
}
|
}
|
||||||
else if (context.canceled)
|
else if (context.canceled)
|
||||||
{
|
{
|
||||||
// Touche relâchée
|
|
||||||
float jumpForceFactor = Mathf.Clamp01(jumpPressTime / maxJumpHoldTime);
|
float jumpForceFactor = Mathf.Clamp01(jumpPressTime / maxJumpHoldTime);
|
||||||
if (IsGrounded())
|
if (IsGrounded())
|
||||||
{
|
|
||||||
PerformJump(jumpForceFactor * JumpForce);
|
PerformJump(jumpForceFactor * JumpForce);
|
||||||
Debug.Log($"Jump Released after {jumpPressTime}s -> Force factor: {jumpForceFactor}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log("Jump Released but not grounded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset jump state so gauge goes back to 0
|
|
||||||
isJumpPressed = false;
|
isJumpPressed = false;
|
||||||
jumpPressTime = 0f;
|
jumpPressTime = 0f;
|
||||||
}
|
}
|
||||||
@@ -424,75 +408,30 @@ public class PlayerController : MonoBehaviour
|
|||||||
|
|
||||||
public void OnForward(InputAction.CallbackContext context)
|
public void OnForward(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
if (context.started)
|
if (ChatUI.IsVisible) { isForwardHeld = false; return; }
|
||||||
{
|
if (context.started) isForwardHeld = true;
|
||||||
isForwardHeld = true;
|
else if (context.canceled) isForwardHeld = false;
|
||||||
Debug.Log("Forward Action Started");
|
|
||||||
}
|
|
||||||
else if (context.performed)
|
|
||||||
{
|
|
||||||
// Forward action performed
|
|
||||||
Debug.Log("Forward Action Performed");
|
|
||||||
}
|
|
||||||
else if (context.canceled)
|
|
||||||
{
|
|
||||||
isForwardHeld = false;
|
|
||||||
Debug.Log("Forward Action Canceled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnBackwards(InputAction.CallbackContext context)
|
public void OnBackwards(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
if (context.started)
|
if (ChatUI.IsVisible) { isBackwardsHeld = false; return; }
|
||||||
{
|
if (context.started) isBackwardsHeld = true;
|
||||||
isBackwardsHeld = true;
|
else if (context.canceled) isBackwardsHeld = false;
|
||||||
Debug.Log("Backwards Action Started");
|
|
||||||
}
|
|
||||||
else if (context.performed)
|
|
||||||
{
|
|
||||||
Debug.Log("Backwards Action Performed");
|
|
||||||
}
|
|
||||||
else if (context.canceled)
|
|
||||||
{
|
|
||||||
isBackwardsHeld = false;
|
|
||||||
Debug.Log("Backwards Action Canceled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnLeft(InputAction.CallbackContext context)
|
public void OnLeft(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
if (context.started)
|
if (ChatUI.IsVisible) { isLeftHeld = false; return; }
|
||||||
{
|
if (context.started) isLeftHeld = true;
|
||||||
isLeftHeld = true;
|
else if (context.canceled) isLeftHeld = false;
|
||||||
Debug.Log("Left Action Started");
|
|
||||||
}
|
|
||||||
else if (context.performed)
|
|
||||||
{
|
|
||||||
Debug.Log("Left Action Performed");
|
|
||||||
}
|
|
||||||
else if (context.canceled)
|
|
||||||
{
|
|
||||||
isLeftHeld = false;
|
|
||||||
Debug.Log("Left Action Canceled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRight(InputAction.CallbackContext context)
|
public void OnRight(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
if (context.started)
|
if (ChatUI.IsVisible) { isRightHeld = false; return; }
|
||||||
{
|
if (context.started) isRightHeld = true;
|
||||||
isRightHeld = true;
|
else if (context.canceled) isRightHeld = false;
|
||||||
Debug.Log("Right Action Started");
|
|
||||||
}
|
|
||||||
else if (context.performed)
|
|
||||||
{
|
|
||||||
Debug.Log("Right Action Performed");
|
|
||||||
}
|
|
||||||
else if (context.canceled)
|
|
||||||
{
|
|
||||||
isRightHeld = false;
|
|
||||||
Debug.Log("Right Action Canceled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Bump collision with remote players ---
|
// --- Bump collision with remote players ---
|
||||||
@@ -564,6 +503,16 @@ public class PlayerController : MonoBehaviour
|
|||||||
_isSquashing = false;
|
_isSquashing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResetInputs()
|
||||||
|
{
|
||||||
|
isForwardHeld = false;
|
||||||
|
isBackwardsHeld = false;
|
||||||
|
isLeftHeld = false;
|
||||||
|
isRightHeld = false;
|
||||||
|
isJumpPressed = false;
|
||||||
|
jumpPressTime = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
void OnDestroy()
|
void OnDestroy()
|
||||||
{
|
{
|
||||||
// Clean up name label (it's not parented to the ball)
|
// Clean up name label (it's not parented to the ball)
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &-670956545734759409
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 3
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: b94fcd11afffcb142908bfcb1e261fba, type: 3}
|
|
||||||
m_Name: MotionBlur
|
|
||||||
m_EditorClassIdentifier: Unity.Postprocessing.Runtime::UnityEngine.Rendering.PostProcessing.MotionBlur
|
|
||||||
active: 1
|
|
||||||
enabled:
|
|
||||||
overrideState: 1
|
|
||||||
value: 1
|
|
||||||
shutterAngle:
|
|
||||||
overrideState: 0
|
|
||||||
value: 270
|
|
||||||
sampleCount:
|
|
||||||
overrideState: 0
|
|
||||||
value: 10
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 8e6292b2c06870d4495f009f912b9600, type: 3}
|
|
||||||
m_Name: PostProcessing Profile
|
|
||||||
m_EditorClassIdentifier: Unity.Postprocessing.Runtime::UnityEngine.Rendering.PostProcessing.PostProcessProfile
|
|
||||||
settings:
|
|
||||||
- {fileID: -670956545734759409}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fc446179a9ae97a4a8ad5c8aa1c2dd47
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fcf7219bab7fe46a1ad266029b2fee19, type: 3}
|
|
||||||
m_Name: Readme
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
icon: {fileID: 2800000, guid: 727a75301c3d24613a3ebcec4a24c2c8, type: 3}
|
|
||||||
title: URP Empty Template
|
|
||||||
sections:
|
|
||||||
- heading: Welcome to the Universal Render Pipeline
|
|
||||||
text: This template includes the settings and assets you need to start creating with the Universal Render Pipeline.
|
|
||||||
linkText:
|
|
||||||
url:
|
|
||||||
- heading: URP Documentation
|
|
||||||
text:
|
|
||||||
linkText: Read more about URP
|
|
||||||
url: https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@latest
|
|
||||||
- heading: Forums
|
|
||||||
text:
|
|
||||||
linkText: Get answers and support
|
|
||||||
url: https://forum.unity.com/forums/universal-render-pipeline.383/
|
|
||||||
- heading: Report bugs
|
|
||||||
text:
|
|
||||||
linkText: Submit a report
|
|
||||||
url: https://unity3d.com/unity/qa/bug-reporting
|
|
||||||
loadedLayout: 1
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8105016687592461f977c054a80ce2f2
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -10,6 +10,6 @@ PhysicsMaterial:
|
|||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_DynamicFriction: 0.6
|
m_DynamicFriction: 0.6
|
||||||
m_StaticFriction: 0.6
|
m_StaticFriction: 0.6
|
||||||
m_Bounciness: 0
|
m_Bounciness: 0.2
|
||||||
m_FrictionCombine: 0
|
m_FrictionCombine: 0
|
||||||
m_BounceCombine: 0
|
m_BounceCombine: 0
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -29,6 +29,8 @@ public class CameraOrbitKeyboard : MonoBehaviour
|
|||||||
{
|
{
|
||||||
// On gère la souris nous-mêmes
|
// On gère la souris nous-mêmes
|
||||||
if (_axisController != null) _axisController.enabled = false;
|
if (_axisController != null) _axisController.enabled = false;
|
||||||
|
// Only lock cursor if no UI panel is open
|
||||||
|
if (!ChatUI.IsVisible && !KeyBindingUI.IsVisible)
|
||||||
LockCursor();
|
LockCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,16 +57,16 @@ public class CameraOrbitKeyboard : MonoBehaviour
|
|||||||
|
|
||||||
var mouse = Mouse.current;
|
var mouse = Mouse.current;
|
||||||
|
|
||||||
// Clic droit = toggle lock
|
// Right-click unlocks, left-click re-locks (consistent with PlayerController)
|
||||||
if (mouse != null && mouse.rightButton.wasPressedThisFrame)
|
if (!ChatUI.IsVisible && !KeyBindingUI.IsVisible && mouse != null)
|
||||||
{
|
{
|
||||||
if (Cursor.lockState == CursorLockMode.Locked)
|
if (Cursor.lockState == CursorLockMode.Locked && mouse.rightButton.wasPressedThisFrame)
|
||||||
UnlockCursor();
|
UnlockCursor();
|
||||||
else
|
else if (Cursor.lockState != CursorLockMode.Locked && mouse.leftButton.wasPressedThisFrame)
|
||||||
LockCursor();
|
LockCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KeyBindingUI.IsVisible) return;
|
if (KeyBindingUI.IsVisible || ChatUI.IsVisible) return;
|
||||||
|
|
||||||
// Souris — seulement quand locked (delta infini, sans accrochage au bord)
|
// Souris — seulement quand locked (delta infini, sans accrochage au bord)
|
||||||
if (Cursor.lockState == CursorLockMode.Locked && mouse != null)
|
if (Cursor.lockState == CursorLockMode.Locked && mouse != null)
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ public class NetworkManager : MonoBehaviour
|
|||||||
_callbacks.OnRemove(state => state.players, (key, player) => OnPlayerRemove(key, player));
|
_callbacks.OnRemove(state => state.players, (key, player) => OnPlayerRemove(key, player));
|
||||||
_callbacks.Listen(state => state.phase, (v, _) => _OnPhaseChanged(v));
|
_callbacks.Listen(state => state.phase, (v, _) => _OnPhaseChanged(v));
|
||||||
_callbacks.Listen(state => state.countdown, (v, _) => OnCountdownChanged?.Invoke(v));
|
_callbacks.Listen(state => state.countdown, (v, _) => OnCountdownChanged?.Invoke(v));
|
||||||
|
_callbacks.Listen(state => state.playersAlive, (v, _) => GameHUD.Instance?.SetPlayersAlive(v));
|
||||||
|
|
||||||
_room.OnMessage<EliminatedMsg>("eliminated", msg => { OnEliminated?.Invoke(msg.sessionId, msg.reason); });
|
_room.OnMessage<EliminatedMsg>("eliminated", msg => { OnEliminated?.Invoke(msg.sessionId, msg.reason); });
|
||||||
_room.OnMessage<QualifiedMsg> ("qualified", msg => { OnQualified?.Invoke(msg.sessionId); });
|
_room.OnMessage<QualifiedMsg> ("qualified", msg => { OnQualified?.Invoke(msg.sessionId); });
|
||||||
@@ -163,6 +164,13 @@ public class NetworkManager : MonoBehaviour
|
|||||||
_room.OnMessage<ChatUI.ChatMessage>("chat", msg => { ChatUI.Instance?.ReceiveChatMessage(msg); });
|
_room.OnMessage<ChatUI.ChatMessage>("chat", msg => { ChatUI.Instance?.ReceiveChatMessage(msg); });
|
||||||
_room.OnLeave += OnRoomLeave;
|
_room.OnLeave += OnRoomLeave;
|
||||||
|
|
||||||
|
// Seed players already present in the room (state decoded before callbacks were registered)
|
||||||
|
if (_room.State.players != null)
|
||||||
|
{
|
||||||
|
foreach (var kvp in _room.State.players)
|
||||||
|
OnPlayerAdd(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
OnConnected?.Invoke();
|
OnConnected?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,11 +265,14 @@ public class NetworkManager : MonoBehaviour
|
|||||||
PlayerCount = _room.State.players?.Count ?? 0;
|
PlayerCount = _room.State.players?.Count ?? 0;
|
||||||
|
|
||||||
if (sessionId == LocalSessionId) return;
|
if (sessionId == LocalSessionId) return;
|
||||||
|
if (_remotePlayers.ContainsKey(sessionId)) return; // prevent duplicate spawn
|
||||||
|
|
||||||
if (remotePlayerPrefab != null)
|
|
||||||
{
|
{
|
||||||
Vector3 spawnPos = new Vector3(player.x, player.y, player.z);
|
Vector3 spawnPos = new Vector3(player.x, player.y, player.z);
|
||||||
GameObject remoteBall = Instantiate(remotePlayerPrefab, spawnPos, Quaternion.identity);
|
GameObject remoteBall = remotePlayerPrefab != null
|
||||||
|
? Instantiate(remotePlayerPrefab, spawnPos, Quaternion.identity)
|
||||||
|
: GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||||
|
remoteBall.transform.position = spawnPos;
|
||||||
remoteBall.name = $"RemotePlayer_{player.name}_{sessionId[..6]}";
|
remoteBall.name = $"RemotePlayer_{player.name}_{sessionId[..6]}";
|
||||||
|
|
||||||
var controller = remoteBall.GetComponent<RemotePlayerController>()
|
var controller = remoteBall.GetComponent<RemotePlayerController>()
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
using Colyseus.Schema;
|
// Generated from @colyseus/schema 4.0.15 — DO NOT EDIT MANUALLY
|
||||||
|
// Class names kept as NetworkPlayer/NetworkState to match existing codebase references.
|
||||||
|
|
||||||
|
using Colyseus.Schema;
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
using UnityEngine.Scripting;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Must match server-side defineTypes field order exactly
|
|
||||||
public partial class NetworkPlayer : Schema
|
public partial class NetworkPlayer : Schema
|
||||||
{
|
{
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[Preserve]
|
||||||
|
#endif
|
||||||
|
public NetworkPlayer() { }
|
||||||
|
|
||||||
[Type(0, "float32")] public float x = 0;
|
[Type(0, "float32")] public float x = 0;
|
||||||
[Type(1, "float32")] public float y = 5;
|
[Type(1, "float32")] public float y = 5;
|
||||||
[Type(2, "float32")] public float z = 0;
|
[Type(2, "float32")] public float z = 0;
|
||||||
@@ -21,23 +31,27 @@ public partial class NetworkPlayer : Schema
|
|||||||
[Type(15, "float32")] public float avx = 0;
|
[Type(15, "float32")] public float avx = 0;
|
||||||
[Type(16, "float32")] public float avy = 0;
|
[Type(16, "float32")] public float avy = 0;
|
||||||
[Type(17, "float32")] public float avz = 0;
|
[Type(17, "float32")] public float avz = 0;
|
||||||
// Game state — order must match server defineTypes exactly
|
|
||||||
[Type(18, "boolean")] public bool isEliminated = false;
|
[Type(18, "boolean")] public bool isEliminated = false;
|
||||||
[Type(19, "boolean")] public bool isQualified = false;
|
[Type(19, "boolean")] public bool isQualified = false;
|
||||||
[Type(20, "boolean")] public bool isReady = false;
|
[Type(20, "boolean")] public bool isReady = false;
|
||||||
[Type(21, "int8")] public int checkpointIndex = 0;
|
[Type(21, "int8")] public sbyte checkpointIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class NetworkState : Schema
|
public partial class NetworkState : Schema
|
||||||
{
|
{
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[Preserve]
|
||||||
|
#endif
|
||||||
|
public NetworkState() { }
|
||||||
|
|
||||||
[Type(0, "map", typeof(MapSchema<NetworkPlayer>))]
|
[Type(0, "map", typeof(MapSchema<NetworkPlayer>))]
|
||||||
public MapSchema<NetworkPlayer> players;
|
public MapSchema<NetworkPlayer> players = null;
|
||||||
|
|
||||||
[Type(1, "string")] public string phase = "lobby";
|
[Type(1, "string")] public string phase = "lobby";
|
||||||
[Type(2, "float32")] public float countdown = 0;
|
[Type(2, "float32")] public float countdown = 0;
|
||||||
[Type(3, "int8")] public int roundNumber = 1;
|
[Type(3, "int8")] public sbyte roundNumber = 1;
|
||||||
[Type(4, "int8")] public int totalRounds = 4;
|
[Type(4, "int8")] public sbyte totalRounds = 3;
|
||||||
[Type(5, "int8")] public int playersAlive = 0;
|
[Type(5, "int8")] public sbyte playersAlive = 0;
|
||||||
[Type(6, "string")] public string gameMode = "race";
|
[Type(6, "string")] public string gameMode = "race";
|
||||||
[Type(7, "string")] public string winnerName = "";
|
[Type(7, "string")] public string winnerName = "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5bf5e078a2ee9ed4fa95eacab5753f3a
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d1f3d6aaca8e97498f40d827f7c5216
|
|
||||||
@@ -4,33 +4,33 @@ using UnityEngine;
|
|||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tracks per-session and per-round player statistics and uploads them to the game server.
|
/// Tracks player statistics and uploads them to the game server every 30s + on disconnect.
|
||||||
/// All HTTP calls use UnityWebRequest coroutines (WebGL-safe, no async/await).
|
/// No dependency on round events — works even if Colyseus callbacks are broken.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatsTracker : MonoBehaviour
|
public class StatsTracker : MonoBehaviour
|
||||||
{
|
{
|
||||||
public static StatsTracker Instance { get; private set; }
|
public static StatsTracker Instance { get; private set; }
|
||||||
|
|
||||||
private const string SERVER_URL = "https://game.rolld.kerboul.me";
|
private const string SERVER_URL = "https://game.rolld.kerboul.me";
|
||||||
|
private const float SEND_INTERVAL = 30f;
|
||||||
|
private const float MIN_SEND_INTERVAL = 6f; // juste au-dessus du rate-limit serveur (5s)
|
||||||
|
|
||||||
// Cumulative session stats (accumulate across rounds)
|
// Cumulative stats
|
||||||
private float _totalDistance;
|
private float _totalDistance;
|
||||||
private int _totalJumps;
|
private int _totalJumps;
|
||||||
private float _maxSpeed;
|
private float _maxSpeed;
|
||||||
private int _racesPlayed;
|
|
||||||
private int _qualifications;
|
|
||||||
private int _eliminations;
|
|
||||||
private int _bumpsGiven;
|
private int _bumpsGiven;
|
||||||
private float _totalPlaytime;
|
|
||||||
|
|
||||||
// Per-round deltas (reset after each send)
|
// Playtime
|
||||||
private float _roundDistance;
|
|
||||||
private float _roundMaxSpeed;
|
|
||||||
private float _sessionStart;
|
private float _sessionStart;
|
||||||
|
private float _playtimeSentSoFar; // how much playtime we already sent
|
||||||
|
|
||||||
|
// Tracking
|
||||||
private Vector3 _lastPos;
|
private Vector3 _lastPos;
|
||||||
private bool _trackingActive;
|
private bool _tracking;
|
||||||
private string _cachedName = "";
|
private string _cachedName = "";
|
||||||
|
private float _lastSentTime = -999f;
|
||||||
|
|
||||||
private PlayerController _pc;
|
private PlayerController _pc;
|
||||||
private Rigidbody _rb;
|
private Rigidbody _rb;
|
||||||
|
|
||||||
@@ -38,7 +38,6 @@ public class StatsTracker : MonoBehaviour
|
|||||||
{
|
{
|
||||||
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
|
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
|
||||||
Instance = this;
|
Instance = this;
|
||||||
_sessionStart = Time.time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
@@ -49,10 +48,6 @@ public class StatsTracker : MonoBehaviour
|
|||||||
var nm = NetworkManager.Instance;
|
var nm = NetworkManager.Instance;
|
||||||
if (nm != null)
|
if (nm != null)
|
||||||
{
|
{
|
||||||
nm.OnRoundStart += OnRoundStart;
|
|
||||||
nm.OnRoundEnd += OnRoundEnd;
|
|
||||||
nm.OnQualified += OnQualified;
|
|
||||||
nm.OnEliminated += OnEliminated;
|
|
||||||
nm.OnConnected += OnConnected;
|
nm.OnConnected += OnConnected;
|
||||||
nm.OnDisconnected += OnDisconnected;
|
nm.OnDisconnected += OnDisconnected;
|
||||||
}
|
}
|
||||||
@@ -63,10 +58,6 @@ public class StatsTracker : MonoBehaviour
|
|||||||
var nm = NetworkManager.Instance;
|
var nm = NetworkManager.Instance;
|
||||||
if (nm != null)
|
if (nm != null)
|
||||||
{
|
{
|
||||||
nm.OnRoundStart -= OnRoundStart;
|
|
||||||
nm.OnRoundEnd -= OnRoundEnd;
|
|
||||||
nm.OnQualified -= OnQualified;
|
|
||||||
nm.OnEliminated -= OnEliminated;
|
|
||||||
nm.OnConnected -= OnConnected;
|
nm.OnConnected -= OnConnected;
|
||||||
nm.OnDisconnected -= OnDisconnected;
|
nm.OnDisconnected -= OnDisconnected;
|
||||||
}
|
}
|
||||||
@@ -74,96 +65,72 @@ public class StatsTracker : MonoBehaviour
|
|||||||
|
|
||||||
void FixedUpdate()
|
void FixedUpdate()
|
||||||
{
|
{
|
||||||
if (!_trackingActive || _rb == null || _pc == null || !_pc.enabled) return;
|
if (!_tracking || _rb == null) return;
|
||||||
|
|
||||||
Vector3 pos = transform.position;
|
Vector3 pos = transform.position;
|
||||||
float delta = Vector3.Distance(pos, _lastPos);
|
float delta = Vector3.Distance(pos, _lastPos);
|
||||||
if (delta < 20f) // sanity cap against teleports
|
if (delta < 20f) // filtre téléportations
|
||||||
{
|
|
||||||
_roundDistance += delta;
|
|
||||||
_totalDistance += delta;
|
_totalDistance += delta;
|
||||||
}
|
|
||||||
_lastPos = pos;
|
_lastPos = pos;
|
||||||
|
|
||||||
float speed = _rb.linearVelocity.magnitude;
|
float speed = _rb.linearVelocity.magnitude;
|
||||||
if (speed > _roundMaxSpeed) _roundMaxSpeed = speed;
|
|
||||||
if (speed > _maxSpeed) _maxSpeed = speed;
|
if (speed > _maxSpeed) _maxSpeed = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Public hooks ────────────────────────────────────────────────────
|
// ─── Public hooks ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
public void RegisterJump()
|
public void RegisterJump() => _totalJumps++;
|
||||||
{
|
public void RegisterBump() => _bumpsGiven++;
|
||||||
_totalJumps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RegisterBump()
|
// ─── Connection events ────────────────────────────────────────────────
|
||||||
{
|
|
||||||
_bumpsGiven++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── Event handlers ──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
private void OnConnected()
|
private void OnConnected()
|
||||||
{
|
{
|
||||||
_cachedName = NetworkManager.Instance?.LocalPlayerName ?? "";
|
_cachedName = NetworkManager.Instance?.LocalPlayerName ?? "";
|
||||||
_lastPos = transform.position;
|
_lastPos = transform.position;
|
||||||
_trackingActive = true;
|
_sessionStart = Time.time;
|
||||||
|
_tracking = true;
|
||||||
|
StartCoroutine(PeriodicSend());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDisconnected()
|
private void OnDisconnected()
|
||||||
{
|
{
|
||||||
_trackingActive = false;
|
_tracking = false;
|
||||||
_totalPlaytime += Time.time - _sessionStart;
|
StopAllCoroutines();
|
||||||
SendStats(); // best-effort on disconnect
|
SendStats(); // envoi final best-effort
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRoundStart(int round, string mode, int totalRounds)
|
// ─── Periodic send ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private IEnumerator PeriodicSend()
|
||||||
{
|
{
|
||||||
_racesPlayed++;
|
while (_tracking)
|
||||||
_roundDistance = 0f;
|
|
||||||
_roundMaxSpeed = 0f;
|
|
||||||
_lastPos = transform.position;
|
|
||||||
_trackingActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRoundEnd(int round)
|
|
||||||
{
|
{
|
||||||
_trackingActive = false;
|
yield return new WaitForSeconds(SEND_INTERVAL);
|
||||||
SendStats();
|
if (_tracking) SendStats();
|
||||||
_roundDistance = 0f;
|
}
|
||||||
_roundMaxSpeed = 0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnQualified(string sessionId)
|
// ─── HTTP send ────────────────────────────────────────────────────────
|
||||||
{
|
|
||||||
if (sessionId == NetworkManager.Instance?.LocalSessionId)
|
|
||||||
_qualifications++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEliminated(string sessionId, string reason)
|
|
||||||
{
|
|
||||||
if (sessionId == NetworkManager.Instance?.LocalSessionId)
|
|
||||||
_eliminations++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── HTTP send ───────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
private void SendStats()
|
private void SendStats()
|
||||||
{
|
{
|
||||||
// Prefer live name, fall back to cached (useful on disconnect where name is cleared)
|
if (Time.time - _lastSentTime < MIN_SEND_INTERVAL) return;
|
||||||
var nm = NetworkManager.Instance;
|
var nm = NetworkManager.Instance;
|
||||||
string name = (nm != null && !string.IsNullOrEmpty(nm.LocalPlayerName))
|
string name = (nm != null && !string.IsNullOrEmpty(nm.LocalPlayerName))
|
||||||
? nm.LocalPlayerName
|
? nm.LocalPlayerName
|
||||||
: _cachedName;
|
: _cachedName;
|
||||||
if (string.IsNullOrEmpty(name)) return;
|
if (string.IsNullOrEmpty(name)) return;
|
||||||
|
_lastSentTime = Time.time;
|
||||||
StartCoroutine(DoSendStats(name));
|
StartCoroutine(DoSendStats(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator DoSendStats(string playerName)
|
private IEnumerator DoSendStats(string playerName)
|
||||||
{
|
{
|
||||||
_totalPlaytime += Time.time - _sessionStart;
|
float now = Time.time;
|
||||||
_sessionStart = Time.time;
|
float sessionSecs = now - _sessionStart;
|
||||||
|
float playtimeToSend = sessionSecs - _playtimeSentSoFar;
|
||||||
|
_playtimeSentSoFar = sessionSecs;
|
||||||
|
|
||||||
var payload = new StatsPayload
|
var payload = new StatsPayload
|
||||||
{
|
{
|
||||||
@@ -173,13 +140,8 @@ public class StatsTracker : MonoBehaviour
|
|||||||
totalDistance = _totalDistance,
|
totalDistance = _totalDistance,
|
||||||
totalJumps = _totalJumps,
|
totalJumps = _totalJumps,
|
||||||
maxSpeed = _maxSpeed,
|
maxSpeed = _maxSpeed,
|
||||||
|
|
||||||
racesPlayed = _racesPlayed,
|
|
||||||
qualifications = _qualifications,
|
|
||||||
eliminations = _eliminations,
|
|
||||||
|
|
||||||
bumpsGiven = _bumpsGiven,
|
bumpsGiven = _bumpsGiven,
|
||||||
totalPlaytime = _totalPlaytime,
|
totalPlaytime = playtimeToSend,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -196,7 +158,7 @@ public class StatsTracker : MonoBehaviour
|
|||||||
if (req.result != UnityWebRequest.Result.Success)
|
if (req.result != UnityWebRequest.Result.Success)
|
||||||
Debug.LogWarning($"[Stats] Upload failed: {req.error}");
|
Debug.LogWarning($"[Stats] Upload failed: {req.error}");
|
||||||
else
|
else
|
||||||
Debug.Log($"[Stats] Uploaded for {playerName}");
|
Debug.Log($"[Stats] Sent for {playerName} — dist:{_totalDistance:F0}m spd:{_maxSpeed:F1}m/s jumps:{_totalJumps}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── DTOs ─────────────────────────────────────────────────────────────
|
// ─── DTOs ─────────────────────────────────────────────────────────────
|
||||||
@@ -210,9 +172,6 @@ public class StatsTracker : MonoBehaviour
|
|||||||
public float totalDistance;
|
public float totalDistance;
|
||||||
public int totalJumps;
|
public int totalJumps;
|
||||||
public float maxSpeed;
|
public float maxSpeed;
|
||||||
public int racesPlayed;
|
|
||||||
public int qualifications;
|
|
||||||
public int eliminations;
|
|
||||||
public int bumpsGiven;
|
public int bumpsGiven;
|
||||||
public float totalPlaytime;
|
public float totalPlaytime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ public class ChatUI : MonoBehaviour
|
|||||||
_pollTimer = POLL_INTERVAL; // poll immediately
|
_pollTimer = POLL_INTERVAL; // poll immediately
|
||||||
Cursor.lockState = CursorLockMode.None;
|
Cursor.lockState = CursorLockMode.None;
|
||||||
Cursor.visible = true;
|
Cursor.visible = true;
|
||||||
|
// Release held movement keys so the ball doesn't keep moving while typing
|
||||||
|
FindFirstObjectByType<PlayerController>()?.ResetInputs();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 51e21afb9dba1904bb425ac1fae825cb
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ba062aa6c92b140379dbc06b43dd3b9b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8a0c9218a650547d98138cd835033977
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1484670163
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,134 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 727a75301c3d24613a3ebcec4a24c2c8
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 11
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 0
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
ignoreMasterTextureLimit: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 0
|
|
||||||
seamlessCubemap: 0
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 0
|
|
||||||
aniso: 1
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 1
|
|
||||||
wrapV: 1
|
|
||||||
wrapW: 0
|
|
||||||
nPOTScale: 0
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 0
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 1
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 2
|
|
||||||
textureShape: 1
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: Android
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: iPhone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID:
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
nameFileIdTable: {}
|
|
||||||
spritePackingTag:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
pSDShowRemoveMatteOption: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,654 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &1
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_PixelRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 45
|
|
||||||
width: 1666
|
|
||||||
height: 958
|
|
||||||
m_ShowMode: 4
|
|
||||||
m_Title:
|
|
||||||
m_RootView: {fileID: 6}
|
|
||||||
m_MinSize: {x: 950, y: 542}
|
|
||||||
m_MaxSize: {x: 10000, y: 10000}
|
|
||||||
--- !u!114 &2
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 466
|
|
||||||
width: 290
|
|
||||||
height: 442
|
|
||||||
m_MinSize: {x: 234, y: 271}
|
|
||||||
m_MaxSize: {x: 10004, y: 10021}
|
|
||||||
m_ActualView: {fileID: 14}
|
|
||||||
m_Panes:
|
|
||||||
- {fileID: 14}
|
|
||||||
m_Selected: 0
|
|
||||||
m_LastSelected: 0
|
|
||||||
--- !u!114 &3
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 4}
|
|
||||||
- {fileID: 2}
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 973
|
|
||||||
y: 0
|
|
||||||
width: 290
|
|
||||||
height: 908
|
|
||||||
m_MinSize: {x: 234, y: 492}
|
|
||||||
m_MaxSize: {x: 10004, y: 14042}
|
|
||||||
vertical: 1
|
|
||||||
controlID: 226
|
|
||||||
--- !u!114 &4
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 290
|
|
||||||
height: 466
|
|
||||||
m_MinSize: {x: 204, y: 221}
|
|
||||||
m_MaxSize: {x: 4004, y: 4021}
|
|
||||||
m_ActualView: {fileID: 17}
|
|
||||||
m_Panes:
|
|
||||||
- {fileID: 17}
|
|
||||||
m_Selected: 0
|
|
||||||
m_LastSelected: 0
|
|
||||||
--- !u!114 &5
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 466
|
|
||||||
width: 973
|
|
||||||
height: 442
|
|
||||||
m_MinSize: {x: 202, y: 221}
|
|
||||||
m_MaxSize: {x: 4002, y: 4021}
|
|
||||||
m_ActualView: {fileID: 15}
|
|
||||||
m_Panes:
|
|
||||||
- {fileID: 15}
|
|
||||||
m_Selected: 0
|
|
||||||
m_LastSelected: 0
|
|
||||||
--- !u!114 &6
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12008, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 7}
|
|
||||||
- {fileID: 8}
|
|
||||||
- {fileID: 9}
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 1666
|
|
||||||
height: 958
|
|
||||||
m_MinSize: {x: 950, y: 542}
|
|
||||||
m_MaxSize: {x: 10000, y: 10000}
|
|
||||||
--- !u!114 &7
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12011, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 1666
|
|
||||||
height: 30
|
|
||||||
m_MinSize: {x: 0, y: 0}
|
|
||||||
m_MaxSize: {x: 0, y: 0}
|
|
||||||
m_LastLoadedLayoutName: Tutorial
|
|
||||||
--- !u!114 &8
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 10}
|
|
||||||
- {fileID: 3}
|
|
||||||
- {fileID: 11}
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 30
|
|
||||||
width: 1666
|
|
||||||
height: 908
|
|
||||||
m_MinSize: {x: 713, y: 492}
|
|
||||||
m_MaxSize: {x: 18008, y: 14042}
|
|
||||||
vertical: 0
|
|
||||||
controlID: 74
|
|
||||||
--- !u!114 &9
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12042, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 938
|
|
||||||
width: 1666
|
|
||||||
height: 20
|
|
||||||
m_MinSize: {x: 0, y: 0}
|
|
||||||
m_MaxSize: {x: 0, y: 0}
|
|
||||||
--- !u!114 &10
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 12}
|
|
||||||
- {fileID: 5}
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 973
|
|
||||||
height: 908
|
|
||||||
m_MinSize: {x: 202, y: 442}
|
|
||||||
m_MaxSize: {x: 4002, y: 8042}
|
|
||||||
vertical: 1
|
|
||||||
controlID: 75
|
|
||||||
--- !u!114 &11
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 1263
|
|
||||||
y: 0
|
|
||||||
width: 403
|
|
||||||
height: 908
|
|
||||||
m_MinSize: {x: 277, y: 71}
|
|
||||||
m_MaxSize: {x: 4002, y: 4021}
|
|
||||||
m_ActualView: {fileID: 13}
|
|
||||||
m_Panes:
|
|
||||||
- {fileID: 13}
|
|
||||||
m_Selected: 0
|
|
||||||
m_LastSelected: 0
|
|
||||||
--- !u!114 &12
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Children: []
|
|
||||||
m_Position:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 973
|
|
||||||
height: 466
|
|
||||||
m_MinSize: {x: 202, y: 221}
|
|
||||||
m_MaxSize: {x: 4002, y: 4021}
|
|
||||||
m_ActualView: {fileID: 16}
|
|
||||||
m_Panes:
|
|
||||||
- {fileID: 16}
|
|
||||||
m_Selected: 0
|
|
||||||
m_LastSelected: 0
|
|
||||||
--- !u!114 &13
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_AutoRepaintOnSceneChange: 0
|
|
||||||
m_MinSize: {x: 275, y: 50}
|
|
||||||
m_MaxSize: {x: 4000, y: 4000}
|
|
||||||
m_TitleContent:
|
|
||||||
m_Text: Inspector
|
|
||||||
m_Image: {fileID: -6905738622615590433, guid: 0000000000000000d000000000000000,
|
|
||||||
type: 0}
|
|
||||||
m_Tooltip:
|
|
||||||
m_DepthBufferBits: 0
|
|
||||||
m_Pos:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 2
|
|
||||||
y: 19
|
|
||||||
width: 401
|
|
||||||
height: 887
|
|
||||||
m_ScrollPosition: {x: 0, y: 0}
|
|
||||||
m_InspectorMode: 0
|
|
||||||
m_PreviewResizer:
|
|
||||||
m_CachedPref: -160
|
|
||||||
m_ControlHash: -371814159
|
|
||||||
m_PrefName: Preview_InspectorPreview
|
|
||||||
m_PreviewWindow: {fileID: 0}
|
|
||||||
--- !u!114 &14
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_AutoRepaintOnSceneChange: 0
|
|
||||||
m_MinSize: {x: 230, y: 250}
|
|
||||||
m_MaxSize: {x: 10000, y: 10000}
|
|
||||||
m_TitleContent:
|
|
||||||
m_Text: Project
|
|
||||||
m_Image: {fileID: -7501376956915960154, guid: 0000000000000000d000000000000000,
|
|
||||||
type: 0}
|
|
||||||
m_Tooltip:
|
|
||||||
m_DepthBufferBits: 0
|
|
||||||
m_Pos:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 2
|
|
||||||
y: 19
|
|
||||||
width: 286
|
|
||||||
height: 421
|
|
||||||
m_SearchFilter:
|
|
||||||
m_NameFilter:
|
|
||||||
m_ClassNames: []
|
|
||||||
m_AssetLabels: []
|
|
||||||
m_AssetBundleNames: []
|
|
||||||
m_VersionControlStates: []
|
|
||||||
m_ReferencingInstanceIDs:
|
|
||||||
m_ScenePaths: []
|
|
||||||
m_ShowAllHits: 0
|
|
||||||
m_SearchArea: 0
|
|
||||||
m_Folders:
|
|
||||||
- Assets
|
|
||||||
m_ViewMode: 0
|
|
||||||
m_StartGridSize: 64
|
|
||||||
m_LastFolders:
|
|
||||||
- Assets
|
|
||||||
m_LastFoldersGridSize: -1
|
|
||||||
m_LastProjectPath: /Users/danielbrauer/Unity Projects/New Unity Project 47
|
|
||||||
m_IsLocked: 0
|
|
||||||
m_FolderTreeState:
|
|
||||||
scrollPos: {x: 0, y: 0}
|
|
||||||
m_SelectedIDs: ee240000
|
|
||||||
m_LastClickedID: 9454
|
|
||||||
m_ExpandedIDs: ee24000000ca9a3bffffff7f
|
|
||||||
m_RenameOverlay:
|
|
||||||
m_UserAcceptedRename: 0
|
|
||||||
m_Name:
|
|
||||||
m_OriginalName:
|
|
||||||
m_EditFieldRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
m_UserData: 0
|
|
||||||
m_IsWaitingForDelay: 0
|
|
||||||
m_IsRenaming: 0
|
|
||||||
m_OriginalEventType: 11
|
|
||||||
m_IsRenamingFilename: 1
|
|
||||||
m_ClientGUIView: {fileID: 0}
|
|
||||||
m_SearchString:
|
|
||||||
m_CreateAssetUtility:
|
|
||||||
m_EndAction: {fileID: 0}
|
|
||||||
m_InstanceID: 0
|
|
||||||
m_Path:
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_ResourceFile:
|
|
||||||
m_AssetTreeState:
|
|
||||||
scrollPos: {x: 0, y: 0}
|
|
||||||
m_SelectedIDs: 68fbffff
|
|
||||||
m_LastClickedID: 0
|
|
||||||
m_ExpandedIDs: ee240000
|
|
||||||
m_RenameOverlay:
|
|
||||||
m_UserAcceptedRename: 0
|
|
||||||
m_Name:
|
|
||||||
m_OriginalName:
|
|
||||||
m_EditFieldRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
m_UserData: 0
|
|
||||||
m_IsWaitingForDelay: 0
|
|
||||||
m_IsRenaming: 0
|
|
||||||
m_OriginalEventType: 11
|
|
||||||
m_IsRenamingFilename: 1
|
|
||||||
m_ClientGUIView: {fileID: 0}
|
|
||||||
m_SearchString:
|
|
||||||
m_CreateAssetUtility:
|
|
||||||
m_EndAction: {fileID: 0}
|
|
||||||
m_InstanceID: 0
|
|
||||||
m_Path:
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_ResourceFile:
|
|
||||||
m_ListAreaState:
|
|
||||||
m_SelectedInstanceIDs: 68fbffff
|
|
||||||
m_LastClickedInstanceID: -1176
|
|
||||||
m_HadKeyboardFocusLastEvent: 0
|
|
||||||
m_ExpandedInstanceIDs: c6230000
|
|
||||||
m_RenameOverlay:
|
|
||||||
m_UserAcceptedRename: 0
|
|
||||||
m_Name:
|
|
||||||
m_OriginalName:
|
|
||||||
m_EditFieldRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
m_UserData: 0
|
|
||||||
m_IsWaitingForDelay: 0
|
|
||||||
m_IsRenaming: 0
|
|
||||||
m_OriginalEventType: 11
|
|
||||||
m_IsRenamingFilename: 1
|
|
||||||
m_ClientGUIView: {fileID: 0}
|
|
||||||
m_CreateAssetUtility:
|
|
||||||
m_EndAction: {fileID: 0}
|
|
||||||
m_InstanceID: 0
|
|
||||||
m_Path:
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_ResourceFile:
|
|
||||||
m_NewAssetIndexInList: -1
|
|
||||||
m_ScrollPosition: {x: 0, y: 0}
|
|
||||||
m_GridSize: 64
|
|
||||||
m_DirectoriesAreaWidth: 110
|
|
||||||
--- !u!114 &15
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_AutoRepaintOnSceneChange: 1
|
|
||||||
m_MinSize: {x: 200, y: 200}
|
|
||||||
m_MaxSize: {x: 4000, y: 4000}
|
|
||||||
m_TitleContent:
|
|
||||||
m_Text: Game
|
|
||||||
m_Image: {fileID: -2087823869225018852, guid: 0000000000000000d000000000000000,
|
|
||||||
type: 0}
|
|
||||||
m_Tooltip:
|
|
||||||
m_DepthBufferBits: 32
|
|
||||||
m_Pos:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 19
|
|
||||||
width: 971
|
|
||||||
height: 421
|
|
||||||
m_MaximizeOnPlay: 0
|
|
||||||
m_Gizmos: 0
|
|
||||||
m_Stats: 0
|
|
||||||
m_SelectedSizes: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
||||||
m_TargetDisplay: 0
|
|
||||||
m_ZoomArea:
|
|
||||||
m_HRangeLocked: 0
|
|
||||||
m_VRangeLocked: 0
|
|
||||||
m_HBaseRangeMin: -242.75
|
|
||||||
m_HBaseRangeMax: 242.75
|
|
||||||
m_VBaseRangeMin: -101
|
|
||||||
m_VBaseRangeMax: 101
|
|
||||||
m_HAllowExceedBaseRangeMin: 1
|
|
||||||
m_HAllowExceedBaseRangeMax: 1
|
|
||||||
m_VAllowExceedBaseRangeMin: 1
|
|
||||||
m_VAllowExceedBaseRangeMax: 1
|
|
||||||
m_ScaleWithWindow: 0
|
|
||||||
m_HSlider: 0
|
|
||||||
m_VSlider: 0
|
|
||||||
m_IgnoreScrollWheelUntilClicked: 0
|
|
||||||
m_EnableMouseInput: 1
|
|
||||||
m_EnableSliderZoom: 0
|
|
||||||
m_UniformScale: 1
|
|
||||||
m_UpDirection: 1
|
|
||||||
m_DrawArea:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 17
|
|
||||||
width: 971
|
|
||||||
height: 404
|
|
||||||
m_Scale: {x: 2, y: 2}
|
|
||||||
m_Translation: {x: 485.5, y: 202}
|
|
||||||
m_MarginLeft: 0
|
|
||||||
m_MarginRight: 0
|
|
||||||
m_MarginTop: 0
|
|
||||||
m_MarginBottom: 0
|
|
||||||
m_LastShownAreaInsideMargins:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: -242.75
|
|
||||||
y: -101
|
|
||||||
width: 485.5
|
|
||||||
height: 202
|
|
||||||
m_MinimalGUI: 1
|
|
||||||
m_defaultScale: 2
|
|
||||||
m_TargetTexture: {fileID: 0}
|
|
||||||
m_CurrentColorSpace: 0
|
|
||||||
m_LastWindowPixelSize: {x: 1942, y: 842}
|
|
||||||
m_ClearInEditMode: 1
|
|
||||||
m_NoCameraWarning: 1
|
|
||||||
m_LowResolutionForAspectRatios: 01000000000100000100
|
|
||||||
--- !u!114 &16
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_AutoRepaintOnSceneChange: 1
|
|
||||||
m_MinSize: {x: 200, y: 200}
|
|
||||||
m_MaxSize: {x: 4000, y: 4000}
|
|
||||||
m_TitleContent:
|
|
||||||
m_Text: Scene
|
|
||||||
m_Image: {fileID: 2318424515335265636, guid: 0000000000000000d000000000000000,
|
|
||||||
type: 0}
|
|
||||||
m_Tooltip:
|
|
||||||
m_DepthBufferBits: 32
|
|
||||||
m_Pos:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 19
|
|
||||||
width: 971
|
|
||||||
height: 445
|
|
||||||
m_SceneLighting: 1
|
|
||||||
lastFramingTime: 0
|
|
||||||
m_2DMode: 0
|
|
||||||
m_isRotationLocked: 0
|
|
||||||
m_AudioPlay: 0
|
|
||||||
m_Position:
|
|
||||||
m_Target: {x: 0, y: 0, z: 0}
|
|
||||||
speed: 2
|
|
||||||
m_Value: {x: 0, y: 0, z: 0}
|
|
||||||
m_RenderMode: 0
|
|
||||||
m_ValidateTrueMetals: 0
|
|
||||||
m_SceneViewState:
|
|
||||||
showFog: 1
|
|
||||||
showMaterialUpdate: 0
|
|
||||||
showSkybox: 1
|
|
||||||
showFlares: 1
|
|
||||||
showImageEffects: 1
|
|
||||||
grid:
|
|
||||||
xGrid:
|
|
||||||
m_Target: 0
|
|
||||||
speed: 2
|
|
||||||
m_Value: 0
|
|
||||||
yGrid:
|
|
||||||
m_Target: 1
|
|
||||||
speed: 2
|
|
||||||
m_Value: 1
|
|
||||||
zGrid:
|
|
||||||
m_Target: 0
|
|
||||||
speed: 2
|
|
||||||
m_Value: 0
|
|
||||||
m_Rotation:
|
|
||||||
m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
|
|
||||||
speed: 2
|
|
||||||
m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
|
|
||||||
m_Size:
|
|
||||||
m_Target: 10
|
|
||||||
speed: 2
|
|
||||||
m_Value: 10
|
|
||||||
m_Ortho:
|
|
||||||
m_Target: 0
|
|
||||||
speed: 2
|
|
||||||
m_Value: 0
|
|
||||||
m_LastSceneViewRotation: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_LastSceneViewOrtho: 0
|
|
||||||
m_ReplacementShader: {fileID: 0}
|
|
||||||
m_ReplacementString:
|
|
||||||
m_LastLockedObject: {fileID: 0}
|
|
||||||
m_ViewIsLockedToObject: 0
|
|
||||||
--- !u!114 &17
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 52
|
|
||||||
m_PrefabParentObject: {fileID: 0}
|
|
||||||
m_PrefabInternal: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 1
|
|
||||||
m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_AutoRepaintOnSceneChange: 0
|
|
||||||
m_MinSize: {x: 200, y: 200}
|
|
||||||
m_MaxSize: {x: 4000, y: 4000}
|
|
||||||
m_TitleContent:
|
|
||||||
m_Text: Hierarchy
|
|
||||||
m_Image: {fileID: -590624980919486359, guid: 0000000000000000d000000000000000,
|
|
||||||
type: 0}
|
|
||||||
m_Tooltip:
|
|
||||||
m_DepthBufferBits: 0
|
|
||||||
m_Pos:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 2
|
|
||||||
y: 19
|
|
||||||
width: 286
|
|
||||||
height: 445
|
|
||||||
m_TreeViewState:
|
|
||||||
scrollPos: {x: 0, y: 0}
|
|
||||||
m_SelectedIDs: 68fbffff
|
|
||||||
m_LastClickedID: -1176
|
|
||||||
m_ExpandedIDs: 7efbffff00000000
|
|
||||||
m_RenameOverlay:
|
|
||||||
m_UserAcceptedRename: 0
|
|
||||||
m_Name:
|
|
||||||
m_OriginalName:
|
|
||||||
m_EditFieldRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 0
|
|
||||||
height: 0
|
|
||||||
m_UserData: 0
|
|
||||||
m_IsWaitingForDelay: 0
|
|
||||||
m_IsRenaming: 0
|
|
||||||
m_OriginalEventType: 11
|
|
||||||
m_IsRenamingFilename: 0
|
|
||||||
m_ClientGUIView: {fileID: 0}
|
|
||||||
m_SearchString:
|
|
||||||
m_ExpandedScenes:
|
|
||||||
-
|
|
||||||
m_CurrenRootInstanceID: 0
|
|
||||||
m_Locked: 0
|
|
||||||
m_CurrentSortingName: TransformSorting
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: eabc9546105bf4accac1fd62a63e88e6
|
|
||||||
timeCreated: 1487337779
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5a9bcd70e6a4b4b05badaa72e827d8e0
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1475835190
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3ad9b87dffba344c89909c6d1b1c17e1
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1475593892
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(Readme))]
|
|
||||||
[InitializeOnLoad]
|
|
||||||
public class ReadmeEditor : Editor
|
|
||||||
{
|
|
||||||
static string s_ShowedReadmeSessionStateName = "ReadmeEditor.showedReadme";
|
|
||||||
|
|
||||||
static string s_ReadmeSourceDirectory = "Assets/TutorialInfo";
|
|
||||||
|
|
||||||
const float k_Space = 16f;
|
|
||||||
|
|
||||||
static ReadmeEditor()
|
|
||||||
{
|
|
||||||
EditorApplication.delayCall += SelectReadmeAutomatically;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RemoveTutorial()
|
|
||||||
{
|
|
||||||
if (EditorUtility.DisplayDialog("Remove Readme Assets",
|
|
||||||
|
|
||||||
$"All contents under {s_ReadmeSourceDirectory} will be removed, are you sure you want to proceed?",
|
|
||||||
"Proceed",
|
|
||||||
"Cancel"))
|
|
||||||
{
|
|
||||||
if (Directory.Exists(s_ReadmeSourceDirectory))
|
|
||||||
{
|
|
||||||
FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory);
|
|
||||||
FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory + ".meta");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log($"Could not find the Readme folder at {s_ReadmeSourceDirectory}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var readmeAsset = SelectReadme();
|
|
||||||
if (readmeAsset != null)
|
|
||||||
{
|
|
||||||
var path = AssetDatabase.GetAssetPath(readmeAsset);
|
|
||||||
FileUtil.DeleteFileOrDirectory(path + ".meta");
|
|
||||||
FileUtil.DeleteFileOrDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SelectReadmeAutomatically()
|
|
||||||
{
|
|
||||||
if (!SessionState.GetBool(s_ShowedReadmeSessionStateName, false))
|
|
||||||
{
|
|
||||||
var readme = SelectReadme();
|
|
||||||
SessionState.SetBool(s_ShowedReadmeSessionStateName, true);
|
|
||||||
|
|
||||||
if (readme && !readme.loadedLayout)
|
|
||||||
{
|
|
||||||
LoadLayout();
|
|
||||||
readme.loadedLayout = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LoadLayout()
|
|
||||||
{
|
|
||||||
var assembly = typeof(EditorApplication).Assembly;
|
|
||||||
var windowLayoutType = assembly.GetType("UnityEditor.WindowLayout", true);
|
|
||||||
var method = windowLayoutType.GetMethod("LoadWindowLayout", BindingFlags.Public | BindingFlags.Static);
|
|
||||||
method.Invoke(null, new object[] { Path.Combine(Application.dataPath, "TutorialInfo/Layout.wlt"), false });
|
|
||||||
}
|
|
||||||
|
|
||||||
static Readme SelectReadme()
|
|
||||||
{
|
|
||||||
var ids = AssetDatabase.FindAssets("Readme t:Readme");
|
|
||||||
if (ids.Length == 1)
|
|
||||||
{
|
|
||||||
var readmeObject = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(ids[0]));
|
|
||||||
|
|
||||||
Selection.objects = new UnityEngine.Object[] { readmeObject };
|
|
||||||
|
|
||||||
return (Readme)readmeObject;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log("Couldn't find a readme");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHeaderGUI()
|
|
||||||
{
|
|
||||||
var readme = (Readme)target;
|
|
||||||
Init();
|
|
||||||
|
|
||||||
var iconWidth = Mathf.Min(EditorGUIUtility.currentViewWidth / 3f - 20f, 128f);
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal("In BigTitle");
|
|
||||||
{
|
|
||||||
if (readme.icon != null)
|
|
||||||
{
|
|
||||||
GUILayout.Space(k_Space);
|
|
||||||
GUILayout.Label(readme.icon, GUILayout.Width(iconWidth), GUILayout.Height(iconWidth));
|
|
||||||
}
|
|
||||||
GUILayout.Space(k_Space);
|
|
||||||
GUILayout.BeginVertical();
|
|
||||||
{
|
|
||||||
|
|
||||||
GUILayout.FlexibleSpace();
|
|
||||||
GUILayout.Label(readme.title, TitleStyle);
|
|
||||||
GUILayout.FlexibleSpace();
|
|
||||||
}
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
GUILayout.FlexibleSpace();
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
var readme = (Readme)target;
|
|
||||||
Init();
|
|
||||||
|
|
||||||
foreach (var section in readme.sections)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(section.heading))
|
|
||||||
{
|
|
||||||
GUILayout.Label(section.heading, HeadingStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(section.text))
|
|
||||||
{
|
|
||||||
GUILayout.Label(section.text, BodyStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(section.linkText))
|
|
||||||
{
|
|
||||||
if (LinkLabel(new GUIContent(section.linkText)))
|
|
||||||
{
|
|
||||||
Application.OpenURL(section.url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Space(k_Space);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button("Remove Readme Assets", ButtonStyle))
|
|
||||||
{
|
|
||||||
RemoveTutorial();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool m_Initialized;
|
|
||||||
|
|
||||||
GUIStyle LinkStyle
|
|
||||||
{
|
|
||||||
get { return m_LinkStyle; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
GUIStyle m_LinkStyle;
|
|
||||||
|
|
||||||
GUIStyle TitleStyle
|
|
||||||
{
|
|
||||||
get { return m_TitleStyle; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
GUIStyle m_TitleStyle;
|
|
||||||
|
|
||||||
GUIStyle HeadingStyle
|
|
||||||
{
|
|
||||||
get { return m_HeadingStyle; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
GUIStyle m_HeadingStyle;
|
|
||||||
|
|
||||||
GUIStyle BodyStyle
|
|
||||||
{
|
|
||||||
get { return m_BodyStyle; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
GUIStyle m_BodyStyle;
|
|
||||||
|
|
||||||
GUIStyle ButtonStyle
|
|
||||||
{
|
|
||||||
get { return m_ButtonStyle; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
GUIStyle m_ButtonStyle;
|
|
||||||
|
|
||||||
void Init()
|
|
||||||
{
|
|
||||||
if (m_Initialized)
|
|
||||||
return;
|
|
||||||
m_BodyStyle = new GUIStyle(EditorStyles.label);
|
|
||||||
m_BodyStyle.wordWrap = true;
|
|
||||||
m_BodyStyle.fontSize = 14;
|
|
||||||
m_BodyStyle.richText = true;
|
|
||||||
|
|
||||||
m_TitleStyle = new GUIStyle(m_BodyStyle);
|
|
||||||
m_TitleStyle.fontSize = 26;
|
|
||||||
|
|
||||||
m_HeadingStyle = new GUIStyle(m_BodyStyle);
|
|
||||||
m_HeadingStyle.fontStyle = FontStyle.Bold;
|
|
||||||
m_HeadingStyle.fontSize = 18;
|
|
||||||
|
|
||||||
m_LinkStyle = new GUIStyle(m_BodyStyle);
|
|
||||||
m_LinkStyle.wordWrap = false;
|
|
||||||
|
|
||||||
// Match selection color which works nicely for both light and dark skins
|
|
||||||
m_LinkStyle.normal.textColor = new Color(0x00 / 255f, 0x78 / 255f, 0xDA / 255f, 1f);
|
|
||||||
m_LinkStyle.stretchWidth = false;
|
|
||||||
|
|
||||||
m_ButtonStyle = new GUIStyle(EditorStyles.miniButton);
|
|
||||||
m_ButtonStyle.fontStyle = FontStyle.Bold;
|
|
||||||
|
|
||||||
m_Initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LinkLabel(GUIContent label, params GUILayoutOption[] options)
|
|
||||||
{
|
|
||||||
var position = GUILayoutUtility.GetRect(label, LinkStyle, options);
|
|
||||||
|
|
||||||
Handles.BeginGUI();
|
|
||||||
Handles.color = LinkStyle.normal.textColor;
|
|
||||||
Handles.DrawLine(new Vector3(position.xMin, position.yMax), new Vector3(position.xMax, position.yMax));
|
|
||||||
Handles.color = Color.white;
|
|
||||||
Handles.EndGUI();
|
|
||||||
|
|
||||||
EditorGUIUtility.AddCursorRect(position, MouseCursor.Link);
|
|
||||||
|
|
||||||
return GUI.Button(position, label, LinkStyle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 476cc7d7cd9874016adc216baab94a0a
|
|
||||||
timeCreated: 1484146680
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public class Readme : ScriptableObject
|
|
||||||
{
|
|
||||||
public Texture2D icon;
|
|
||||||
public string title;
|
|
||||||
public Section[] sections;
|
|
||||||
public bool loadedLayout;
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class Section
|
|
||||||
{
|
|
||||||
public string heading, text, linkText, url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fcf7219bab7fe46a1ad266029b2fee19
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences:
|
|
||||||
- icon: {instanceID: 0}
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {fileID: 2800000, guid: a186f8a87ca4f4d3aa864638ad5dfb65, type: 3}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -56,8 +56,12 @@ const gameServer = new Server({
|
|||||||
|
|
||||||
app.post('/stats/update', (req, res) => {
|
app.post('/stats/update', (req, res) => {
|
||||||
const parsed = statsUpdateSchema.safeParse(req.body);
|
const parsed = statsUpdateSchema.safeParse(req.body);
|
||||||
if (!parsed.success) return res.status(400).json({ error: parsed.error.issues });
|
if (!parsed.success) {
|
||||||
|
console.warn('[Stats] Bad update request:', JSON.stringify(parsed.error.issues));
|
||||||
|
return res.status(400).json({ error: parsed.error.issues });
|
||||||
|
}
|
||||||
const ok = Stats.update(parsed.data.name, parsed.data.stats);
|
const ok = Stats.update(parsed.data.name, parsed.data.stats);
|
||||||
|
console.log(`[Stats] Update for "${parsed.data.name}": ok=${ok}`, JSON.stringify(parsed.data.stats));
|
||||||
res.json({ ok });
|
res.json({ ok });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user