Compare commits
2 Commits
83544fe3d2
...
aa27725c4e
| Author | SHA1 | Date | |
|---|---|---|---|
| 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:
|
|
||||||
@@ -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
@@ -1,11 +1,21 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
[Type(0, "float32")] public float x = 0;
|
#if UNITY_5_3_OR_NEWER
|
||||||
[Type(1, "float32")] public float y = 5;
|
[Preserve]
|
||||||
[Type(2, "float32")] public float z = 0;
|
#endif
|
||||||
|
public NetworkPlayer() { }
|
||||||
|
|
||||||
|
[Type(0, "float32")] public float x = 0;
|
||||||
|
[Type(1, "float32")] public float y = 5;
|
||||||
|
[Type(2, "float32")] public float z = 0;
|
||||||
[Type(3, "float32")] public float vx = 0;
|
[Type(3, "float32")] public float vx = 0;
|
||||||
[Type(4, "float32")] public float vy = 0;
|
[Type(4, "float32")] public float vy = 0;
|
||||||
[Type(5, "float32")] public float vz = 0;
|
[Type(5, "float32")] public float vz = 0;
|
||||||
@@ -13,31 +23,35 @@ public partial class NetworkPlayer : Schema
|
|||||||
[Type(7, "float32")] public float ry = 0;
|
[Type(7, "float32")] public float ry = 0;
|
||||||
[Type(8, "float32")] public float rz = 0;
|
[Type(8, "float32")] public float rz = 0;
|
||||||
[Type(9, "float32")] public float rw = 1;
|
[Type(9, "float32")] public float rw = 1;
|
||||||
[Type(10, "float64")] public double t = 0;
|
[Type(10, "float64")] public double t = 0;
|
||||||
[Type(11, "string")] public string name = "";
|
[Type(11, "string")] public string name = "";
|
||||||
[Type(12, "float32")] public float colorR = 1;
|
[Type(12, "float32")] public float colorR = 1;
|
||||||
[Type(13, "float32")] public float colorG = 1;
|
[Type(13, "float32")] public float colorG = 1;
|
||||||
[Type(14, "float32")] public float colorB = 1;
|
[Type(14, "float32")] public float colorB = 1;
|
||||||
[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 sbyte checkpointIndex = 0;
|
||||||
[Type(21, "int8")] public int checkpointIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class NetworkState : Schema
|
public partial class NetworkState : Schema
|
||||||
{
|
{
|
||||||
[Type(0, "map", typeof(MapSchema<NetworkPlayer>))]
|
#if UNITY_5_3_OR_NEWER
|
||||||
public MapSchema<NetworkPlayer> players;
|
[Preserve]
|
||||||
|
#endif
|
||||||
|
public NetworkState() { }
|
||||||
|
|
||||||
[Type(1, "string")] public string phase = "lobby";
|
[Type(0, "map", typeof(MapSchema<NetworkPlayer>))]
|
||||||
[Type(2, "float32")] public float countdown = 0;
|
public MapSchema<NetworkPlayer> players = null;
|
||||||
[Type(3, "int8")] public int roundNumber = 1;
|
|
||||||
[Type(4, "int8")] public int totalRounds = 4;
|
[Type(1, "string")] public string phase = "lobby";
|
||||||
[Type(5, "int8")] public int playersAlive = 0;
|
[Type(2, "float32")] public float countdown = 0;
|
||||||
[Type(6, "string")] public string gameMode = "race";
|
[Type(3, "int8")] public sbyte roundNumber = 1;
|
||||||
[Type(7, "string")] public string winnerName = "";
|
[Type(4, "int8")] public sbyte totalRounds = 3;
|
||||||
|
[Type(5, "int8")] public sbyte playersAlive = 0;
|
||||||
|
[Type(6, "string")] public string gameMode = "race";
|
||||||
|
[Type(7, "string")] public string winnerName = "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5bf5e078a2ee9ed4fa95eacab5753f3a
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d1f3d6aaca8e97498f40d827f7c5216
|
|
||||||
@@ -4,41 +4,40 @@ 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;
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
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,11 +48,7 @@ public class StatsTracker : MonoBehaviour
|
|||||||
var nm = NetworkManager.Instance;
|
var nm = NetworkManager.Instance;
|
||||||
if (nm != null)
|
if (nm != null)
|
||||||
{
|
{
|
||||||
nm.OnRoundStart += OnRoundStart;
|
nm.OnConnected += OnConnected;
|
||||||
nm.OnRoundEnd += OnRoundEnd;
|
|
||||||
nm.OnQualified += OnQualified;
|
|
||||||
nm.OnEliminated += OnEliminated;
|
|
||||||
nm.OnConnected += OnConnected;
|
|
||||||
nm.OnDisconnected += OnDisconnected;
|
nm.OnDisconnected += OnDisconnected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,123 +58,90 @@ public class StatsTracker : MonoBehaviour
|
|||||||
var nm = NetworkManager.Instance;
|
var nm = NetworkManager.Instance;
|
||||||
if (nm != null)
|
if (nm != null)
|
||||||
{
|
{
|
||||||
nm.OnRoundStart -= OnRoundStart;
|
nm.OnConnected -= OnConnected;
|
||||||
nm.OnRoundEnd -= OnRoundEnd;
|
|
||||||
nm.OnQualified -= OnQualified;
|
|
||||||
nm.OnEliminated -= OnEliminated;
|
|
||||||
nm.OnConnected -= OnConnected;
|
|
||||||
nm.OnDisconnected -= OnDisconnected;
|
nm.OnDisconnected -= OnDisconnected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
{
|
_totalDistance += delta;
|
||||||
_roundDistance += 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;
|
yield return new WaitForSeconds(SEND_INTERVAL);
|
||||||
_lastPos = transform.position;
|
if (_tracking) SendStats();
|
||||||
_trackingActive = true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRoundEnd(int round)
|
// ─── HTTP send ────────────────────────────────────────────────────────
|
||||||
{
|
|
||||||
_trackingActive = false;
|
|
||||||
SendStats();
|
|
||||||
_roundDistance = 0f;
|
|
||||||
_roundMaxSpeed = 0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnQualified(string sessionId)
|
|
||||||
{
|
|
||||||
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
|
||||||
{
|
{
|
||||||
name = playerName,
|
name = playerName,
|
||||||
stats = new StatsData
|
stats = new StatsData
|
||||||
{
|
{
|
||||||
totalDistance = _totalDistance,
|
totalDistance = _totalDistance,
|
||||||
totalJumps = _totalJumps,
|
totalJumps = _totalJumps,
|
||||||
maxSpeed = _maxSpeed,
|
maxSpeed = _maxSpeed,
|
||||||
|
bumpsGiven = _bumpsGiven,
|
||||||
racesPlayed = _racesPlayed,
|
totalPlaytime = playtimeToSend,
|
||||||
qualifications = _qualifications,
|
|
||||||
eliminations = _eliminations,
|
|
||||||
|
|
||||||
bumpsGiven = _bumpsGiven,
|
|
||||||
totalPlaytime = _totalPlaytime,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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