Compare commits
15
Commits
pre-restructure
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a0618fd31 | ||
|
|
ec4619d9dc | ||
|
|
2a20bd68fe | ||
|
|
4f48d258b5 | ||
|
|
46160d86dc | ||
|
|
ad598143f8 | ||
|
|
bb0f2b760c | ||
|
|
40b4547c71 | ||
|
|
1c1e50809a | ||
|
|
f5b302b3e3 | ||
|
|
2b35d3f754 | ||
|
|
382f6c7f63 | ||
|
|
ed28763017 | ||
|
|
f1fadf7909 | ||
|
|
b915ad78c7 |
+102
@@ -0,0 +1,102 @@
|
||||
# Nightclub Arcadia — git attributes
|
||||
#
|
||||
# Two jobs: make Unity's YAML files mergeable, and keep line endings from
|
||||
# becoming a source of phantom diffs.
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Unity YAML — text, LF, and merged with UnityYAMLMerge
|
||||
# ---------------------------------------------------------------------------
|
||||
# The merge driver needs a one-time setup per machine; see §"Merge driver" in
|
||||
# CLAUDE.md. Without it git falls back to a normal text merge, which for scenes
|
||||
# and prefabs means conflicts that are painful but not silently wrong.
|
||||
*.unity text eol=lf merge=unityyamlmerge
|
||||
*.prefab text eol=lf merge=unityyamlmerge
|
||||
*.asset text eol=lf merge=unityyamlmerge
|
||||
*.mat text eol=lf merge=unityyamlmerge
|
||||
*.anim text eol=lf merge=unityyamlmerge
|
||||
*.controller text eol=lf merge=unityyamlmerge
|
||||
*.overrideController text eol=lf merge=unityyamlmerge
|
||||
*.physicMaterial text eol=lf merge=unityyamlmerge
|
||||
*.physicsMaterial2D text eol=lf merge=unityyamlmerge
|
||||
*.playable text eol=lf merge=unityyamlmerge
|
||||
*.mask text eol=lf merge=unityyamlmerge
|
||||
*.brush text eol=lf merge=unityyamlmerge
|
||||
*.flare text eol=lf merge=unityyamlmerge
|
||||
*.lighting text eol=lf merge=unityyamlmerge
|
||||
*.terrainlayer text eol=lf merge=unityyamlmerge
|
||||
*.signal text eol=lf merge=unityyamlmerge
|
||||
*.guiskin text eol=lf merge=unityyamlmerge
|
||||
*.fontsettings text eol=lf merge=unityyamlmerge
|
||||
*.meta text eol=lf
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Source, config and prose
|
||||
# ---------------------------------------------------------------------------
|
||||
*.cs text eol=lf diff=csharp
|
||||
*.yarn text eol=lf
|
||||
*.yarnproject text eol=lf
|
||||
*.asmdef text eol=lf
|
||||
*.asmref text eol=lf
|
||||
*.inputactions text eol=lf
|
||||
*.shader text eol=lf
|
||||
*.compute text eol=lf
|
||||
*.cginc text eol=lf
|
||||
*.hlsl text eol=lf
|
||||
*.shadergraph text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.py text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.csproj text eol=lf
|
||||
*.xml text eol=lf
|
||||
*.gitattributes text eol=lf
|
||||
*.gitignore text eol=lf
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Binary — never diffed, never line-ending converted
|
||||
# ---------------------------------------------------------------------------
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.tga binary
|
||||
*.tif binary
|
||||
*.tiff binary
|
||||
*.psd binary
|
||||
*.exr binary
|
||||
*.hdr binary
|
||||
*.fbx binary
|
||||
*.obj binary
|
||||
*.blend binary
|
||||
*.wav binary
|
||||
*.mp3 binary
|
||||
*.ogg binary
|
||||
*.aif binary
|
||||
*.ttf binary
|
||||
*.otf binary
|
||||
*.pdf binary
|
||||
*.dll binary
|
||||
*.pdb binary
|
||||
*.so binary
|
||||
*.dylib binary
|
||||
*.bundle binary
|
||||
*.a binary
|
||||
*.unitypackage binary
|
||||
*.cubemap binary
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Git LFS — deliberately NOT enabled yet
|
||||
# ---------------------------------------------------------------------------
|
||||
# git-lfs is installed locally, but this repo pushes to a self-hosted server
|
||||
# whose LFS support has not been verified, and enabling LFS against a server
|
||||
# that lacks it breaks pushing. There is also almost nothing to store yet: one
|
||||
# placeholder PNG plus the StarterAssets meshes.
|
||||
#
|
||||
# When real art lands, verify the server first, then add:
|
||||
# *.png filter=lfs diff=lfs merge=lfs -text
|
||||
# *.fbx filter=lfs diff=lfs merge=lfs -text
|
||||
# *.wav filter=lfs diff=lfs merge=lfs -text
|
||||
# and migrate existing blobs with `git lfs migrate import --include=...`.
|
||||
# Adding the filter without migrating leaves old blobs outside LFS, which is
|
||||
# confusing rather than broken.
|
||||
@@ -127,3 +127,9 @@ tools/**/obj/
|
||||
*.tar.gz
|
||||
*.7z
|
||||
*.rar
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Local build and test output (Makefile targets)
|
||||
# ---------------------------------------------------------------------------
|
||||
/.test-results/
|
||||
/build/
|
||||
|
||||
@@ -17,7 +17,9 @@ to fix — it is the checkout path). The Unity project is a **subdirectory**:
|
||||
/Users/lennart/Dev/nightlcub-arcadia/ # git root
|
||||
├── CLAUDE.md, AGENTS.md # this reference
|
||||
├── docs/ # design + plan docs (markdown)
|
||||
├── writing/ # writer-facing context — see §4
|
||||
├── tools/YarnCheck/ # .NET 9 Yarn compiler/player, no Unity needed
|
||||
├── tools/writing/ # voice-sheet sync (md <-> skill_bible.json)
|
||||
├── .gitignore # macOS / IDE / toolchain rules
|
||||
└── NightclubArcadia/ # ← the Unity project (-projectPath)
|
||||
├── .gitignore # Unity rules (anchored, must stay here)
|
||||
@@ -45,17 +47,47 @@ AI Navigation 2.0.14, ProBuilder 6.1.2, Test Framework 1.7.0. Yarn Spinner is an
|
||||
overwritten by the Editor setup scripts. Edit the JSON.
|
||||
2. **Never hand-edit scene or prefab YAML unless you have read the surrounding block.**
|
||||
GUID/fileID surgery in `.unity` / `.prefab` files silently detaches components.
|
||||
3. **One Unity instance per project path.** Unity refuses to open a project in batch
|
||||
5. **One Unity instance per project path.** Unity refuses to open a project in batch
|
||||
mode while the Editor has it open — a single instance at a time. Always check before
|
||||
any `-batchmode` invocation (§3.1).
|
||||
4. **Prefer YarnCheck over Unity for dialogue validation.** It is seconds, not minutes,
|
||||
and needs no Editor lock (§5.3).
|
||||
5. **Do not commit on the user's behalf** unless asked. Unity writes to tracked files
|
||||
6. **Prefer YarnCheck over Unity for dialogue validation.** It is seconds, not minutes,
|
||||
and needs no Editor lock (§5.5).
|
||||
7. **Do not commit on the user's behalf** unless asked. Unity writes to tracked files
|
||||
(`ProjectSettings/*`, `.meta`, scenes) as a side effect of simply being open, so
|
||||
`git status` noise is expected and is not always yours.
|
||||
|
||||
---
|
||||
|
||||
## 2b. Everyday commands
|
||||
|
||||
A `Makefile` at the repo root wraps everything in this document. Prefer it — the exact
|
||||
invocations live there instead of being retyped.
|
||||
|
||||
```bash
|
||||
make # list targets
|
||||
make check # yarn + voice sheets + EditMode — run this before committing
|
||||
make test # EditMode suite, with a readable summary
|
||||
make yarn # compile every Yarn script (seconds, no Unity)
|
||||
make build # macOS player into build/
|
||||
make lock # fail if the Editor has the project open
|
||||
```
|
||||
|
||||
`make test` and `make build` refuse to run while the Editor is open, which removes the most
|
||||
common way these commands fail confusingly.
|
||||
|
||||
### Merge driver — one-time per machine
|
||||
|
||||
`.gitattributes` marks Unity YAML for `unityyamlmerge`. Git needs to be told what that is, or
|
||||
it falls back to a line-oriented text merge that can produce a scene Unity still loads and that
|
||||
is quietly wrong:
|
||||
|
||||
```bash
|
||||
make merge-driver
|
||||
```
|
||||
|
||||
That points git at `UnityYAMLMerge` inside the Editor bundle (`Contents/Helpers/`, not
|
||||
`Contents/Tools/` — the path in most online guides is wrong for Unity 6 on macOS).
|
||||
|
||||
## 3. Unity from the command line
|
||||
|
||||
### 3.0 Two different tools, both present
|
||||
@@ -101,10 +133,11 @@ misread the check. `Temp/UnityLockfile` and `unity status` are the other two sig
|
||||
Useful flags: `--filter <pattern>`, `--retries <0-10>` (reports tests that pass on retry as
|
||||
flaky), `--rerun-failed`, `--shard N/M` for parallel CI, `--coverage`, `--timeout <seconds>`.
|
||||
|
||||
`--mode PlayMode` runs the PlayMode suite. **There are none yet** — `Assets/Tests/` is EditMode
|
||||
only, so that command reports zero tests. A PlayMode suite needs a new
|
||||
`Assets/Tests/PlayMode/*.asmdef` referencing `UnityEngine.TestRunner` with `includePlatforms`
|
||||
left empty.
|
||||
`--mode PlayMode` runs `Assets/Tests/PlayMode` — currently `BootstrapTests`, which loads
|
||||
`Bootstrap.unity` and asserts the whole game comes up: both scenes loaded, the player present
|
||||
and tagged, the dialogue runner found, both NPCs having resolved their runner across the scene
|
||||
boundary, and the reveal camera bound to the player. **If that suite fails, the game does not
|
||||
start.**
|
||||
|
||||
Raw-Editor equivalent, if you need a flag the CLI does not expose:
|
||||
|
||||
@@ -133,11 +166,21 @@ the legacy desktop player flags — and builds whatever scenes `EditorBuildSetti
|
||||
`--profile <name>` selects a profile from `Assets/Settings/Build Profiles` (the profile defines
|
||||
the target). `-l/--log-file` overrides the log path; the log streams to console unless `--no-tail`.
|
||||
|
||||
**No build script exists yet.** When one is added, put it at `Assets/Editor/BuildPipeline.cs` and
|
||||
call `--execute-method NightclubArcadia.Editor.BuildPipeline.BuildMacOS`. The CLI forwards the
|
||||
output path as `-buildOutput` and **your method is responsible for honouring it**. A build method
|
||||
must call `EditorApplication.Exit(1)` on failure, or Unity exits 0 and CI reports a green build
|
||||
that produced nothing.
|
||||
`make build` uses the entry point below, which is the form to prefer:
|
||||
|
||||
```bash
|
||||
"$UNITY_CLI" build "$UNITY_PROJECT" --no-banner --target StandaloneOSX \
|
||||
--execute-method NightclubArcadia.EditorTools.PlayerBuild.BuildMacOS \
|
||||
-o "$PWD/build/NightclubArcadia.app"
|
||||
```
|
||||
|
||||
`Assets/Editor/PlayerBuild.cs` reads the enabled scenes from the build settings, asserts
|
||||
`Bootstrap.unity` is scene 0 (the player opens scene 0 on launch), honours the `-buildOutput`
|
||||
the CLI forwards from `-o`, inspects the `BuildReport`, and calls `EditorApplication.Exit(1)` on
|
||||
anything short of `Succeeded`. Without that last part Unity exits 0 on a build that produced
|
||||
nothing and CI reports green. `BuildWindows` and `BuildLinux` are there too.
|
||||
|
||||
Verified: a full macOS build takes about two minutes and produces a ~172MB `.app`.
|
||||
|
||||
### 3.4 Run an arbitrary Editor method
|
||||
|
||||
@@ -174,6 +217,49 @@ NightclubArcadia/Assets/Dialogue/
|
||||
└── Objects/ Chair
|
||||
```
|
||||
|
||||
The writer-facing context sits at the repo root, outside `Assets/` so it gets no `.meta` files:
|
||||
|
||||
The scenes are split three ways, loaded additively from `Bootstrap`:
|
||||
|
||||
```
|
||||
Assets/Scenes/
|
||||
├── Bootstrap.unity entry point; GameBootstrap loads the rest
|
||||
├── Systems/Systems.unity dialogue, skills, UI, camera rig, and the PLAYER
|
||||
└── Levels/
|
||||
├── SC101_ConferenceHall.unity geometry, light, navmesh, reveal cameras
|
||||
└── SC101_ConferenceHall/ baked data for that scene (NavMesh asset)
|
||||
```
|
||||
|
||||
`Bootstrap` must stay index 0 in the build settings. The level is made the active scene after
|
||||
load, so new objects and lighting land there rather than in Bootstrap.
|
||||
|
||||
**Working in the Editor.** `Tools ▸ Nightclub Arcadia ▸ Open Game Scenes` opens all three at
|
||||
once, with the level active. Do that before pressing Play.
|
||||
|
||||
If you press Play with only `Bootstrap` open, `GameBootstrap` loads the other two *at runtime*,
|
||||
and Unity discards runtime-loaded scenes when Play ends — the Hierarchy comes back with Bootstrap
|
||||
alone and it looks as though the scenes were destroyed. **Nothing is written to disk**; it is the
|
||||
Hierarchy, not the files. With all three already open, `GameBootstrap` skips loading them
|
||||
(`LoadIfNeeded`) and they are still there afterwards. `GameSceneWorkflow` also captures and
|
||||
restores the scene setup around Play as a safety net; toggle it under the same menu.
|
||||
|
||||
```
|
||||
writing/
|
||||
├── README.md session entry point
|
||||
├── STYLE.md register, tone moves, ban list, branching rules ← read first
|
||||
├── YARN-PRIMER.md the one page of syntax a writer needs
|
||||
├── GLOSSARY.md in-world and project vocabulary
|
||||
├── voices/ the eleven skill voices, one sheet each (generated — see §4.7)
|
||||
├── characters/ named NPCs, dialogue-facing
|
||||
├── scenes/ per-scene briefs: intent, beats, checks, constraints
|
||||
└── lore/ candidates.md — the three identity readings and their hard rules
|
||||
```
|
||||
|
||||
Design material deeper than this lives in Obsidian, not the repo:
|
||||
`~/Obsidian-Vaults/obsidian-vault/Projects/Active/NightclubArcadia/`. **`Ground Truth.md` there
|
||||
is the solution document — never copy, quote, or summarise it into this repo**, including into
|
||||
commit messages. The game's premise is that the protagonist's identity never resolves.
|
||||
|
||||
**Dialogue is already plain text in the repo.** It is authored in `.yarn` files, not inside
|
||||
the Unity Editor, and any new `.yarn` file dropped anywhere under `Assets/Dialogue/` is picked
|
||||
up automatically by the `**/*.yarn` glob in the `.yarnproject`. Adding a scene or a character
|
||||
@@ -242,20 +328,52 @@ There is **no manual sync step** for dialogue. The chain is:
|
||||
The only things that need a human/Editor step are the *data* files, not the dialogue:
|
||||
|
||||
```
|
||||
skill_bible.json → Tools ▸ Nightclub Arcadia ▸ (SkillSystemSetup) → Skills/Definitions/*.asset + SkillDatabase.asset
|
||||
candidates.json → Tools ▸ Nightclub Arcadia ▸ (CandidateSystemSetup) → Candidates/Definitions/*.asset + CandidateDatabase.asset
|
||||
skill_bible.json → Tools ▸ Nightclub Arcadia ▸ Set Up Skill System → Skills/Definitions/*.asset + SkillDatabase.asset
|
||||
candidates.json → Tools ▸ Nightclub Arcadia ▸ Set Up Candidate System → Candidates/Definitions/*.asset + CandidateDatabase.asset
|
||||
characters.json → Tools ▸ Nightclub Arcadia ▸ Set Up Characters → Characters/Definitions/*.asset
|
||||
```
|
||||
|
||||
`characters.json` is where an NPC or a talkable object gets its display name, its Yarn node and
|
||||
its interaction range. Adding one is a JSON entry plus a prefab; it needs no code.
|
||||
|
||||
Those setup scripts also register a `[DidReloadScripts]` callback, so in practice the assets
|
||||
regenerate on script reload too. The JSON is the source of truth either way.
|
||||
|
||||
### 4.6 Code-owned vs writer-owned
|
||||
### 4.6 The voice-sheet pipeline
|
||||
|
||||
The Skill Bible prose used to live as a `\n`-escaped string inside `skill_bible.json`, which no
|
||||
writer could comfortably read or revise. It now lives in `writing/voices/*.md`, and truth flows
|
||||
in opposite directions for the two halves of each sheet:
|
||||
|
||||
```
|
||||
PROSE writing/voices/<id>.md -> skill_bible.json -> Skills/Definitions/*.asset
|
||||
MACHINE skill_bible.json -> the "Machine fields" table in the .md
|
||||
```
|
||||
|
||||
```bash
|
||||
python3 tools/writing/sync_voices.py --check # verify; exit 1 on drift
|
||||
python3 tools/writing/sync_voices.py --to-json # fold edited prose into the bible
|
||||
python3 tools/writing/sync_voices.py --to-md # refresh the machine table from the bible
|
||||
```
|
||||
|
||||
`tools/writing/voicelib.py` does the parsing and guarantees `notes -> dict -> notes` is identity
|
||||
for all eleven skills. `--to-json` on unchanged sheets is byte-identical, so it is safe to run
|
||||
at any time.
|
||||
|
||||
`VoiceSheetSyncTests` (EditMode) enforces the same invariant, so drift fails the build instead
|
||||
of silently shipping a voice that no longer matches the sheet the next scene is written against.
|
||||
It deliberately does not reimplement the markdown parser in C# — it asserts the shipped prose
|
||||
appears verbatim in the sheet, which catches drift in either direction with no second parser to
|
||||
keep in step.
|
||||
|
||||
### 4.7 Code-owned vs writer-owned
|
||||
|
||||
| Writer-owned (edit freely, no Unity) | Code-owned (needs an engineer) |
|
||||
|---|---|
|
||||
| `Assets/Dialogue/**/*.yarn` | `Assets/Scripts/**/*.cs` |
|
||||
| `<<declare>>` lines in `Common.yarn` | `Assets/Editor/**/*.cs` |
|
||||
| `Assets/Skills/skill_bible.json` (prose fields) | Yarn command/function *implementations* |
|
||||
| `writing/**` | `Assets/Scripts/**/*.cs` |
|
||||
| `Assets/Dialogue/**/*.yarn` | `Assets/Editor/**/*.cs` |
|
||||
| `<<declare>>` lines in `Common.yarn` | Yarn command/function *implementations* |
|
||||
| `writing/voices/*.md` (prose → the bible, §4.6) | `Assets/Skills/skill_bible.json` (machine fields) |
|
||||
| `Assets/Candidates/candidates.json` (`status`, `sceneId`, `notes`, `unlockFlag`) | `.asset`, `.prefab`, `.unity`, `.meta` |
|
||||
| `docs/` writing docs | `ProjectSettings/**` |
|
||||
|
||||
@@ -278,11 +396,24 @@ or a branch.** If a writing task requires either, that is a pipeline bug — fil
|
||||
`$self_lean_*` / `$found_*` in any `.yarn` file resolves to a real id in `CandidateDatabase`.
|
||||
It is a tripwire, not a proof.
|
||||
|
||||
### 5.2 One-click in-Editor run
|
||||
### 5.2 PlayMode suite
|
||||
|
||||
`Assets/Tests/PlayMode/BootstrapTests.cs`. Verifies the scene split at runtime — the thing no
|
||||
EditMode test can see, because none of the runtime resolution has happened yet.
|
||||
|
||||
### 5.3 Voice-sheet sync
|
||||
|
||||
```bash
|
||||
python3 tools/writing/sync_voices.py --check
|
||||
```
|
||||
|
||||
Seconds, no Unity. Run it after touching `writing/voices/*.md` or `skill_bible.json` (§4.6).
|
||||
|
||||
### 5.4 One-click in-Editor run
|
||||
|
||||
`Tools ▸ Nightclub Arcadia ▸ Run Skill EditMode Tests` (`Assets/Editor/SkillSystemTestRunner.cs`).
|
||||
|
||||
### 5.3 YarnCheck — validate dialogue without Unity ⭐
|
||||
### 5.5 YarnCheck — validate dialogue without Unity ⭐
|
||||
|
||||
`tools/YarnCheck` is a .NET 9 console app that compiles **and plays** the Yarn scripts using
|
||||
the exact Yarn Spinner DLLs shipped in `Packages/dev.yarnspinner.unity/Runtime/DLLs`, so it
|
||||
@@ -318,11 +449,26 @@ should not be — see `docs/restructure-plan.md`.
|
||||
|
||||
- Namespaces: `NightclubArcadia.<Area>` — `Skills`, `Dialogue`, `UI`, `UI.Dialogue`,
|
||||
`UI.HUD`, `UI.Menu`, `Cinematics`, `Interaction`, `Player`, `Player.Math`.
|
||||
**Exception:** `NPCStandIn.cs` sits in the global namespace. That is a scaffold tell, not a
|
||||
convention to copy — new runtime types always get a namespace.
|
||||
- Assembly definitions exist for `NightclubArcadia.Skills` and `NightclubArcadia.Locomotion.Math`
|
||||
only. Camera, Player, UI, Dialogue, NPCs and Interaction all currently compile into the
|
||||
default `Assembly-CSharp`. Widening asmdef coverage is planned, not done.
|
||||
There are no global-namespace runtime types left; the last one, `NPCStandIn`, went with the
|
||||
scaffold, and `InputDeviceTracker` moved into `NightclubArcadia.Core`.
|
||||
- **Assemblies.** No project code is in `Assembly-CSharp` any more:
|
||||
|
||||
| Assembly | Covers | Depends on |
|
||||
|---|---|---|
|
||||
| `NightclubArcadia.Core` | `Scripts/Core` | nothing |
|
||||
| `NightclubArcadia.Locomotion.Math` | `Scripts/Player/Math` | nothing |
|
||||
| `NightclubArcadia.Skills` | `Scripts/Skills` | Yarn, TMP, uGUI |
|
||||
| `NightclubArcadia.Game` | the rest of `Scripts` | Core, Skills, Math, StarterAssets, packages |
|
||||
| `StarterAssets` | vendored template code | Input System |
|
||||
|
||||
`Scripts/Interaction` holds the interaction layer: `InteractableDefinition` (the asset that
|
||||
says what a thing is called and which node it starts), `DialogueInteractor` (the component
|
||||
that places one in the world), plus `WorldSpaceLabel` and `InteractionPrompt`.
|
||||
|
||||
`Game` is one assembly rather than one per area because the areas are genuinely cyclic:
|
||||
UI ↔ Dialogue, UI ↔ Player and UI ↔ Camera, via `UILayerBootstrap`, `PlayerControlLock` and
|
||||
`CharacterPanelView`. Splitting further means moving those three, not just adding asmdefs.
|
||||
The `.asmdef` at `Scripts/` covers everything beneath it except folders with their own.
|
||||
- Comments in this codebase carry *decision history* — why a flag is written at the bottom of a
|
||||
node rather than the top, why four voices in SC-101 breaks the three-voice cap on purpose.
|
||||
Match that density. Do not strip such comments as "noise"; they are the design record.
|
||||
@@ -333,29 +479,66 @@ should not be — see `docs/restructure-plan.md`.
|
||||
|
||||
## 7. Traps
|
||||
|
||||
1. **`Assets/Scenes/DialogueTest.unity` is serialized as binary**, and Unity will not convert it
|
||||
from a headless run. The project is set to Force Text (`m_SerializationMode: 2`) and the API
|
||||
agrees — `EditorSettings.serializationMode` reads `ForceText` — but Force Text governs
|
||||
conversion **at the moment the setting changes**, not on every save. A file that entered the
|
||||
project as binary stays binary. Four approaches were tried and all failed silently:
|
||||
`AssetDatabase.ForceReserializeAssets` does not rewrite scene files; `OpenScene` +
|
||||
`MarkSceneDirty` + `SaveScene` to the same path returns `true` and writes nothing, because
|
||||
`MarkSceneDirty` does not take in batch mode; `SaveScene` to a *new* path writes a fresh file
|
||||
that is also binary; and re-assigning `serializationMode` (Mixed → ForceText) from script
|
||||
does not trigger a reserialize pass. **The fix is Editor-UI only:** Project Settings ▸ Editor
|
||||
▸ Asset Serialization, switch the mode and switch it back, which reserializes on apply.
|
||||
Until then the scene is not diffable or mergeable. It is committed and intact (14 roots).
|
||||
2. **`unity run` reserves `-batchmode`, `-nographics`, `-quit`, `-logFile`.** Passing any of them
|
||||
1. **A scene silently turns binary if it holds an object that prefers binary serialization.**
|
||||
This one cost real time. `DialogueTest.unity` was binary for weeks despite the project being
|
||||
set to Force Text, because the `NavMeshSurface` held its baked `NavMeshData` *embedded in the
|
||||
scene* rather than as an asset. One such object forces the whole file to binary, and no amount
|
||||
of re-saving or toggling the setting fixes it — Force Text only converts at the moment the
|
||||
setting changes. The fix is to extract the data to its own asset, which is what baking from
|
||||
the NavMeshSurface inspector produces anyway. If a scene goes binary again, bisect: move the
|
||||
roots one at a time into a fresh scene and see which one yields a binary file.
|
||||
|
||||
2. **Serialized references cannot cross a scene boundary.** Unity nulls them. The split cost
|
||||
exactly seven: both NPCs' `dialogueRunner`, `dialogueUI` and `player`, plus the reveal
|
||||
camera's tracking target. All are resolved at runtime now — `SceneServices` for the first,
|
||||
`CinemachineFollowsPlayer` for the last.
|
||||
|
||||
**Resolve at the point of use, never in `Awake`.** A level object can wake up before the
|
||||
scene holding its dependency exists — open the level on its own, or in the wrong order, and
|
||||
`Awake` runs with no Systems scene in sight. That produced
|
||||
`[SceneServices] Bartender: could not resolve dialogueRunner`, and because the result was
|
||||
cached once, it stayed broken for the whole session. `SceneServices.TryResolve` is the silent
|
||||
lookup for speculative calls; `SceneServices.Resolve` logs and belongs only where the
|
||||
dependency is genuinely needed. `NPCStandIn.ResolvedDialogueRunner` is the pattern to copy.
|
||||
`SceneOrderTests` holds the property, and asserts it is actually reproducing the race rather
|
||||
than passing for free.
|
||||
|
||||
3. **The player's NavMeshAgent outlives the NavMesh.** The player is in Systems, the NavMesh is
|
||||
baked into the level, so there is a window during load where the agent exists and is not on a
|
||||
mesh. `ResetPath`, `isStopped` and `SetDestination` all log errors in that state. Guard on
|
||||
`agent.isOnNavMesh`, not just a null check.
|
||||
|
||||
4. **An asmdef assembly cannot reference `Assembly-CSharp`.** Only the reverse. This is why
|
||||
giving the runtime code assemblies had to include `StarterAssets`, which had none and which
|
||||
four runtime files use — without that, everything referencing it would have stopped compiling.
|
||||
Keep it in mind before adding loose scripts outside an asmdef folder.
|
||||
|
||||
5. **The one-shot scene builders are gone.** `UILayerSetup`, `PlayerControlSetup`,
|
||||
`UILayerSetupAutoRun` and `YarnDemoSetup` built scenes from scratch and assumed the
|
||||
single-scene layout; after the split they produced duplicates, and one of them destroyed a
|
||||
level. The prefabs they used to generate are authored and committed now, so they were deleted
|
||||
rather than fixed. They are in git history if the wiring ever needs consulting.
|
||||
`Set Up Skill System`, `Set Up Candidate System` and `Set Up Characters` remain — they
|
||||
regenerate assets from JSON and touch no scene. **To run the game, open `Bootstrap.unity`.**
|
||||
|
||||
6. **`unity run` reserves `-batchmode`, `-nographics`, `-quit`, `-logFile`.** Passing any of them
|
||||
after `--` is a hard error, and its output does not reach stdout — read `Logs/Editor.log` (§3.4).
|
||||
3. **`-quit` with `-runTests`** hangs or truncates. Omit it (§3.2).
|
||||
4. **Exit code alone is not a test verdict.** Parse the results XML (§3.2).
|
||||
5. **`which unity` fails** in non-interactive shells even though the CLI is installed. Use the
|
||||
|
||||
7. **`-quit` with `-runTests`** hangs or truncates. Omit it (§3.2).
|
||||
|
||||
8. **Exit code alone is not a test verdict.** Parse the results XML (§3.2), which is what
|
||||
`make test` does.
|
||||
|
||||
9. **`which unity` fails** in non-interactive shells even though the CLI is installed. Use the
|
||||
absolute path `/Users/lennart/.unity/bin/unity` (§3.0).
|
||||
6. **Editor lock** — check before every headless run, filtering out `AssetImportWorker` children (§3.1).
|
||||
7. **Regenerated assets** — hand edits to `Skills/Definitions/*`, `Candidates/Definitions/*`
|
||||
and the two `*Database.asset` files are silently discarded (§2.1).
|
||||
8. **`top_skill` ties** resolve to the first argument. Reordering arguments changes the game.
|
||||
9. **No `.gitattributes`** — no Unity YAML merge driver, no LFS rule for `Assets/Art/`.
|
||||
Scene and prefab merges will conflict destructively under branching.
|
||||
10. **Template leftovers still present**: `Assets/Scenes/SampleScene.unity`, `Assets/Readme.asset`,
|
||||
`Assets/TutorialInfo/`. `SampleScene` is in the build scene list. Not load-bearing.
|
||||
|
||||
10. **Editor lock** — check before every headless run, filtering out `AssetImportWorker` children.
|
||||
`make test` and `make build` do this for you (§2b).
|
||||
|
||||
11. **Regenerated assets** — hand edits to `Skills/Definitions/*`, `Candidates/Definitions/*`
|
||||
and the two `*Database.asset` files are silently discarded (§2.1).
|
||||
|
||||
12. **`top_skill` ties** resolve to the first argument. Reordering arguments changes the game.
|
||||
|
||||
13. **`Bootstrap` must stay index 0** in the build settings, and all three scenes must be listed,
|
||||
or `LoadSceneAsync` by name fails at runtime with nothing but a console error.
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# Nightclub Arcadia — common commands.
|
||||
#
|
||||
# Everything here is documented in CLAUDE.md; this file exists so the exact
|
||||
# invocations live in one place instead of being retyped from memory.
|
||||
|
||||
UNITY_CLI ?= /Users/lennart/.unity/bin/unity
|
||||
UNITY ?= /Applications/Unity/Hub/Editor/6000.5.8f1/Unity.app/Contents/MacOS/Unity
|
||||
PROJECT ?= $(CURDIR)/NightclubArcadia
|
||||
RESULTS ?= $(CURDIR)/.test-results
|
||||
SMARTMERGE ?= /Applications/Unity/Hub/Editor/6000.5.8f1/Unity.app/Contents/Helpers/UnityYAMLMerge
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: help check yarn yarn-play voices voices-sync test test-play build lock clean-results merge-driver
|
||||
|
||||
help: ## Show this help
|
||||
@grep -hE '^[a-z-]+:.*?## ' $(MAKEFILE_LIST) \
|
||||
| awk 'BEGIN {FS = ":.*?## "} {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
|
||||
@echo ""
|
||||
@echo " Unity must be CLOSED for test/build — run 'make lock' to check."
|
||||
|
||||
check: yarn voices test test-play ## Everything a change should pass before commit
|
||||
|
||||
yarn: ## Compile every Yarn script (seconds, no Unity)
|
||||
@cd tools/YarnCheck && DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run -- ../../NightclubArcadia/Assets/Dialogue
|
||||
|
||||
yarn-play: ## Play a node: make yarn-play NODE=Bartender_Talk PICKS="2 2 0 0"
|
||||
@cd tools/YarnCheck && DOTNET_CLI_TELEMETRY_OPTOUT=1 \
|
||||
dotnet run -- ../../NightclubArcadia/Assets/Dialogue $(NODE) $(PICKS)
|
||||
|
||||
voices: ## Check writing/voices/*.md against skill_bible.json
|
||||
@python3 tools/writing/sync_voices.py --check
|
||||
|
||||
voices-sync: ## Fold edited voice prose into skill_bible.json
|
||||
@python3 tools/writing/sync_voices.py --to-json
|
||||
|
||||
test: lock ## Run the EditMode suite
|
||||
@mkdir -p $(RESULTS)
|
||||
@$(UNITY_CLI) test $(PROJECT) --no-banner --mode EditMode \
|
||||
--output $(RESULTS)/editmode.xml --timeout 900 || true
|
||||
@python3 tools/ci/report_tests.py $(RESULTS)/editmode.xml
|
||||
|
||||
test-play: lock ## Run the PlayMode suite (bootstrap + scene split)
|
||||
@mkdir -p $(RESULTS)
|
||||
@$(UNITY_CLI) test $(PROJECT) --no-banner --mode PlayMode \
|
||||
--output $(RESULTS)/playmode.xml --timeout 900 || true
|
||||
@python3 tools/ci/report_tests.py $(RESULTS)/playmode.xml
|
||||
|
||||
build: lock ## Build a macOS player into build/
|
||||
@$(UNITY_CLI) build $(PROJECT) --no-banner --target StandaloneOSX \
|
||||
--execute-method NightclubArcadia.EditorTools.PlayerBuild.BuildMacOS \
|
||||
-o $(CURDIR)/build/NightclubArcadia.app
|
||||
|
||||
lock: ## Fail if the Unity Editor has the project open
|
||||
# pgrep -x matches the process NAME only. The previous `pgrep -f` on the full
|
||||
# binary path matched this very shell, because the pattern appears in its own
|
||||
# command line — the check reported the Editor running when nothing was.
|
||||
# AssetImportWorkers share the name but only exist alongside an Editor, so
|
||||
# matching them is correct rather than a false positive.
|
||||
@if pgrep -x Unity > /dev/null 2>&1; then \
|
||||
echo "The Unity Editor is running — close it first (only one instance per project)."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
merge-driver: ## One-time: teach git to merge Unity YAML with UnityYAMLMerge
|
||||
@test -x "$(SMARTMERGE)" || { echo "UnityYAMLMerge not found at $(SMARTMERGE)"; exit 1; }
|
||||
@git config merge.unityyamlmerge.name "Unity SmartMerge"
|
||||
@git config merge.unityyamlmerge.driver "'$(SMARTMERGE)' merge -p --force --fallback none %O %B %A %A"
|
||||
@git config merge.unityyamlmerge.recursive binary
|
||||
@echo "configured: $$(git config merge.unityyamlmerge.name)"
|
||||
|
||||
clean-results: ## Remove local test results
|
||||
@rm -rf $(RESULTS)
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba062aa6c92b140379dbc06b43dd3b9b
|
||||
guid: fd96ed0121314a93aff9d3ef7845fd1d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2216657f3a0224501bcfa09add14f689
|
||||
guid: 642dac0a511114afa9f701fb8a59378c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,19 @@
|
||||
%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: 8f4df63859ea4e39910d900aa7a5510a, type: 3}
|
||||
m_Name: bartender
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.InteractableDefinition
|
||||
id: bartender
|
||||
displayName: Bartender
|
||||
yarnNode: Bartender_Talk
|
||||
interactionRange: 3
|
||||
showLabel: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ccb543c858f74a969cb025cb3e1f0ea
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
%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: 8f4df63859ea4e39910d900aa7a5510a, type: 3}
|
||||
m_Name: chair
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.InteractableDefinition
|
||||
id: chair
|
||||
displayName: Chair
|
||||
yarnNode: Chair_Interaction
|
||||
interactionRange: 3
|
||||
showLabel: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 403e142c457b0412a8c8604a2a9807ed
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"interactables": [
|
||||
{
|
||||
"id": "bartender",
|
||||
"displayName": "Bartender",
|
||||
"yarnNode": "Bartender_Talk",
|
||||
"interactionRange": 3.0,
|
||||
"showLabel": true
|
||||
},
|
||||
{
|
||||
"id": "chair",
|
||||
"displayName": "Chair",
|
||||
"yarnNode": "Chair_Interaction",
|
||||
"interactionRange": 3.0,
|
||||
"showLabel": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4673507aac641739818bc04a57a8930
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -23,11 +23,11 @@
|
||||
"x": 282,
|
||||
"y": 12
|
||||
},
|
||||
"Bradford Kane.yarn": {
|
||||
"BradfordKane.yarn": {
|
||||
"x": 1320,
|
||||
"y": 2287
|
||||
},
|
||||
"Chevalier Cassian Thal.yarn": {
|
||||
"ChevalierCassianThal.yarn": {
|
||||
"x": 1621,
|
||||
"y": 2260
|
||||
},
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
// SC-101 — The Card at the Desk. Opening candidate hooks.
|
||||
//
|
||||
// Scene files stay thin: set the stage, <<detour>> into hook nodes, return.
|
||||
// Brief, beats, checks and the reasoning behind every rule below:
|
||||
// writing/scenes/sc101-the-card-at-the-desk.md
|
||||
//
|
||||
// Evidence rule: each candidate gets exactly one of each evidence type —
|
||||
// object, testimony, document, intuition. Preserve that balance; do not
|
||||
// stack types so trust becomes an artifact of imbalance.
|
||||
// See Assets/Candidates/candidates.json.
|
||||
// Rules that bind while editing THIS file — all six are deliberate, none is a
|
||||
// leftover. The brief says why; this is the short form so you do not have to
|
||||
// leave the file to avoid breaking it.
|
||||
//
|
||||
// Beat order: hooks fire in sequence from SC101_Desk (STANDING ORDER →
|
||||
// HOUSE POUR → FACEWORK → CONFLUENCE). Each remains an independently authored
|
||||
// node. Never <<if>>-guard a hook on another hook having fired, on any
|
||||
// $self_lean_*, or on skill_rank(...).
|
||||
//
|
||||
// Passive pattern (clue-bearing):
|
||||
// one voice per hook, from the candidate's attached pair;
|
||||
// the line is that character's argument, never a report;
|
||||
// exactly one $self_lean_* write; set $found_<clue_id> alongside it.
|
||||
//
|
||||
// Four-voice exception: this opening uses four voice introductions (one per
|
||||
// pair) against the writing handbook's "cap introductions at three voices"
|
||||
// rule. Deliberate and for SC-101 only — do not "correct" it down to three,
|
||||
// and do not copy it as a new precedent elsewhere.
|
||||
//
|
||||
// Body stays neutral on purpose: no lean, no candidate attachment.
|
||||
// 1. Scene files stay thin: set the stage, <<detour>> into hook nodes, return.
|
||||
// 2. Evidence balance — one object / testimony / document / intuition per
|
||||
// candidate. Never stack types. See Assets/Candidates/candidates.json.
|
||||
// 3. Beat order is fixed: STANDING ORDER -> HOUSE POUR -> FACEWORK ->
|
||||
// CONFLUENCE. Never <<if>>-guard a hook on another hook having fired, on any
|
||||
// $self_lean_*, or on skill_rank(...).
|
||||
// 4. Passive pattern for a clue-bearing hook: one voice, from the candidate's
|
||||
// attached pair; the line is that voice's argument, never a report; exactly
|
||||
// one $self_lean_* write, with $found_<clue_id> set alongside it.
|
||||
// 5. Four voice introductions, against the handbook cap of three. Deliberate,
|
||||
// SC-101 only — one voice per pair. Do not correct it down, do not copy it.
|
||||
// 6. The body stays neutral: no lean, no candidate attachment outside the hooks.
|
||||
|
||||
title: Start
|
||||
position: -17,-276
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NightclubArcadia.Interaction;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Regenerates InteractableDefinition assets from Assets/Characters/characters.json.
|
||||
///
|
||||
/// The JSON is the source of truth and the .asset files are build output; hand edits
|
||||
/// to them are overwritten. Same contract as Skills and Candidates, deliberately —
|
||||
/// a writer adding a character edits one JSON file and never opens Unity.
|
||||
///
|
||||
/// This exists because the identity of an NPC used to live in public fields on a
|
||||
/// scene object, where nothing outside that scene could see it and two copies could
|
||||
/// disagree. They did: the scene's second "Bartender" was the chair.
|
||||
/// </summary>
|
||||
public static class CharacterSetup
|
||||
{
|
||||
const string JsonPath = "Assets/Characters/characters.json";
|
||||
const string DefinitionsFolder = "Assets/Characters/Definitions";
|
||||
|
||||
[Serializable]
|
||||
class Dto
|
||||
{
|
||||
public string id;
|
||||
public string displayName;
|
||||
public string yarnNode;
|
||||
public float interactionRange = 3f;
|
||||
public bool showLabel = true;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
class DtoList
|
||||
{
|
||||
public Dto[] interactables;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Nightclub Arcadia/Set Up Characters")]
|
||||
public static void SetUpCharacters() => Regenerate(verbose: true);
|
||||
|
||||
[DidReloadScripts]
|
||||
static void OnScriptsReloaded() => Regenerate(verbose: false);
|
||||
|
||||
static void Regenerate(bool verbose)
|
||||
{
|
||||
if (!File.Exists(JsonPath))
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
Debug.LogError($"[Characters] Missing {JsonPath}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DtoList parsed;
|
||||
try
|
||||
{
|
||||
parsed = JsonUtility.FromJson<DtoList>(File.ReadAllText(JsonPath));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[Characters] {JsonPath} is not valid JSON: {e.Message}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed?.interactables == null || parsed.interactables.Length == 0)
|
||||
{
|
||||
Debug.LogError($"[Characters] {JsonPath} defines no interactables.");
|
||||
return;
|
||||
}
|
||||
|
||||
var duplicates = parsed.interactables.GroupBy(i => i.id).Where(g => g.Count() > 1).ToList();
|
||||
if (duplicates.Count > 0)
|
||||
{
|
||||
Debug.LogError("[Characters] Duplicate ids: " +
|
||||
string.Join(", ", duplicates.Select(g => g.Key)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AssetDatabase.IsValidFolder(DefinitionsFolder))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets/Characters", "Definitions");
|
||||
}
|
||||
|
||||
var live = new HashSet<string>(StringComparer.Ordinal);
|
||||
var changed = new List<string>();
|
||||
|
||||
foreach (var dto in parsed.interactables)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dto.id))
|
||||
{
|
||||
Debug.LogError("[Characters] An entry has no id; skipped.");
|
||||
continue;
|
||||
}
|
||||
live.Add(dto.id);
|
||||
|
||||
var path = $"{DefinitionsFolder}/{dto.id}.asset";
|
||||
var asset = AssetDatabase.LoadAssetAtPath<InteractableDefinition>(path);
|
||||
if (asset == null)
|
||||
{
|
||||
asset = ScriptableObject.CreateInstance<InteractableDefinition>();
|
||||
AssetDatabase.CreateAsset(asset, path);
|
||||
changed.Add(dto.id);
|
||||
}
|
||||
else if (asset.DisplayName != dto.displayName || asset.YarnNode != dto.yarnNode ||
|
||||
!Mathf.Approximately(asset.InteractionRange, dto.interactionRange) ||
|
||||
asset.ShowLabel != dto.showLabel)
|
||||
{
|
||||
changed.Add(dto.id);
|
||||
}
|
||||
|
||||
asset.EditorSet(dto.id, dto.displayName, dto.yarnNode, dto.interactionRange, dto.showLabel);
|
||||
EditorUtility.SetDirty(asset);
|
||||
}
|
||||
|
||||
// An id removed from the JSON should not leave an orphan asset behind that a
|
||||
// prefab could still be pointing at.
|
||||
foreach (var guid in AssetDatabase.FindAssets("t:InteractableDefinition", new[] { DefinitionsFolder }))
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var name = Path.GetFileNameWithoutExtension(path);
|
||||
if (!live.Contains(name))
|
||||
{
|
||||
Debug.LogWarning($"[Characters] Removing orphan definition '{name}' — no longer in the JSON.");
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
if (verbose || changed.Count > 0)
|
||||
{
|
||||
Debug.Log($"[Characters] {parsed.interactables.Length} definition(s) in {DefinitionsFolder}" +
|
||||
(changed.Count > 0 ? $"; updated: {string.Join(", ", changed)}" : "; no changes"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c0e3c886ff143d3b26b7f55d7f22410
|
||||
guid: 9cbb2b742dcc4031a4e0cfc0c0544faf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,129 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Makes the split-scene layout usable in the Editor.
|
||||
///
|
||||
/// The game runs from Bootstrap, which loads Systems and a level additively AT
|
||||
/// RUNTIME. Unity discards runtime-loaded scenes when Play ends and restores
|
||||
/// whatever the Editor had open, which for someone who pressed Play in Bootstrap is
|
||||
/// Bootstrap alone. The Hierarchy comes back nearly empty and it looks as though the
|
||||
/// scenes were destroyed. They are not — nothing is written to disk — but it is an
|
||||
/// unpleasant way to work.
|
||||
///
|
||||
/// Two fixes, both opt-outable:
|
||||
/// - Open Game Scenes puts all three in the Hierarchy for authoring.
|
||||
/// - The Editor's scene setup is captured before Play and restored after, so what
|
||||
/// you had open is what you get back.
|
||||
///
|
||||
/// GameBootstrap skips any scene that is already loaded, so having all three open
|
||||
/// and pressing Play does the right thing rather than loading anything twice.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public static class GameSceneWorkflow
|
||||
{
|
||||
const string RestorePrefKey = "NightclubArcadia.RestoreSceneSetup";
|
||||
const string RestoreMenu = "Tools/Nightclub Arcadia/Restore Scene Setup After Play";
|
||||
|
||||
static SceneSetup[] setupBeforePlay;
|
||||
|
||||
static GameSceneWorkflow()
|
||||
{
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Nightclub Arcadia/Open Game Scenes")]
|
||||
public static void OpenGameScenes()
|
||||
{
|
||||
// The prompt cannot be shown in batch mode, where it returns false and would
|
||||
// make this menu a silent no-op.
|
||||
if (!Application.isBatchMode && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var path in new[] { ScenePaths.Bootstrap, ScenePaths.Systems, ScenePaths.WorkingLevel })
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Debug.LogError($"[Scenes] Missing: {path}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EditorSceneManager.OpenScene(ScenePaths.Bootstrap, OpenSceneMode.Single);
|
||||
EditorSceneManager.OpenScene(ScenePaths.Systems, OpenSceneMode.Additive);
|
||||
var level = EditorSceneManager.OpenScene(ScenePaths.WorkingLevel, OpenSceneMode.Additive);
|
||||
|
||||
// The level owns the lighting and is where new objects should land.
|
||||
EditorSceneManager.SetActiveScene(level);
|
||||
Debug.Log("[Scenes] Bootstrap + Systems + SC101_ConferenceHall open. Level is active.");
|
||||
}
|
||||
|
||||
[MenuItem(RestoreMenu)]
|
||||
static void ToggleRestore()
|
||||
{
|
||||
var on = !EditorPrefs.GetBool(RestorePrefKey, true);
|
||||
EditorPrefs.SetBool(RestorePrefKey, on);
|
||||
Debug.Log($"[Scenes] Restore scene setup after Play: {(on ? "on" : "off")}");
|
||||
}
|
||||
|
||||
[MenuItem(RestoreMenu, true)]
|
||||
static bool ToggleRestoreValidate()
|
||||
{
|
||||
Menu.SetChecked(RestoreMenu, EditorPrefs.GetBool(RestorePrefKey, true));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (!EditorPrefs.GetBool(RestorePrefKey, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
setupBeforePlay = EditorSceneManager.GetSceneManagerSetup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state != PlayModeStateChange.EnteredEditMode || setupBeforePlay == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var setup = setupBeforePlay;
|
||||
setupBeforePlay = null;
|
||||
|
||||
// A scene deleted or renamed while Play was running would throw here, and
|
||||
// an exception in this callback leaves the Editor in a confusing state.
|
||||
var usable = setup.Where(s => File.Exists(s.path)).ToArray();
|
||||
if (usable.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var current = EditorSceneManager.GetSceneManagerSetup();
|
||||
if (current.Length == usable.Length &&
|
||||
current.Select(s => s.path).SequenceEqual(usable.Select(s => s.path)))
|
||||
{
|
||||
return; // already what we wanted; do not disturb it
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
EditorSceneManager.RestoreSceneManagerSetup(usable);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[Scenes] Could not restore the pre-Play scene setup: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bdf044f1ab04312b76895dac1740b37
|
||||
guid: 0e05a1f05ef74ff7a53f6e24ab37e51e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Headless player builds.
|
||||
///
|
||||
/// Not called "BuildPipeline" on purpose — that name collides with
|
||||
/// UnityEditor.BuildPipeline, which this has to call.
|
||||
///
|
||||
/// The reason to have this at all rather than let the CLI drive Unity's built-in
|
||||
/// build: a flag-only build reports success even when it produced nothing useful,
|
||||
/// because Unity exits 0 unless the process itself failed. CI then goes green on a
|
||||
/// build that does not exist. Every entry point here inspects the BuildReport and
|
||||
/// calls EditorApplication.Exit(1) on anything short of success.
|
||||
///
|
||||
/// unity build NightclubArcadia --target StandaloneOSX \
|
||||
/// --execute-method NightclubArcadia.EditorTools.PlayerBuild.BuildMacOS \
|
||||
/// -o build/NightclubArcadia.app
|
||||
///
|
||||
/// The CLI forwards -o as -buildOutput, and honouring it is this method's job.
|
||||
/// </summary>
|
||||
public static class PlayerBuild
|
||||
{
|
||||
public static void BuildMacOS() => Build(BuildTarget.StandaloneOSX, "build/NightclubArcadia.app");
|
||||
|
||||
public static void BuildWindows() => Build(BuildTarget.StandaloneWindows64, "build/NightclubArcadia.exe");
|
||||
|
||||
public static void BuildLinux() => Build(BuildTarget.StandaloneLinux64, "build/NightclubArcadia");
|
||||
|
||||
static void Build(BuildTarget target, string defaultOutput)
|
||||
{
|
||||
var output = ArgValue("-buildOutput") ?? defaultOutput;
|
||||
|
||||
var scenes = EditorBuildSettings.scenes
|
||||
.Where(s => s.enabled)
|
||||
.Select(s => s.path)
|
||||
.ToArray();
|
||||
|
||||
if (scenes.Length == 0)
|
||||
{
|
||||
Fail("No enabled scenes in the build settings — the player would have nothing to load.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Bootstrap loads the others by name at runtime, so it has to be index 0.
|
||||
if (!scenes[0].EndsWith("/Bootstrap.unity", StringComparison.Ordinal))
|
||||
{
|
||||
Fail($"Scene 0 is '{scenes[0]}', expected Assets/Scenes/Bootstrap.unity. " +
|
||||
"The player opens scene 0 on launch.");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[PlayerBuild] {target} -> {output}");
|
||||
foreach (var scene in scenes)
|
||||
{
|
||||
Debug.Log($"[PlayerBuild] scene: {scene}");
|
||||
}
|
||||
|
||||
var options = new BuildPlayerOptions
|
||||
{
|
||||
scenes = scenes,
|
||||
locationPathName = output,
|
||||
target = target,
|
||||
options = BuildOptions.None,
|
||||
};
|
||||
|
||||
BuildReport report;
|
||||
try
|
||||
{
|
||||
report = UnityEditor.BuildPipeline.BuildPlayer(options);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Fail($"BuildPlayer threw: {e}");
|
||||
return;
|
||||
}
|
||||
|
||||
var summary = report.summary;
|
||||
Debug.Log($"[PlayerBuild] {summary.result} — {summary.totalSize} bytes in {summary.totalTime}, " +
|
||||
$"{summary.totalErrors} error(s), {summary.totalWarnings} warning(s)");
|
||||
|
||||
if (summary.result != BuildResult.Succeeded)
|
||||
{
|
||||
foreach (var step in report.steps)
|
||||
{
|
||||
foreach (var msg in step.messages.Where(m => m.type == LogType.Error || m.type == LogType.Exception))
|
||||
{
|
||||
Debug.LogError($"[PlayerBuild] {step.name}: {msg.content}");
|
||||
}
|
||||
}
|
||||
Fail($"Build did not succeed: {summary.result}");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("[PlayerBuild] ok");
|
||||
}
|
||||
|
||||
static void Fail(string message)
|
||||
{
|
||||
Debug.LogError($"[PlayerBuild] {message}");
|
||||
EditorApplication.Exit(1);
|
||||
}
|
||||
|
||||
/// <summary>Reads "-name value" out of the command line Unity was launched with.</summary>
|
||||
static string ArgValue(string name)
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
for (var i = 0; i < args.Length - 1; i++)
|
||||
{
|
||||
if (string.Equals(args[i], name, StringComparison.Ordinal))
|
||||
{
|
||||
return args[i + 1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ec643a873224cc89e1f94dfb735037d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,316 +0,0 @@
|
||||
using NightclubArcadia.Cinematics;
|
||||
using NightclubArcadia.Interaction;
|
||||
using NightclubArcadia.Player;
|
||||
using StarterAssets;
|
||||
using Unity.AI.Navigation;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Wires player control, navigation, and camera systems into DialogueTest.unity.
|
||||
/// Run via Tools → Nightclub Arcadia → Set Up Player Control & Camera.
|
||||
/// </summary>
|
||||
public static class PlayerControlSetup
|
||||
{
|
||||
const string ScenePath = "Assets/Scenes/DialogueTest.unity";
|
||||
const string PlayerPrefabPath = "Assets/StarterAssets/ThirdPersonController/Prefabs/PlayerArmature.prefab";
|
||||
const string SettingsFolder = "Assets/Settings";
|
||||
|
||||
[MenuItem("Tools/Nightclub Arcadia/Set Up Player Control & Camera")]
|
||||
public static void SetUp()
|
||||
{
|
||||
EnsurePlayerPrefab();
|
||||
WireScene();
|
||||
AssetDatabase.SaveAssets();
|
||||
Debug.Log("[PlayerControlSetup] Player control and camera setup complete.");
|
||||
}
|
||||
|
||||
static void EnsurePlayerPrefab()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||||
if (prefab == null)
|
||||
{
|
||||
Debug.LogError($"[PlayerControlSetup] Missing prefab at {PlayerPrefabPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var root = PrefabUtility.LoadPrefabContents(PlayerPrefabPath);
|
||||
|
||||
EnsureComponent<PlayerPointerInput>(root);
|
||||
EnsureComponent<PlayerMotionArbiter>(root);
|
||||
EnsureComponent<ClickToMoveController>(root);
|
||||
EnsureComponent<PointerNavigationInput>(root);
|
||||
EnsureComponent<NavMeshAgent>(root);
|
||||
|
||||
var inputs = root.GetComponent<StarterAssetsInputs>();
|
||||
if (inputs != null)
|
||||
{
|
||||
inputs.analogMovement = true;
|
||||
inputs.cursorLocked = false;
|
||||
}
|
||||
|
||||
var controller = root.GetComponent<ThirdPersonController>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.LockCameraPosition = true;
|
||||
}
|
||||
|
||||
var clickToMove = root.GetComponent<ClickToMoveController>();
|
||||
var pointerNav = root.GetComponent<PointerNavigationInput>();
|
||||
var pointerInput = root.GetComponent<PlayerPointerInput>();
|
||||
var arbiter = root.GetComponent<PlayerMotionArbiter>();
|
||||
|
||||
WireSerializedReference(clickToMove, "brainCamera", null);
|
||||
WireSerializedReference(pointerNav, "pointerInput", pointerInput);
|
||||
WireSerializedReference(pointerNav, "clickToMove", clickToMove);
|
||||
WireSerializedReference(pointerNav, "motionArbiter", arbiter);
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(root, PlayerPrefabPath);
|
||||
PrefabUtility.UnloadPrefabContents(root);
|
||||
}
|
||||
|
||||
static void WireScene()
|
||||
{
|
||||
var scene = EditorSceneManager.OpenScene(ScenePath, OpenSceneMode.Single);
|
||||
var player = GameObject.FindGameObjectWithTag("Player");
|
||||
if (player == null)
|
||||
{
|
||||
Debug.LogError("[PlayerControlSetup] No Player-tagged object found in scene.");
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureComponent<PlayerPointerInput>(player);
|
||||
EnsureComponent<PlayerMotionArbiter>(player);
|
||||
EnsureComponent<ClickToMoveController>(player);
|
||||
EnsureComponent<PointerNavigationInput>(player);
|
||||
EnsureComponent<NavMeshAgent>(player);
|
||||
|
||||
var inputs = player.GetComponent<StarterAssetsInputs>();
|
||||
if (inputs != null)
|
||||
{
|
||||
inputs.analogMovement = true;
|
||||
inputs.cursorLocked = false;
|
||||
}
|
||||
|
||||
var controller = player.GetComponent<ThirdPersonController>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.LockCameraPosition = true;
|
||||
}
|
||||
|
||||
var brainCamera = Camera.main;
|
||||
var pointerInput = player.GetComponent<PlayerPointerInput>();
|
||||
var clickToMove = player.GetComponent<ClickToMoveController>();
|
||||
var pointerNav = player.GetComponent<PointerNavigationInput>();
|
||||
var arbiter = player.GetComponent<PlayerMotionArbiter>();
|
||||
|
||||
WireSerializedReference(clickToMove, "brainCamera", brainCamera);
|
||||
WireSerializedReference(pointerNav, "brainCamera", brainCamera);
|
||||
WireSerializedReference(pointerNav, "pointerInput", pointerInput);
|
||||
WireSerializedReference(pointerNav, "clickToMove", clickToMove);
|
||||
WireSerializedReference(pointerNav, "motionArbiter", arbiter);
|
||||
|
||||
var groundLayer = LayerMask.NameToLayer("Ground");
|
||||
var interactableLayer = LayerMask.NameToLayer("Interactable");
|
||||
SetLayerIfExists("Floor", groundLayer);
|
||||
SetLayerIfExists("Room_101", groundLayer);
|
||||
SetLayerIfExists("Wall_Back", groundLayer);
|
||||
SetLayerIfExists("Wall_Front", groundLayer);
|
||||
SetLayerIfExists("Table", groundLayer);
|
||||
|
||||
WireBartender("Bartender", interactableLayer);
|
||||
WireBartender("Bartender (1)", interactableLayer);
|
||||
|
||||
EnsureNavigation(player.transform.position);
|
||||
EnsureCameraAnchor(player.transform, brainCamera);
|
||||
|
||||
EditorSceneManager.MarkSceneDirty(scene);
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
}
|
||||
|
||||
static void WireBartender(string objectName, int interactableLayer)
|
||||
{
|
||||
var bartender = GameObject.Find(objectName);
|
||||
if (bartender == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (interactableLayer >= 0)
|
||||
{
|
||||
bartender.layer = interactableLayer;
|
||||
}
|
||||
|
||||
EnsureComponent<ClickInteractableBridge>(bartender);
|
||||
EnsureComponent<CameraPointOfInterest>(bartender);
|
||||
}
|
||||
|
||||
static void EnsureNavigation(Vector3 sampleOrigin)
|
||||
{
|
||||
var navigation = GameObject.Find("Navigation");
|
||||
if (navigation == null)
|
||||
{
|
||||
navigation = new GameObject("Navigation");
|
||||
}
|
||||
|
||||
var surface = EnsureComponent<NavMeshSurface>(navigation);
|
||||
surface.agentTypeID = 0;
|
||||
surface.collectObjects = CollectObjects.All;
|
||||
surface.useGeometry = NavMeshCollectGeometry.RenderMeshes;
|
||||
|
||||
var included = 0;
|
||||
var defaultLayer = LayerMask.NameToLayer("Default");
|
||||
var groundLayer = LayerMask.NameToLayer("Ground");
|
||||
if (defaultLayer >= 0)
|
||||
{
|
||||
included |= 1 << defaultLayer;
|
||||
}
|
||||
|
||||
if (groundLayer >= 0)
|
||||
{
|
||||
included |= 1 << groundLayer;
|
||||
}
|
||||
|
||||
surface.layerMask = included;
|
||||
|
||||
var table = GameObject.Find("Table");
|
||||
if (table != null)
|
||||
{
|
||||
var modifier = EnsureComponent<NavMeshModifier>(table);
|
||||
modifier.overrideArea = true;
|
||||
modifier.area = NavMesh.GetAreaFromName("Not Walkable");
|
||||
}
|
||||
|
||||
surface.BuildNavMesh();
|
||||
|
||||
if (!NavMesh.SamplePosition(sampleOrigin, out _, 2f, NavMesh.AllAreas))
|
||||
{
|
||||
Debug.LogWarning("[PlayerControlSetup] NavMesh bake did not cover the player start position.");
|
||||
}
|
||||
}
|
||||
|
||||
static void EnsureCameraAnchor(Transform followTarget, Camera brainCamera)
|
||||
{
|
||||
var vcamObject = GameObject.Find("CinemachineCamera");
|
||||
if (vcamObject == null)
|
||||
{
|
||||
Debug.LogError("[PlayerControlSetup] CinemachineCamera not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var vcam = vcamObject.GetComponent<CinemachineCamera>();
|
||||
var composer = vcamObject.GetComponent<CinemachinePositionComposer>();
|
||||
|
||||
var anchorObject = GameObject.Find("CameraAnchor");
|
||||
if (anchorObject == null)
|
||||
{
|
||||
anchorObject = new GameObject("CameraAnchor");
|
||||
}
|
||||
|
||||
anchorObject.transform.position = followTarget.position;
|
||||
|
||||
var anchor = EnsureComponent<CameraRigAnchor>(anchorObject);
|
||||
EnsureComponent<CameraPanInput>(anchorObject);
|
||||
EnsureComponent<CameraPointOfInterestDirector>(anchorObject);
|
||||
EnsureComponent<CameraStateDirector>(anchorObject);
|
||||
|
||||
WireSerializedReference(anchor, "followTarget", followTarget);
|
||||
WireSerializedReference(anchor, "composer", composer);
|
||||
|
||||
if (vcam != null)
|
||||
{
|
||||
vcam.Target.TrackingTarget = anchorObject.transform;
|
||||
vcam.Priority.Value = 10;
|
||||
}
|
||||
|
||||
var pan = anchorObject.GetComponent<CameraPanInput>();
|
||||
WireSerializedReference(pan, "brainCamera", brainCamera);
|
||||
WireSerializedReference(pan, "anchor", anchor);
|
||||
WireSerializedReference(pan, "stateDirector", anchorObject.GetComponent<CameraStateDirector>());
|
||||
|
||||
var poiDirector = anchorObject.GetComponent<CameraPointOfInterestDirector>();
|
||||
WireSerializedReference(poiDirector, "anchor", anchor);
|
||||
WireSerializedReference(poiDirector, "stateDirector", anchorObject.GetComponent<CameraStateDirector>());
|
||||
|
||||
var stateDirector = anchorObject.GetComponent<CameraStateDirector>();
|
||||
WireSerializedReference(stateDirector, "anchor", anchor);
|
||||
|
||||
EnsureRevealCamera(vcamObject, followTarget);
|
||||
}
|
||||
|
||||
static void EnsureRevealCamera(GameObject followVcam, Transform followTarget)
|
||||
{
|
||||
var revealName = "CM_Reveal_Room101";
|
||||
var revealObject = GameObject.Find(revealName);
|
||||
if (revealObject == null)
|
||||
{
|
||||
revealObject = new GameObject(revealName);
|
||||
revealObject.transform.SetPositionAndRotation(
|
||||
followVcam.transform.position + new Vector3(-4f, 2f, -2f),
|
||||
followVcam.transform.rotation);
|
||||
}
|
||||
|
||||
var revealCam = EnsureComponent<CinemachineCamera>(revealObject);
|
||||
revealCam.Target.TrackingTarget = followTarget;
|
||||
revealCam.Priority.Value = 0;
|
||||
revealCam.Lens.FieldOfView = followVcam.GetComponent<CinemachineCamera>().Lens.FieldOfView;
|
||||
|
||||
var volumeObject = GameObject.Find("RevealVolume_Room101");
|
||||
if (volumeObject == null)
|
||||
{
|
||||
volumeObject = new GameObject("RevealVolume_Room101");
|
||||
volumeObject.transform.position = followTarget.position + new Vector3(0f, 1f, 2f);
|
||||
}
|
||||
|
||||
var box = EnsureComponent<BoxCollider>(volumeObject);
|
||||
box.isTrigger = true;
|
||||
box.size = new Vector3(6f, 3f, 4f);
|
||||
|
||||
var volume = EnsureComponent<CameraFramingVolume>(volumeObject);
|
||||
WireSerializedReference(volume, "revealCamera", revealCam);
|
||||
}
|
||||
|
||||
static T EnsureComponent<T>(GameObject target) where T : Component
|
||||
{
|
||||
var component = target.GetComponent<T>();
|
||||
if (component == null)
|
||||
{
|
||||
component = target.AddComponent<T>();
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
static void SetLayerIfExists(string objectName, int layer)
|
||||
{
|
||||
if (layer < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = GameObject.Find(objectName);
|
||||
if (obj != null)
|
||||
{
|
||||
obj.layer = layer;
|
||||
}
|
||||
}
|
||||
|
||||
static void WireSerializedReference(Object target, string propertyName, Object value)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var so = new SerializedObject(target);
|
||||
var property = so.FindProperty(propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
property.objectReferenceValue = value;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eedfabcda58c94099b2ad3e19f141b09
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace NightclubArcadia.EditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// The scene paths the one-shot setup menus operate on.
|
||||
///
|
||||
/// These used to be a literal "Assets/Scenes/DialogueTest.unity" repeated in four
|
||||
/// Editor scripts, which is why renaming the scene meant finding all four. One
|
||||
/// place now.
|
||||
/// </summary>
|
||||
public static class ScenePaths
|
||||
{
|
||||
/// <summary>Entry point. Loads Systems, then a level.</summary>
|
||||
public const string Bootstrap = "Assets/Scenes/Bootstrap.unity";
|
||||
|
||||
/// <summary>Persistent systems: dialogue, skills, UI, camera rig, player.</summary>
|
||||
public const string Systems = "Assets/Scenes/Systems/Systems.unity";
|
||||
|
||||
/// <summary>The level scene. SC-101's conference hall.</summary>
|
||||
public const string WorkingLevel = "Assets/Scenes/Levels/SC101_ConferenceHall.unity";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a3f10ec1f9042358ed09c1cdcc345d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -23,7 +23,7 @@ public static class SkillSystemSetup
|
||||
const string SkillsFolder = "Assets/Skills";
|
||||
const string BiblePath = "Assets/Skills/skill_bible.json";
|
||||
const string DatabasePath = "Assets/Skills/SkillDatabase.asset";
|
||||
const string ScenePath = "Assets/Scenes/DialogueTest.unity";
|
||||
const string ScenePath = NightclubArcadia.EditorTools.ScenePaths.Systems;
|
||||
const string AutoSetupSessionKey = "NightclubArcadia.SkillSystem.AutoSetupDone";
|
||||
|
||||
[DidReloadScripts]
|
||||
@@ -55,7 +55,7 @@ public static class SkillSystemSetup
|
||||
/// <summary>
|
||||
/// Creates/updates ScriptableObject assets without opening a scene.
|
||||
/// Safe to run on domain reload. Scene wiring stays on the menu item /
|
||||
/// the checked-in DialogueTest.unity Skill System objects.
|
||||
/// the checked-in Systems.unity Skill System objects.
|
||||
/// </summary>
|
||||
static void EnsureSkillAssetsOnly()
|
||||
{
|
||||
@@ -122,9 +122,12 @@ public static class SkillSystemSetup
|
||||
EditorUtility.SetDirty(database);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
WireDialogueTestScene(database);
|
||||
// Scene wiring deliberately skipped: the Skill System objects live in
|
||||
// Systems.unity and are already wired there. Regenerating the assets is
|
||||
// still useful and touches no scene. See LegacySceneSetup.
|
||||
AssetDatabase.SaveAssets();
|
||||
Debug.Log($"Skill system setup complete. Database at {DatabasePath}; scene wired at {ScenePath}.");
|
||||
Debug.Log($"Skill assets regenerated. Database at {DatabasePath}. Scene wiring skipped — "
|
||||
+ "the Skill System already exists in Systems.unity.");
|
||||
}
|
||||
|
||||
static bool TryLoadRoster(out SkillBibleEntry[] roster)
|
||||
@@ -230,7 +233,7 @@ public static class SkillSystemSetup
|
||||
}
|
||||
}
|
||||
|
||||
static void WireDialogueTestScene(SkillDatabase database)
|
||||
static void WireWorkingLevelScene(SkillDatabase database)
|
||||
{
|
||||
if (!File.Exists(ScenePath))
|
||||
{
|
||||
@@ -243,7 +246,7 @@ public static class SkillSystemSetup
|
||||
var runner = UnityEngine.Object.FindAnyObjectByType<DialogueRunner>();
|
||||
if (runner == null)
|
||||
{
|
||||
Debug.LogError("No DialogueRunner in DialogueTest.unity.");
|
||||
Debug.LogError("No DialogueRunner in Systems.unity.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,818 +0,0 @@
|
||||
using System.IO;
|
||||
using NightclubArcadia.Cinematics;
|
||||
using NightclubArcadia.Dialogue;
|
||||
using NightclubArcadia.Skills;
|
||||
using NightclubArcadia.UI;
|
||||
using NightclubArcadia.UI.Dialogue;
|
||||
using NightclubArcadia.UI.HUD;
|
||||
using NightclubArcadia.UI.Menu;
|
||||
using StarterAssets;
|
||||
using TMPro;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Yarn.Unity;
|
||||
|
||||
/// <summary>
|
||||
/// Builds UI prefabs and wires them into DialogueTest.unity.
|
||||
/// Run via Tools → Nightclub Arcadia → Set Up UI Layer.
|
||||
/// </summary>
|
||||
public static class UILayerSetup
|
||||
{
|
||||
const string ScenePath = "Assets/Scenes/DialogueTest.unity";
|
||||
const string PrefabFolder = "Assets/Prefabs/UI";
|
||||
const string ArtFolder = "Assets/Art/UI/Placeholder";
|
||||
|
||||
// Nested Resources folder: UILayerBootstrap builds the HUD at runtime and
|
||||
// can only reach the sprite through Resources.Load. Keeping it under
|
||||
// Art/UI/Placeholder preserves the organisation while making it
|
||||
// build-safe — an AssetDatabase-only path is null outside the editor.
|
||||
const string PortraitFolder = ArtFolder + "/Resources";
|
||||
const string PortraitPath = PortraitFolder + "/portrait_placeholder.png";
|
||||
const string MessageRowPrefabPath = PrefabFolder + "/DialogueMessageRow.prefab";
|
||||
const string StreamCanvasPrefabPath = PrefabFolder + "/DialogueStreamCanvas.prefab";
|
||||
const string HudCanvasPrefabPath = PrefabFolder + "/HudCanvas.prefab";
|
||||
const string SkillRowPrefabPath = PrefabFolder + "/SkillRow.prefab";
|
||||
const string MenuCanvasPrefabPath = PrefabFolder + "/PlayerMenuCanvas.prefab";
|
||||
|
||||
[MenuItem("Tools/Nightclub Arcadia/Set Up UI Layer")]
|
||||
public static void SetUp()
|
||||
{
|
||||
EnsureFolders();
|
||||
CreatePortraitPlaceholder();
|
||||
|
||||
var messageRow = CreateMessageRowPrefab();
|
||||
var skillRow = CreateSkillRowPrefab();
|
||||
var streamCanvas = CreateDialogueStreamCanvasPrefab(messageRow);
|
||||
var hudCanvas = CreateHudCanvasPrefab();
|
||||
var menuCanvas = CreatePlayerMenuCanvasPrefab(skillRow);
|
||||
|
||||
WireScene(streamCanvas, hudCanvas, menuCanvas);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
Debug.Log("[UILayerSetup] UI layer setup complete.");
|
||||
}
|
||||
|
||||
static void EnsureFolders()
|
||||
{
|
||||
EnsureFolder("Assets/Prefabs");
|
||||
EnsureFolder(PrefabFolder);
|
||||
EnsureFolder("Assets/Art");
|
||||
EnsureFolder("Assets/Art/UI");
|
||||
EnsureFolder(ArtFolder);
|
||||
EnsureFolder(PortraitFolder);
|
||||
}
|
||||
|
||||
static void EnsureFolder(string path)
|
||||
{
|
||||
if (AssetDatabase.IsValidFolder(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = Path.GetDirectoryName(path)?.Replace('\\', '/');
|
||||
var name = Path.GetFileName(path);
|
||||
if (!string.IsNullOrEmpty(parent) && !string.IsNullOrEmpty(name))
|
||||
{
|
||||
AssetDatabase.CreateFolder(parent, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void CreatePortraitPlaceholder()
|
||||
{
|
||||
if (File.Exists(PortraitPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tex = new Texture2D(512, 512, TextureFormat.RGBA32, false);
|
||||
var dark = new Color(0.12f, 0.12f, 0.14f, 1f);
|
||||
var mid = new Color(0.35f, 0.35f, 0.4f, 1f);
|
||||
for (var y = 0; y < 512; y++)
|
||||
{
|
||||
for (var x = 0; x < 512; x++)
|
||||
{
|
||||
var dx = (x - 256) / 256f;
|
||||
var dy = (y - 280) / 256f;
|
||||
var inHead = dx * dx + dy * dy < 0.12f;
|
||||
var inBody = Mathf.Abs(dx) < 0.22f && y < 220 && y > 40;
|
||||
tex.SetPixel(x, y, inHead || inBody ? mid : dark);
|
||||
}
|
||||
}
|
||||
|
||||
tex.Apply();
|
||||
File.WriteAllBytes(PortraitPath, tex.EncodeToPNG());
|
||||
Object.DestroyImmediate(tex);
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
var importer = AssetImporter.GetAtPath(PortraitPath) as TextureImporter;
|
||||
if (importer != null)
|
||||
{
|
||||
importer.textureType = TextureImporterType.Sprite;
|
||||
importer.spritePixelsPerUnit = 100;
|
||||
importer.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
|
||||
static GameObject CreateMessageRowPrefab()
|
||||
{
|
||||
var root = new GameObject("DialogueMessageRow", typeof(RectTransform), typeof(DialogueMessageRow));
|
||||
var rootRt = root.GetComponent<RectTransform>();
|
||||
rootRt.sizeDelta = new Vector2(0f, 80f);
|
||||
|
||||
var layout = root.AddComponent<VerticalLayoutGroup>();
|
||||
layout.padding = new RectOffset(12, 12, 8, 8);
|
||||
layout.spacing = 4f;
|
||||
layout.childControlHeight = true;
|
||||
layout.childControlWidth = true;
|
||||
layout.childForceExpandHeight = false;
|
||||
layout.childForceExpandWidth = true;
|
||||
|
||||
var fitter = root.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
fitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
|
||||
|
||||
var speakerGo = CreateTmp("Speaker", root.transform, 22f, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||
var bodyGo = CreateTmp("Body", root.transform, 28f, FontStyles.Normal, TextAlignmentOptions.TopLeft);
|
||||
|
||||
var row = root.GetComponent<DialogueMessageRow>();
|
||||
var so = new SerializedObject(row);
|
||||
so.FindProperty("speakerText").objectReferenceValue = speakerGo.GetComponent<TMP_Text>();
|
||||
so.FindProperty("bodyText").objectReferenceValue = bodyGo.GetComponent<TMP_Text>();
|
||||
so.FindProperty("speakerLabel").objectReferenceValue = speakerGo;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
var prefab = PrefabUtility.SaveAsPrefabAsset(root, MessageRowPrefabPath);
|
||||
Object.DestroyImmediate(root);
|
||||
return prefab;
|
||||
}
|
||||
|
||||
static GameObject CreateSkillRowPrefab()
|
||||
{
|
||||
var root = new GameObject("SkillRow", typeof(RectTransform), typeof(SkillRowView));
|
||||
var rootRt = root.GetComponent<RectTransform>();
|
||||
rootRt.sizeDelta = new Vector2(0f, 48f);
|
||||
|
||||
var hlg = root.AddComponent<HorizontalLayoutGroup>();
|
||||
hlg.padding = new RectOffset(8, 8, 4, 4);
|
||||
hlg.spacing = 12f;
|
||||
hlg.childAlignment = TextAnchor.MiddleLeft;
|
||||
hlg.childControlHeight = true;
|
||||
hlg.childControlWidth = true;
|
||||
hlg.childForceExpandHeight = true;
|
||||
hlg.childForceExpandWidth = false;
|
||||
|
||||
var stripe = CreateUiImage("Accent", root.transform, new Color(1f, 1f, 1f, 1f));
|
||||
stripe.GetComponent<LayoutElement>().preferredWidth = 6f;
|
||||
stripe.GetComponent<LayoutElement>().flexibleWidth = 0f;
|
||||
|
||||
var nameGo = CreateTmp("Name", root.transform, 24f, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||
nameGo.GetComponent<LayoutElement>().flexibleWidth = 1f;
|
||||
|
||||
var barGo = new GameObject("Bar", typeof(RectTransform), typeof(Image), typeof(LayoutElement));
|
||||
barGo.transform.SetParent(root.transform, false);
|
||||
barGo.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.22f, 1f);
|
||||
barGo.GetComponent<LayoutElement>().preferredWidth = 160f;
|
||||
barGo.GetComponent<LayoutElement>().flexibleWidth = 0f;
|
||||
barGo.GetComponent<LayoutElement>().preferredHeight = 16f;
|
||||
|
||||
var fillGo = CreateUiImage("Fill", barGo.transform, Color.white);
|
||||
var fillRt = fillGo.GetComponent<RectTransform>();
|
||||
fillRt.anchorMin = Vector2.zero;
|
||||
fillRt.anchorMax = Vector2.one;
|
||||
fillRt.offsetMin = Vector2.zero;
|
||||
fillRt.offsetMax = Vector2.zero;
|
||||
var fillImage = fillGo.GetComponent<Image>();
|
||||
fillImage.type = Image.Type.Filled;
|
||||
fillImage.fillMethod = Image.FillMethod.Horizontal;
|
||||
fillImage.fillAmount = 0.2f;
|
||||
Object.DestroyImmediate(fillGo.GetComponent<LayoutElement>());
|
||||
|
||||
var rankGo = CreateTmp("Rank", root.transform, 24f, FontStyles.Normal, TextAlignmentOptions.Right);
|
||||
rankGo.GetComponent<LayoutElement>().preferredWidth = 40f;
|
||||
rankGo.GetComponent<LayoutElement>().flexibleWidth = 0f;
|
||||
|
||||
var view = root.GetComponent<SkillRowView>();
|
||||
var so = new SerializedObject(view);
|
||||
so.FindProperty("nameLabel").objectReferenceValue = nameGo.GetComponent<TMP_Text>();
|
||||
so.FindProperty("rankLabel").objectReferenceValue = rankGo.GetComponent<TMP_Text>();
|
||||
so.FindProperty("barFill").objectReferenceValue = fillImage;
|
||||
so.FindProperty("accentStripe").objectReferenceValue = stripe.GetComponent<Image>();
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
var prefab = PrefabUtility.SaveAsPrefabAsset(root, SkillRowPrefabPath);
|
||||
Object.DestroyImmediate(root);
|
||||
return prefab;
|
||||
}
|
||||
|
||||
static GameObject CreateDialogueStreamCanvasPrefab(GameObject messageRowPrefab)
|
||||
{
|
||||
var canvasGo = CreateCanvas("DialogueStreamCanvas", 5);
|
||||
var canvasGroup = canvasGo.AddComponent<CanvasGroup>();
|
||||
|
||||
var panel = new GameObject("Panel", typeof(RectTransform), typeof(Image));
|
||||
panel.transform.SetParent(canvasGo.transform, false);
|
||||
var panelRt = panel.GetComponent<RectTransform>();
|
||||
panelRt.anchorMin = new Vector2(0.66f, 0f);
|
||||
panelRt.anchorMax = new Vector2(1f, 1f);
|
||||
panelRt.offsetMin = Vector2.zero;
|
||||
panelRt.offsetMax = Vector2.zero;
|
||||
panel.GetComponent<Image>().color = new Color(0.05f, 0.05f, 0.08f, 0.92f);
|
||||
|
||||
var scrollGo = new GameObject("Scroll", typeof(RectTransform), typeof(ScrollRect), typeof(Image));
|
||||
scrollGo.transform.SetParent(panel.transform, false);
|
||||
Stretch(scrollGo.GetComponent<RectTransform>(), 8f);
|
||||
scrollGo.GetComponent<Image>().color = new Color(0f, 0f, 0f, 0.01f);
|
||||
|
||||
var viewport = new GameObject("Viewport", typeof(RectTransform), typeof(RectMask2D), typeof(Image));
|
||||
viewport.transform.SetParent(scrollGo.transform, false);
|
||||
Stretch(viewport.GetComponent<RectTransform>());
|
||||
viewport.GetComponent<Image>().color = new Color(1f, 1f, 1f, 0.01f);
|
||||
|
||||
var content = new GameObject("Content", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
|
||||
content.transform.SetParent(viewport.transform, false);
|
||||
var contentRt = content.GetComponent<RectTransform>();
|
||||
contentRt.anchorMin = new Vector2(0f, 0f);
|
||||
contentRt.anchorMax = new Vector2(1f, 0f);
|
||||
contentRt.pivot = new Vector2(0.5f, 0f);
|
||||
contentRt.sizeDelta = new Vector2(0f, 0f);
|
||||
|
||||
var vlg = content.GetComponent<VerticalLayoutGroup>();
|
||||
vlg.childAlignment = TextAnchor.LowerCenter;
|
||||
vlg.childControlHeight = true;
|
||||
vlg.childControlWidth = true;
|
||||
vlg.childForceExpandHeight = false;
|
||||
vlg.childForceExpandWidth = true;
|
||||
vlg.spacing = 6f;
|
||||
vlg.padding = new RectOffset(4, 4, 8, 8);
|
||||
|
||||
var csf = content.GetComponent<ContentSizeFitter>();
|
||||
csf.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
var messages = new GameObject("Messages", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
|
||||
messages.transform.SetParent(content.transform, false);
|
||||
ConfigureVerticalContent(messages);
|
||||
|
||||
var options = new GameObject("Options", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter), typeof(CanvasGroup));
|
||||
options.transform.SetParent(content.transform, false);
|
||||
ConfigureVerticalContent(options);
|
||||
var optionsGroup = options.GetComponent<CanvasGroup>();
|
||||
optionsGroup.alpha = 0f;
|
||||
optionsGroup.interactable = false;
|
||||
optionsGroup.blocksRaycasts = false;
|
||||
|
||||
var scroll = scrollGo.GetComponent<ScrollRect>();
|
||||
scroll.content = contentRt;
|
||||
scroll.viewport = viewport.GetComponent<RectTransform>();
|
||||
scroll.horizontal = false;
|
||||
scroll.vertical = true;
|
||||
scroll.movementType = ScrollRect.MovementType.Clamped;
|
||||
|
||||
var streamPresenter = canvasGo.AddComponent<DialogueStreamPresenter>();
|
||||
var streamSo = new SerializedObject(streamPresenter);
|
||||
streamSo.FindProperty("messageRowPrefab").objectReferenceValue = messageRowPrefab.GetComponent<DialogueMessageRow>();
|
||||
streamSo.FindProperty("messageContainer").objectReferenceValue = messages.GetComponent<RectTransform>();
|
||||
streamSo.FindProperty("scrollRect").objectReferenceValue = scroll;
|
||||
streamSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
var optionPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(
|
||||
"Packages/dev.yarnspinner.unity/Prefabs/Option Item.prefab");
|
||||
var optionsPresenter = canvasGo.AddComponent<DialogueStreamOptionsPresenter>();
|
||||
var optSo = new SerializedObject(optionsPresenter);
|
||||
if (optionPrefab != null)
|
||||
{
|
||||
optSo.FindProperty("optionViewPrefab").objectReferenceValue = optionPrefab.GetComponent<OptionItem>();
|
||||
}
|
||||
|
||||
optSo.FindProperty("optionsContainer").objectReferenceValue = options.transform;
|
||||
optSo.FindProperty("canvasGroup").objectReferenceValue = optionsGroup;
|
||||
optSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
// Start hidden — DialogueTransitionController shows it.
|
||||
canvasGroup.alpha = 0f;
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
|
||||
var prefab = PrefabUtility.SaveAsPrefabAsset(canvasGo, StreamCanvasPrefabPath);
|
||||
Object.DestroyImmediate(canvasGo);
|
||||
return prefab;
|
||||
}
|
||||
|
||||
static GameObject CreateHudCanvasPrefab()
|
||||
{
|
||||
var canvasGo = CreateCanvas("HudCanvas", 10);
|
||||
var portraitSprite = AssetDatabase.LoadAssetAtPath<Sprite>(PortraitPath);
|
||||
|
||||
var panel = new GameObject("PortraitPanel", typeof(RectTransform), typeof(CanvasGroup), typeof(Image), typeof(Button));
|
||||
panel.transform.SetParent(canvasGo.transform, false);
|
||||
var panelRt = panel.GetComponent<RectTransform>();
|
||||
panelRt.anchorMin = new Vector2(1f, 0f);
|
||||
panelRt.anchorMax = new Vector2(1f, 0f);
|
||||
panelRt.pivot = new Vector2(1f, 0f);
|
||||
panelRt.sizeDelta = new Vector2(220f, 280f);
|
||||
panelRt.anchoredPosition = new Vector2(-24f, 24f);
|
||||
panel.GetComponent<Image>().color = new Color(0.15f, 0.15f, 0.18f, 0.95f);
|
||||
if (portraitSprite != null)
|
||||
{
|
||||
panel.GetComponent<Image>().sprite = portraitSprite;
|
||||
panel.GetComponent<Image>().preserveAspect = true;
|
||||
}
|
||||
|
||||
var hint = CreateTmp("TabHint", panel.transform, 18f, FontStyles.Normal, TextAlignmentOptions.Center);
|
||||
var hintRt = hint.GetComponent<RectTransform>();
|
||||
hintRt.anchorMin = new Vector2(0f, 0f);
|
||||
hintRt.anchorMax = new Vector2(1f, 0f);
|
||||
hintRt.pivot = new Vector2(0.5f, 0f);
|
||||
hintRt.sizeDelta = new Vector2(0f, 28f);
|
||||
hintRt.anchoredPosition = new Vector2(0f, 4f);
|
||||
hint.GetComponent<TMP_Text>().text = "Tab";
|
||||
Object.DestroyImmediate(hint.GetComponent<LayoutElement>());
|
||||
|
||||
var view = canvasGo.AddComponent<PortraitHudView>();
|
||||
var so = new SerializedObject(view);
|
||||
so.FindProperty("panelRoot").objectReferenceValue = panel;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
var prefab = PrefabUtility.SaveAsPrefabAsset(canvasGo, HudCanvasPrefabPath);
|
||||
Object.DestroyImmediate(canvasGo);
|
||||
return prefab;
|
||||
}
|
||||
|
||||
static GameObject CreatePlayerMenuCanvasPrefab(GameObject skillRowPrefab)
|
||||
{
|
||||
var canvasGo = CreateCanvas("PlayerMenuCanvas", 20);
|
||||
var rootGroup = canvasGo.AddComponent<CanvasGroup>();
|
||||
|
||||
var dimmer = CreateUiImage("Dimmer", canvasGo.transform, new Color(0f, 0f, 0f, 0.6f));
|
||||
Stretch(dimmer.GetComponent<RectTransform>());
|
||||
Object.DestroyImmediate(dimmer.GetComponent<LayoutElement>());
|
||||
|
||||
var body = new GameObject("MenuBody", typeof(RectTransform), typeof(Image));
|
||||
body.transform.SetParent(canvasGo.transform, false);
|
||||
var bodyRt = body.GetComponent<RectTransform>();
|
||||
bodyRt.anchorMin = new Vector2(0.15f, 0.1f);
|
||||
bodyRt.anchorMax = new Vector2(0.85f, 0.9f);
|
||||
bodyRt.offsetMin = Vector2.zero;
|
||||
bodyRt.offsetMax = Vector2.zero;
|
||||
body.GetComponent<Image>().color = new Color(0.08f, 0.08f, 0.1f, 0.98f);
|
||||
|
||||
var tabBarGo = new GameObject("TabBar", typeof(RectTransform), typeof(HorizontalLayoutGroup), typeof(MenuTabBar));
|
||||
tabBarGo.transform.SetParent(body.transform, false);
|
||||
var tabBarRt = tabBarGo.GetComponent<RectTransform>();
|
||||
tabBarRt.anchorMin = new Vector2(0f, 1f);
|
||||
tabBarRt.anchorMax = new Vector2(1f, 1f);
|
||||
tabBarRt.pivot = new Vector2(0.5f, 1f);
|
||||
tabBarRt.sizeDelta = new Vector2(0f, 56f);
|
||||
tabBarRt.anchoredPosition = Vector2.zero;
|
||||
var tabHlg = tabBarGo.GetComponent<HorizontalLayoutGroup>();
|
||||
tabHlg.spacing = 8f;
|
||||
tabHlg.padding = new RectOffset(12, 12, 8, 8);
|
||||
// childControl* default to FALSE on a script-added layout group. Left
|
||||
// false, each tab button keeps its own 100px sizeDelta ("Character"
|
||||
// clips to "Charact") and childForceExpandWidth dumps all the leftover
|
||||
// room between them as a gap instead of widening them.
|
||||
tabHlg.childControlWidth = true;
|
||||
tabHlg.childControlHeight = true;
|
||||
tabHlg.childForceExpandWidth = true;
|
||||
tabHlg.childForceExpandHeight = true;
|
||||
|
||||
var contentArea = new GameObject("ContentArea", typeof(RectTransform));
|
||||
contentArea.transform.SetParent(body.transform, false);
|
||||
var contentRt = contentArea.GetComponent<RectTransform>();
|
||||
contentRt.anchorMin = new Vector2(0f, 0f);
|
||||
contentRt.anchorMax = new Vector2(1f, 1f);
|
||||
contentRt.offsetMin = new Vector2(16f, 16f);
|
||||
contentRt.offsetMax = new Vector2(-16f, -64f);
|
||||
|
||||
var characterPanel = CreateTabPanel("CharacterPanel", contentArea.transform);
|
||||
var skillsPanel = CreateTabPanel("SkillsPanel", contentArea.transform);
|
||||
var journalPanel = CreateTabPanel("JournalPanel", contentArea.transform);
|
||||
|
||||
// Character content
|
||||
var charView = characterPanel.AddComponent<CharacterPanelView>();
|
||||
var nameLabel = CreateTmp("Name", characterPanel.transform, 36f, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||
var aliasLabel = CreateTmp("Alias", characterPanel.transform, 28f, FontStyles.Italic, TextAlignmentOptions.Left);
|
||||
var invLabel = CreateTmp("Inventory", characterPanel.transform, 24f, FontStyles.Normal, TextAlignmentOptions.Left);
|
||||
var charVlg = characterPanel.AddComponent<VerticalLayoutGroup>();
|
||||
charVlg.spacing = 12f;
|
||||
charVlg.padding = new RectOffset(8, 8, 8, 8);
|
||||
charVlg.childControlWidth = true;
|
||||
charVlg.childControlHeight = true;
|
||||
charVlg.childForceExpandWidth = true;
|
||||
charVlg.childForceExpandHeight = false;
|
||||
var charSo = new SerializedObject(charView);
|
||||
charSo.FindProperty("nameLabel").objectReferenceValue = nameLabel.GetComponent<TMP_Text>();
|
||||
charSo.FindProperty("aliasLabel").objectReferenceValue = aliasLabel.GetComponent<TMP_Text>();
|
||||
charSo.FindProperty("inventoryPlaceholder").objectReferenceValue = invLabel.GetComponent<TMP_Text>();
|
||||
charSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
// Skills content
|
||||
var skillsScroll = new GameObject("SkillsScroll", typeof(RectTransform), typeof(ScrollRect));
|
||||
skillsScroll.transform.SetParent(skillsPanel.transform, false);
|
||||
Stretch(skillsScroll.GetComponent<RectTransform>());
|
||||
var skillsViewport = new GameObject("Viewport", typeof(RectTransform), typeof(RectMask2D), typeof(Image));
|
||||
skillsViewport.transform.SetParent(skillsScroll.transform, false);
|
||||
Stretch(skillsViewport.GetComponent<RectTransform>());
|
||||
skillsViewport.GetComponent<Image>().color = new Color(1f, 1f, 1f, 0.01f);
|
||||
var skillsContent = new GameObject("Content", typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
|
||||
skillsContent.transform.SetParent(skillsViewport.transform, false);
|
||||
ConfigureVerticalContent(skillsContent);
|
||||
var skillsContentRt = skillsContent.GetComponent<RectTransform>();
|
||||
skillsContentRt.anchorMin = new Vector2(0f, 1f);
|
||||
skillsContentRt.anchorMax = new Vector2(1f, 1f);
|
||||
skillsContentRt.pivot = new Vector2(0.5f, 1f);
|
||||
var skillsScrollRect = skillsScroll.GetComponent<ScrollRect>();
|
||||
skillsScrollRect.content = skillsContentRt;
|
||||
skillsScrollRect.viewport = skillsViewport.GetComponent<RectTransform>();
|
||||
skillsScrollRect.horizontal = false;
|
||||
|
||||
var axisHeaderTemplate = CreateTmp("AxisHeaderTemplate", skillsContent.transform, 20f, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||
axisHeaderTemplate.SetActive(false);
|
||||
|
||||
var skillsView = skillsPanel.AddComponent<SkillsPanelView>();
|
||||
var skillsSo = new SerializedObject(skillsView);
|
||||
skillsSo.FindProperty("contentRoot").objectReferenceValue = skillsContentRt;
|
||||
skillsSo.FindProperty("rowPrefab").objectReferenceValue = skillRowPrefab.GetComponent<SkillRowView>();
|
||||
skillsSo.FindProperty("axisHeaderPrefab").objectReferenceValue = axisHeaderTemplate.GetComponent<TMP_Text>();
|
||||
skillsSo.FindProperty("displayMaxRank").intValue = 6;
|
||||
skillsSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
// Journal content
|
||||
var journalView = journalPanel.AddComponent<JournalPanelView>();
|
||||
var journalLabel = CreateTmp("Placeholder", journalPanel.transform, 28f, FontStyles.Italic, TextAlignmentOptions.Center);
|
||||
Stretch(journalLabel.GetComponent<RectTransform>());
|
||||
Object.DestroyImmediate(journalLabel.GetComponent<LayoutElement>());
|
||||
var journalSo = new SerializedObject(journalView);
|
||||
journalSo.FindProperty("placeholderLabel").objectReferenceValue = journalLabel.GetComponent<TMP_Text>();
|
||||
journalSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
var charBtn = CreateTabButton("Character", tabBarGo.transform);
|
||||
var skillsBtn = CreateTabButton("Skills", tabBarGo.transform);
|
||||
var journalBtn = CreateTabButton("Journal", tabBarGo.transform);
|
||||
|
||||
var tabBar = tabBarGo.GetComponent<MenuTabBar>();
|
||||
var tabSo = new SerializedObject(tabBar);
|
||||
var tabsProp = tabSo.FindProperty("tabs");
|
||||
tabsProp.arraySize = 3;
|
||||
// Character tab must refresh on show for the same reason as Skills:
|
||||
// panels toggle via CanvasGroup, so OnEnable never fires again.
|
||||
SetTabEntry(tabsProp.GetArrayElementAtIndex(0), charBtn.GetComponent<Button>(), characterPanel.GetComponent<CanvasGroup>(), charView, "Refresh");
|
||||
SetTabEntry(tabsProp.GetArrayElementAtIndex(1), skillsBtn.GetComponent<Button>(), skillsPanel.GetComponent<CanvasGroup>(), skillsView, "Refresh");
|
||||
SetTabEntry(tabsProp.GetArrayElementAtIndex(2), journalBtn.GetComponent<Button>(), journalPanel.GetComponent<CanvasGroup>(), null);
|
||||
tabSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
var menuController = canvasGo.AddComponent<PlayerMenuController>();
|
||||
var menuSo = new SerializedObject(menuController);
|
||||
menuSo.FindProperty("menuRoot").objectReferenceValue = canvasGo;
|
||||
menuSo.FindProperty("tabBar").objectReferenceValue = tabBar;
|
||||
menuSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
rootGroup.alpha = 0f;
|
||||
rootGroup.interactable = false;
|
||||
rootGroup.blocksRaycasts = false;
|
||||
|
||||
var prefab = PrefabUtility.SaveAsPrefabAsset(canvasGo, MenuCanvasPrefabPath);
|
||||
Object.DestroyImmediate(canvasGo);
|
||||
return prefab;
|
||||
}
|
||||
|
||||
static void SetTabEntry(SerializedProperty entry, Button button, CanvasGroup panel, Object target, string method = null)
|
||||
{
|
||||
entry.FindPropertyRelative("button").objectReferenceValue = button;
|
||||
entry.FindPropertyRelative("panel").objectReferenceValue = panel;
|
||||
if (target != null && method != null)
|
||||
{
|
||||
var onShown = entry.FindPropertyRelative("onShown");
|
||||
onShown.FindPropertyRelative("m_PersistentCalls.m_Calls").arraySize = 1;
|
||||
var call = onShown.FindPropertyRelative("m_PersistentCalls.m_Calls").GetArrayElementAtIndex(0);
|
||||
call.FindPropertyRelative("m_Target").objectReferenceValue = target;
|
||||
call.FindPropertyRelative("m_MethodName").stringValue = method;
|
||||
call.FindPropertyRelative("m_Mode").enumValueIndex = 1; // Void
|
||||
call.FindPropertyRelative("m_CallState").enumValueIndex = 2; // RuntimeOnly
|
||||
}
|
||||
}
|
||||
|
||||
static void WireScene(GameObject streamCanvasPrefab, GameObject hudCanvasPrefab, GameObject menuCanvasPrefab)
|
||||
{
|
||||
var scene = EditorSceneManager.OpenScene(ScenePath, OpenSceneMode.Single);
|
||||
|
||||
// UI System root
|
||||
var uiSystem = GameObject.Find("UI System");
|
||||
if (uiSystem == null)
|
||||
{
|
||||
uiSystem = new GameObject("UI System");
|
||||
}
|
||||
|
||||
if (uiSystem.GetComponent<UIStateController>() == null)
|
||||
{
|
||||
uiSystem.AddComponent<UIStateController>();
|
||||
}
|
||||
|
||||
// Player components
|
||||
var player = GameObject.Find("PlayerArmature");
|
||||
if (player == null)
|
||||
{
|
||||
Debug.LogError("[UILayerSetup] PlayerArmature not found in scene.");
|
||||
return;
|
||||
}
|
||||
|
||||
var controlLock = player.GetComponent<PlayerControlLock>();
|
||||
if (controlLock == null)
|
||||
{
|
||||
controlLock = player.AddComponent<PlayerControlLock>();
|
||||
}
|
||||
|
||||
var menuInput = player.GetComponent<PlayerMenuInput>();
|
||||
if (menuInput == null)
|
||||
{
|
||||
menuInput = player.AddComponent<PlayerMenuInput>();
|
||||
}
|
||||
|
||||
var inputs = player.GetComponent<StarterAssetsInputs>();
|
||||
if (inputs != null)
|
||||
{
|
||||
inputs.cursorLocked = false;
|
||||
EditorUtility.SetDirty(inputs);
|
||||
}
|
||||
|
||||
// DialogueTransitionController
|
||||
var transition = Object.FindFirstObjectByType<DialogueTransitionController>();
|
||||
if (transition != null)
|
||||
{
|
||||
var tSo = new SerializedObject(transition);
|
||||
tSo.FindProperty("controlLock").objectReferenceValue = controlLock;
|
||||
tSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
// Instantiate / refresh UI prefab instances
|
||||
var streamInstance = EnsurePrefabInstance(streamCanvasPrefab, "DialogueStreamCanvas");
|
||||
var hudInstance = EnsurePrefabInstance(hudCanvasPrefab, "HudCanvas");
|
||||
var menuInstance = EnsurePrefabInstance(menuCanvasPrefab, "PlayerMenuCanvas");
|
||||
|
||||
// Wire menu controller refs
|
||||
var menuController = menuInstance.GetComponent<PlayerMenuController>();
|
||||
if (menuController != null)
|
||||
{
|
||||
var mSo = new SerializedObject(menuController);
|
||||
mSo.FindProperty("menuInput").objectReferenceValue = menuInput;
|
||||
mSo.FindProperty("controlLock").objectReferenceValue = controlLock;
|
||||
mSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
// Portrait → Open menu
|
||||
var portraitButton = hudInstance.GetComponentInChildren<Button>(true);
|
||||
if (portraitButton != null && menuController != null)
|
||||
{
|
||||
while (portraitButton.onClick.GetPersistentEventCount() > 0)
|
||||
{
|
||||
UnityEditor.Events.UnityEventTools.RemovePersistentListener(portraitButton.onClick, 0);
|
||||
}
|
||||
|
||||
UnityEditor.Events.UnityEventTools.AddPersistentListener(portraitButton.onClick, menuController.Open);
|
||||
EditorUtility.SetDirty(portraitButton);
|
||||
}
|
||||
|
||||
// Camera framing
|
||||
var vcam = GameObject.Find("CinemachineCamera");
|
||||
if (vcam != null)
|
||||
{
|
||||
var framing = vcam.GetComponent<DialogueCameraFraming>();
|
||||
if (framing == null)
|
||||
{
|
||||
framing = vcam.AddComponent<DialogueCameraFraming>();
|
||||
}
|
||||
|
||||
var composer = vcam.GetComponent<CinemachinePositionComposer>();
|
||||
var fSo = new SerializedObject(framing);
|
||||
fSo.FindProperty("composer").objectReferenceValue = composer;
|
||||
fSo.FindProperty("dialogueScreenX").floatValue = -0.17f;
|
||||
fSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
// Re-point DialogueRunner presenters
|
||||
var runner = Object.FindFirstObjectByType<DialogueRunner>();
|
||||
var streamPresenter = streamInstance.GetComponent<DialogueStreamPresenter>();
|
||||
var optionsPresenter = streamInstance.GetComponent<DialogueStreamOptionsPresenter>();
|
||||
var lineAdvancer = Object.FindFirstObjectByType<LineAdvancer>();
|
||||
|
||||
if (runner != null && streamPresenter != null && optionsPresenter != null)
|
||||
{
|
||||
var rSo = new SerializedObject(runner);
|
||||
var presenters = rSo.FindProperty("dialoguePresenters");
|
||||
if (presenters != null)
|
||||
{
|
||||
presenters.arraySize = lineAdvancer != null ? 3 : 2;
|
||||
presenters.GetArrayElementAtIndex(0).objectReferenceValue = streamPresenter;
|
||||
presenters.GetArrayElementAtIndex(1).objectReferenceValue = optionsPresenter;
|
||||
if (lineAdvancer != null)
|
||||
{
|
||||
presenters.GetArrayElementAtIndex(2).objectReferenceValue = lineAdvancer;
|
||||
}
|
||||
|
||||
rSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
}
|
||||
|
||||
if (lineAdvancer != null && streamPresenter != null)
|
||||
{
|
||||
var aSo = new SerializedObject(lineAdvancer);
|
||||
aSo.FindProperty("presenter").objectReferenceValue = streamPresenter;
|
||||
aSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
// Point DialogueTransitionController.dialogueUI at the new canvas
|
||||
if (transition != null && streamInstance != null)
|
||||
{
|
||||
var tSo = new SerializedObject(transition);
|
||||
tSo.FindProperty("dialogueUI").objectReferenceValue = streamInstance;
|
||||
tSo.FindProperty("controlLock").objectReferenceValue = controlLock;
|
||||
tSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
// Deactivate the package Dialogue System Canvas (keep EventSystem alive)
|
||||
var dialogueSystem = GameObject.Find("Dialogue System");
|
||||
if (dialogueSystem != null)
|
||||
{
|
||||
var packageCanvas = dialogueSystem.transform.Find("Canvas");
|
||||
if (packageCanvas != null)
|
||||
{
|
||||
// Rescue the Skill Check Banner onto the scene-owned Skill Check
|
||||
// Canvas — NOT into streamInstance. EnsurePrefabInstance
|
||||
// DestroyImmediates the stream canvas on every re-run, so
|
||||
// anything parented under it dies with it; that is what left
|
||||
// SkillRuntime.resultView null after the second setup run.
|
||||
// Skill Check Canvas is scene-owned, survives re-runs, and its
|
||||
// sortingOrder 100 already draws above the dialogue canvas.
|
||||
var banner = packageCanvas.Find("Skill Check Banner");
|
||||
if (banner != null)
|
||||
{
|
||||
var bannerHost = GameObject.Find("Skill Check Canvas");
|
||||
if (bannerHost != null)
|
||||
{
|
||||
banner.SetParent(bannerHost.transform, false);
|
||||
}
|
||||
}
|
||||
|
||||
packageCanvas.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Repair SkillRuntime.resultView. It can be left dangling by an earlier
|
||||
// run of this menu item, and a null here silently disables every roll
|
||||
// banner ("SkillCheckResultView is not assigned; skipping roll banner").
|
||||
// Prefer an active view if more than one survives.
|
||||
SkillCheckResultView resultView = null;
|
||||
foreach (var candidate in Object.FindObjectsByType<SkillCheckResultView>(
|
||||
FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||
{
|
||||
if (resultView == null
|
||||
|| (!resultView.gameObject.activeInHierarchy && candidate.gameObject.activeInHierarchy))
|
||||
{
|
||||
resultView = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
var skillRuntime = Object.FindFirstObjectByType<SkillRuntime>();
|
||||
if (skillRuntime != null && resultView != null)
|
||||
{
|
||||
var skillSo = new SerializedObject(skillRuntime);
|
||||
skillSo.FindProperty("resultView").objectReferenceValue = resultView;
|
||||
skillSo.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
else if (skillRuntime != null)
|
||||
{
|
||||
Debug.LogWarning("[UILayerSetup] No SkillCheckResultView found in the scene; roll banners will not display.", skillRuntime);
|
||||
}
|
||||
|
||||
// Update NPCStandIn dialogueUI refs to the new canvas
|
||||
foreach (var npc in Object.FindObjectsByType<NPCStandIn>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||
{
|
||||
var so = new SerializedObject(npc);
|
||||
var uiProp = so.FindProperty("dialogueUI");
|
||||
if (uiProp != null)
|
||||
{
|
||||
uiProp.objectReferenceValue = streamInstance;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
}
|
||||
|
||||
EditorSceneManager.MarkSceneDirty(scene);
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
}
|
||||
|
||||
static GameObject EnsurePrefabInstance(GameObject prefab, string name)
|
||||
{
|
||||
var existing = GameObject.Find(name);
|
||||
if (existing != null)
|
||||
{
|
||||
Object.DestroyImmediate(existing);
|
||||
}
|
||||
|
||||
var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
|
||||
instance.name = name;
|
||||
return instance;
|
||||
}
|
||||
|
||||
static GameObject CreateCanvas(string name, int sortingOrder)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
|
||||
var canvas = go.GetComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.sortingOrder = sortingOrder;
|
||||
var scaler = go.GetComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
return go;
|
||||
}
|
||||
|
||||
static GameObject CreateTabPanel(string name, Transform parent)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform), typeof(CanvasGroup));
|
||||
go.transform.SetParent(parent, false);
|
||||
Stretch(go.GetComponent<RectTransform>());
|
||||
var group = go.GetComponent<CanvasGroup>();
|
||||
group.alpha = 0f;
|
||||
group.interactable = false;
|
||||
group.blocksRaycasts = false;
|
||||
return go;
|
||||
}
|
||||
|
||||
static GameObject CreateTabButton(string label, Transform parent)
|
||||
{
|
||||
var go = new GameObject(label, typeof(RectTransform), typeof(Image), typeof(Button), typeof(LayoutElement));
|
||||
go.transform.SetParent(parent, false);
|
||||
go.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.25f, 1f);
|
||||
var text = CreateTmp("Label", go.transform, 22f, FontStyles.Bold, TextAlignmentOptions.Center);
|
||||
Stretch(text.GetComponent<RectTransform>());
|
||||
Object.DestroyImmediate(text.GetComponent<LayoutElement>());
|
||||
text.GetComponent<TMP_Text>().text = label;
|
||||
return go;
|
||||
}
|
||||
|
||||
static GameObject CreateTmp(string name, Transform parent, float size, FontStyles style, TextAlignmentOptions align)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform), typeof(TextMeshProUGUI), typeof(LayoutElement));
|
||||
go.transform.SetParent(parent, false);
|
||||
var tmp = go.GetComponent<TextMeshProUGUI>();
|
||||
tmp.fontSize = size;
|
||||
tmp.fontStyle = style;
|
||||
tmp.alignment = align;
|
||||
tmp.color = Color.white;
|
||||
tmp.text = name;
|
||||
tmp.textWrappingMode = TextWrappingModes.Normal;
|
||||
|
||||
// Deliberately no LayoutElement.preferredHeight. A fixed height here is
|
||||
// one line's worth, and LayoutElement outranks TMP's own ILayoutElement
|
||||
// report — so a wrapped 4-line body would be allocated ~40px while
|
||||
// rendering ~150px, and consecutive rows draw on top of each other.
|
||||
// Leaving it at the -1 default lets TMP measure the wrapped text.
|
||||
// The component stays so callers can still set preferredWidth /
|
||||
// flexibleWidth (see the skill row).
|
||||
return go;
|
||||
}
|
||||
|
||||
static GameObject CreateUiImage(string name, Transform parent, Color color)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform), typeof(Image), typeof(LayoutElement));
|
||||
go.transform.SetParent(parent, false);
|
||||
go.GetComponent<Image>().color = color;
|
||||
return go;
|
||||
}
|
||||
|
||||
static void Stretch(RectTransform rt, float pad = 0f)
|
||||
{
|
||||
rt.anchorMin = Vector2.zero;
|
||||
rt.anchorMax = Vector2.one;
|
||||
rt.offsetMin = new Vector2(pad, pad);
|
||||
rt.offsetMax = new Vector2(-pad, -pad);
|
||||
}
|
||||
|
||||
static void ConfigureVerticalContent(GameObject go)
|
||||
{
|
||||
var rt = go.GetComponent<RectTransform>();
|
||||
rt.anchorMin = new Vector2(0f, 0f);
|
||||
rt.anchorMax = new Vector2(1f, 0f);
|
||||
rt.pivot = new Vector2(0.5f, 0f);
|
||||
|
||||
// A RectTransform added via `new GameObject(..., typeof(RectTransform))`
|
||||
// starts at sizeDelta (100,100). With horizontal-stretch anchors that
|
||||
// makes the rect parentWidth + 100 wide, centred — overhanging 50px off
|
||||
// each side, and the RectMask2D shears the left edge off every label.
|
||||
// ContentSizeFitter only governs the vertical axis, so it never
|
||||
// corrects this. Zero the horizontal size explicitly.
|
||||
rt.sizeDelta = new Vector2(0f, rt.sizeDelta.y);
|
||||
rt.anchoredPosition = Vector2.zero;
|
||||
|
||||
var vlg = go.GetComponent<VerticalLayoutGroup>();
|
||||
vlg.childControlHeight = true;
|
||||
vlg.childControlWidth = true;
|
||||
vlg.childForceExpandHeight = false;
|
||||
vlg.childForceExpandWidth = true;
|
||||
vlg.spacing = 4f;
|
||||
var csf = go.GetComponent<ContentSizeFitter>();
|
||||
csf.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Reminds the user to run the one-shot prefab/scene wiring menu after scripts
|
||||
/// compile. Runtime play works without it via UILayerBootstrap.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
static class UILayerSetupAutoRun
|
||||
{
|
||||
const string PrefKey = "NightclubArcadia.UILayerSetup.Reminded";
|
||||
const string MarkerPrefab = "Assets/Prefabs/UI/PlayerMenuCanvas.prefab";
|
||||
|
||||
static UILayerSetupAutoRun()
|
||||
{
|
||||
EditorApplication.delayCall += RemindIfNeeded;
|
||||
}
|
||||
|
||||
static void RemindIfNeeded()
|
||||
{
|
||||
if (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isCompiling)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AssetDatabase.LoadAssetAtPath<GameObject>(MarkerPrefab) != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (EditorPrefs.GetBool(PrefKey, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorPrefs.SetBool(PrefKey, true);
|
||||
Debug.Log(
|
||||
"[UILayer] Prefabs not built yet. Play Mode works via UILayerBootstrap. " +
|
||||
"To author prefabs into the scene, run Tools → Nightclub Arcadia → Set Up UI Layer.");
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Nightclub Arcadia/Reset UI Layer Auto-Setup Flag")]
|
||||
static void ResetFlag()
|
||||
{
|
||||
EditorPrefs.DeleteKey(PrefKey);
|
||||
Debug.Log("[UILayer] Reminder flag cleared.");
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using Yarn.Compiler;
|
||||
using Yarn.Unity;
|
||||
using Yarn.Unity.Editor;
|
||||
|
||||
public static class YarnDemoSetup
|
||||
{
|
||||
const string YarnProjectPath = "Assets/Dialogue/NightclubArcadia.yarnproject";
|
||||
const string ScenePath = "Assets/Scenes/DialogueTest.unity";
|
||||
|
||||
[MenuItem("Tools/Nightclub Arcadia/Set Up Yarn Dialogue Test")]
|
||||
public static void SetUpYarnDialogueTest()
|
||||
{
|
||||
if (!AssetDatabase.IsValidFolder("Assets/TextMesh Pro"))
|
||||
{
|
||||
Debug.LogWarning("TextMesh Pro essential resources are missing. Run Window → TextMeshPro → Import TMP Essential Resources.");
|
||||
}
|
||||
|
||||
if (!AssetDatabase.IsValidFolder("Assets/Dialogue"))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets", "Dialogue");
|
||||
}
|
||||
|
||||
if (!AssetDatabase.IsValidFolder("Assets/Scenes"))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets", "Scenes");
|
||||
}
|
||||
|
||||
var yarnProject = AssetDatabase.LoadAssetAtPath<YarnProject>(YarnProjectPath);
|
||||
if (yarnProject == null)
|
||||
{
|
||||
// YarnProjectUtility.CreateDefaultYarnProject is internal, so
|
||||
// construct the same default project here.
|
||||
var project = new Project
|
||||
{
|
||||
ExcludeFilePatterns = new[] { "**/*~/*", "./Samples/Yarn Spinner*/*" },
|
||||
};
|
||||
YarnEditorUtility.CreateYarnProject(YarnProjectPath, project);
|
||||
AssetDatabase.Refresh();
|
||||
yarnProject = AssetDatabase.LoadAssetAtPath<YarnProject>(YarnProjectPath);
|
||||
}
|
||||
|
||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
|
||||
|
||||
var runner = CreateDialogueRunnerMenuItem.CreateDialogueRunner();
|
||||
|
||||
var so = new SerializedObject(runner);
|
||||
so.FindProperty("yarnProject").objectReferenceValue = yarnProject;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
runner.autoStart = true;
|
||||
runner.startNode = "Start";
|
||||
EditorUtility.SetDirty(runner);
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var eventSystems = Object.FindObjectsByType<EventSystem>(FindObjectsInactive.Include);
|
||||
#else
|
||||
var eventSystems = Object.FindObjectsOfType<EventSystem>(true);
|
||||
#endif
|
||||
foreach (var eventSystem in eventSystems)
|
||||
{
|
||||
if (eventSystem.GetComponent<BaseInputModule>() != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
eventSystem.gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
|
||||
#endif
|
||||
}
|
||||
|
||||
EditorSceneManager.SaveScene(scene, ScenePath);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log($"Yarn dialogue test setup complete. Scene saved to {ScenePath}");
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d9af60546b8c47c892a7b924fd4c91e
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d48f257d1ed84378baccde7a64adf41
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,539 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4737069642952972654
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1722946503423415487}
|
||||
- component: {fileID: 8432845660793814868}
|
||||
- component: {fileID: 6335817353128072766}
|
||||
- component: {fileID: 2944890677120165287}
|
||||
m_Layer: 0
|
||||
m_Name: Prompt
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1722946503423415487
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4737069642952972654}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 172386393200463862}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0.7}
|
||||
m_SizeDelta: {x: 1.5, y: 0.4}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!23 &8432845660793814868
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4737069642952972654}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_MaskInteraction: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &6335817353128072766
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4737069642952972654}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text:
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: 0
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 3
|
||||
m_fontSizeBase: 3
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 0
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
_SortingLayer: 0
|
||||
_SortingLayerID: 0
|
||||
_SortingOrder: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_renderer: {fileID: 8432845660793814868}
|
||||
m_maskType: 0
|
||||
--- !u!114 &2944890677120165287
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4737069642952972654}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 10b4e7c1069944b49acca9287528f275, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.InteractionPrompt
|
||||
--- !u!1 &7322328536378480179
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4239915935349831280}
|
||||
- component: {fileID: 5807897220633392622}
|
||||
- component: {fileID: 2641391509207732614}
|
||||
- component: {fileID: 2690437797691371565}
|
||||
m_Layer: 0
|
||||
m_Name: Label
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4239915935349831280
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7322328536378480179}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 172386393200463862}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 1.2}
|
||||
m_SizeDelta: {x: 2, y: 0.5}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!23 &5807897220633392622
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7322328536378480179}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_MaskInteraction: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &2641391509207732614
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7322328536378480179}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Bartender
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: 0
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 4
|
||||
m_fontSizeBase: 4
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 0
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
_SortingLayer: 0
|
||||
_SortingLayerID: 0
|
||||
_SortingOrder: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_renderer: {fileID: 5807897220633392622}
|
||||
m_maskType: 0
|
||||
--- !u!114 &2690437797691371565
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7322328536378480179}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5d24ca2949394cc78a1fdde5d83e08c2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.WorldSpaceLabel
|
||||
billboard: 1
|
||||
--- !u!1 &7530910684996007227
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 172386393200463862}
|
||||
- component: {fileID: 1403734579041167056}
|
||||
- component: {fileID: 3418223217292734787}
|
||||
- component: {fileID: 2161798758485273970}
|
||||
- component: {fileID: 3703434673071649520}
|
||||
- component: {fileID: 3878869479229240904}
|
||||
m_Layer: 0
|
||||
m_Name: Bartender
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &172386393200463862
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7530910684996007227}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4239915935349831280}
|
||||
- {fileID: 1722946503423415487}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &1403734579041167056
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7530910684996007227}
|
||||
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!135 &3418223217292734787
|
||||
SphereCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7530910684996007227}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Radius: 0.5
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &2161798758485273970
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7530910684996007227}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: fa72b8a577b83400c8fe35f9f594fb93, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 1
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_MaskInteraction: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &3703434673071649520
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7530910684996007227}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ba3ce042c3b3457ba101f1c6643b983f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.DialogueInteractor
|
||||
definition: {fileID: 11400000, guid: 8ccb543c858f74a969cb025cb3e1f0ea, type: 2}
|
||||
label: {fileID: 2690437797691371565}
|
||||
prompt: {fileID: 2944890677120165287}
|
||||
dialogueUI: {fileID: 0}
|
||||
--- !u!114 &3878869479229240904
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7530910684996007227}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7862f80331f384d28b27600075971a77, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Cinematics.CameraPointOfInterest
|
||||
weight: 1
|
||||
triggerRadius: 8
|
||||
maxBias: 2.5
|
||||
extraDistance: 1.5
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0db6e63cdcba4608a13198c04bfc610
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,137 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Bartender_Placeholder
|
||||
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap:
|
||||
RenderType: Opaque
|
||||
disabledShaderPasses:
|
||||
- MOTIONVECTORS
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _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}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AddPrecomputedVelocity: 0
|
||||
- _AlphaClip: 0
|
||||
- _AlphaToMask: 0
|
||||
- _Blend: 0
|
||||
- _BlendModePreserveSpecular: 1
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _DstBlendAlpha: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _SrcBlendAlpha: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _XRMotionVectorsPass: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 0.92, b: 0.016, a: 1}
|
||||
- _Color: {r: 1, g: 0.92, b: 0.016, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &9147223334991767282
|
||||
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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
|
||||
version: 10
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8105016687592461f977c054a80ce2f2
|
||||
guid: fa72b8a577b83400c8fe35f9f594fb93
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8c20d75ae36249ab8379c0e4913f984
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,539 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &777994819892892268
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1239266274743412553}
|
||||
- component: {fileID: 4457577143334209326}
|
||||
- component: {fileID: 7850630094993076482}
|
||||
- component: {fileID: 5006241980557930104}
|
||||
m_Layer: 0
|
||||
m_Name: Prompt
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1239266274743412553
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 777994819892892268}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 8926026372035049776}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0.7}
|
||||
m_SizeDelta: {x: 1.5, y: 0.4}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!23 &4457577143334209326
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 777994819892892268}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_MaskInteraction: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &7850630094993076482
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 777994819892892268}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text:
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: 0
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 3
|
||||
m_fontSizeBase: 3
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 0
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
_SortingLayer: 0
|
||||
_SortingLayerID: 0
|
||||
_SortingOrder: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_renderer: {fileID: 4457577143334209326}
|
||||
m_maskType: 0
|
||||
--- !u!114 &5006241980557930104
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 777994819892892268}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 10b4e7c1069944b49acca9287528f275, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.InteractionPrompt
|
||||
--- !u!1 &1028094190342798046
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4034517959994022032}
|
||||
- component: {fileID: 6899414861324739809}
|
||||
- component: {fileID: 2525172943720193920}
|
||||
- component: {fileID: 8100187015087210284}
|
||||
m_Layer: 0
|
||||
m_Name: Label
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4034517959994022032
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1028094190342798046}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 8926026372035049776}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 1.2}
|
||||
m_SizeDelta: {x: 2, y: 0.5}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!23 &6899414861324739809
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1028094190342798046}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_MaskInteraction: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &2525172943720193920
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1028094190342798046}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Chair
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: 0
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 4
|
||||
m_fontSizeBase: 4
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 0
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
_SortingLayer: 0
|
||||
_SortingLayerID: 0
|
||||
_SortingOrder: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_renderer: {fileID: 6899414861324739809}
|
||||
m_maskType: 0
|
||||
--- !u!114 &8100187015087210284
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1028094190342798046}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5d24ca2949394cc78a1fdde5d83e08c2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.WorldSpaceLabel
|
||||
billboard: 1
|
||||
--- !u!1 &7280501095255275029
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8926026372035049776}
|
||||
- component: {fileID: 5837614995048342275}
|
||||
- component: {fileID: 3813584389814668824}
|
||||
- component: {fileID: 5825175854856588849}
|
||||
- component: {fileID: 9133955159482683932}
|
||||
- component: {fileID: 758253250585826679}
|
||||
m_Layer: 0
|
||||
m_Name: Chair
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &8926026372035049776
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7280501095255275029}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4034517959994022032}
|
||||
- {fileID: 1239266274743412553}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &5837614995048342275
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7280501095255275029}
|
||||
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!135 &3813584389814668824
|
||||
SphereCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7280501095255275029}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Radius: 0.5
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &5825175854856588849
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7280501095255275029}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_ForceMeshLod: -1
|
||||
m_MeshLodSelectionBias: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: dcf0462a407634956a12aae26cb9768b, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 1
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_MaskInteraction: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &9133955159482683932
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7280501095255275029}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ba3ce042c3b3457ba101f1c6643b983f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Interaction.DialogueInteractor
|
||||
definition: {fileID: 11400000, guid: 403e142c457b0412a8c8604a2a9807ed, type: 2}
|
||||
label: {fileID: 8100187015087210284}
|
||||
prompt: {fileID: 5006241980557930104}
|
||||
dialogueUI: {fileID: 0}
|
||||
--- !u!114 &758253250585826679
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7280501095255275029}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7862f80331f384d28b27600075971a77, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.Cinematics.CameraPointOfInterest
|
||||
weight: 1
|
||||
triggerRadius: 8
|
||||
maxBias: 2.5
|
||||
extraDistance: 1.5
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f94d8e9cc93d47deb267073aebce344
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,137 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &-386927403897027456
|
||||
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: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
|
||||
version: 10
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Chair_Placeholder
|
||||
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap:
|
||||
RenderType: Opaque
|
||||
disabledShaderPasses:
|
||||
- MOTIONVECTORS
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _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}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AddPrecomputedVelocity: 0
|
||||
- _AlphaClip: 0
|
||||
- _AlphaToMask: 0
|
||||
- _Blend: 0
|
||||
- _BlendModePreserveSpecular: 1
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _DstBlendAlpha: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _SrcBlendAlpha: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _XRMotionVectorsPass: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 0, g: 0, b: 1, a: 1}
|
||||
- _Color: {r: 0, g: 0, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcf0462a407634956a12aae26cb9768b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -51,7 +51,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a7773ea9a6f44798aa98356903037d16, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Dialogue.DialogueMessageRow
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Dialogue.DialogueMessageRow
|
||||
speakerText: {fileID: 5900251945930220314}
|
||||
bodyText: {fileID: 1670956017877202442}
|
||||
speakerLabel: {fileID: 5822252844234204748}
|
||||
|
||||
@@ -542,7 +542,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 88cb6495795a4e13ac7fb72343c132af, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Dialogue.DialogueStreamPresenter
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Dialogue.DialogueStreamPresenter
|
||||
messageRowPrefab: {fileID: 5353601244371665078, guid: 90818ef7dc74247ceb348994755cea86, type: 3}
|
||||
messageContainer: {fileID: 4838388606347767229}
|
||||
scrollRect: {fileID: 7105587415705135446}
|
||||
@@ -559,7 +559,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8d86cc99d5b545c4a3fad9e1482031a2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Dialogue.DialogueStreamOptionsPresenter
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Dialogue.DialogueStreamOptionsPresenter
|
||||
optionViewPrefab: {fileID: 2576261519635394347, guid: e605972137b0b4c1399ffb07beae9a9b, type: 3}
|
||||
optionsContainer: {fileID: 6329947636030823459}
|
||||
canvasGroup: {fileID: 5117926241503925785}
|
||||
|
||||
@@ -252,7 +252,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fd1354ade14b4b1d80da9acac4aa9e12, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.HUD.PortraitHudView
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.HUD.PortraitHudView
|
||||
panelRoot: {fileID: 4989543578856257477}
|
||||
--- !u!1 &4989543578856257477
|
||||
GameObject:
|
||||
|
||||
@@ -61,7 +61,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 74efa3bf7a354892a401418d8f56fb2b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.JournalPanelView
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.JournalPanelView
|
||||
placeholderLabel: {fileID: 438358810008138731}
|
||||
--- !u!1 &2044419659697384337
|
||||
GameObject:
|
||||
@@ -140,7 +140,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: db83a1a74e0e418881880ca808f68160, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.MenuTabBar
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.MenuTabBar
|
||||
tabs:
|
||||
- button: {fileID: 1673770274793931208}
|
||||
panel: {fileID: 5076829831943889175}
|
||||
@@ -245,7 +245,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ef17c93c7dec4af2ae7ce565c8984de3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.CharacterPanelView
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.CharacterPanelView
|
||||
nameLabel: {fileID: 8967222838737055253}
|
||||
aliasLabel: {fileID: 4652515771799086270}
|
||||
inventoryPlaceholder: {fileID: 1990427928476398531}
|
||||
@@ -483,7 +483,7 @@ MonoBehaviour:
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 118cc9783dba4b3cac1646d97ebd3998, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.PlayerMenuController
|
||||
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.PlayerMenuController
|
||||
menuRoot: {fileID: 2249656863633318815}
|
||||
menuInput: {fileID: 0}
|
||||
controlLock: {fileID: 0}
|
||||
@@ -783,6 +783,143 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &3123656435113957211
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2894368236897154238}
|
||||
- component: {fileID: 8211184503074210791}
|
||||
- component: {fileID: 8997850575536806412}
|
||||
m_Layer: 0
|
||||
m_Name: Label
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2894368236897154238
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3123656435113957211}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6001922808625371455}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8211184503074210791
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3123656435113957211}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8997850575536806412
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3123656435113957211}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Skills
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: 0
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 22
|
||||
m_fontSizeBase: 22
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 1
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &3533277334474984255
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1388,7 +1525,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 3528103284151106981}
|
||||
- {fileID: 1481520485721663919}
|
||||
m_Father: {fileID: 5714344749226447693}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
@@ -1605,7 +1742,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1015917500768946775}
|
||||
- {fileID: 2894368236897154238}
|
||||
m_Father: {fileID: 5714344749226447693}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
@@ -1873,7 +2010,7 @@ MonoBehaviour:
|
||||
m_FlexibleWidth: -1
|
||||
m_FlexibleHeight: -1
|
||||
m_LayoutPriority: 1
|
||||
--- !u!1 &7644334300092530069
|
||||
--- !u!1 &7967390318583634950
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -1881,9 +2018,9 @@ GameObject:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1015917500768946775}
|
||||
- component: {fileID: 4696967337599140493}
|
||||
- component: {fileID: 3131234387202370334}
|
||||
- component: {fileID: 1481520485721663919}
|
||||
- component: {fileID: 2759775973399345411}
|
||||
- component: {fileID: 6167893425112707945}
|
||||
m_Layer: 0
|
||||
m_Name: Label
|
||||
m_TagString: Untagged
|
||||
@@ -1891,40 +2028,40 @@ GameObject:
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1015917500768946775
|
||||
--- !u!224 &1481520485721663919
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7644334300092530069}
|
||||
m_GameObject: {fileID: 7967390318583634950}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6001922808625371455}
|
||||
m_Father: {fileID: 453386429374550589}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4696967337599140493
|
||||
--- !u!222 &2759775973399345411
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7644334300092530069}
|
||||
m_GameObject: {fileID: 7967390318583634950}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &3131234387202370334
|
||||
--- !u!114 &6167893425112707945
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7644334300092530069}
|
||||
m_GameObject: {fileID: 7967390318583634950}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
@@ -1938,7 +2075,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Skills
|
||||
m_text: Journal
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
@@ -2213,143 +2350,6 @@ MonoBehaviour:
|
||||
rowPrefab: {fileID: 1141587833647839303, guid: e14f68d6a57ea4945bd93c44202db910, type: 3}
|
||||
axisHeaderPrefab: {fileID: 5719341463139795832}
|
||||
displayMaxRank: 6
|
||||
--- !u!1 &8926189410052142562
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3528103284151106981}
|
||||
- component: {fileID: 8980946710928878816}
|
||||
- component: {fileID: 5867361342524513168}
|
||||
m_Layer: 0
|
||||
m_Name: Label
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3528103284151106981
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8926189410052142562}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 453386429374550589}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8980946710928878816
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8926189410052142562}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &5867361342524513168
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8926189410052142562}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Journal
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: 0
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 22
|
||||
m_fontSizeBase: 22
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 1
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &9109014941581283762
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,172 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 10
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 0
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 13
|
||||
m_BakeOnSceneLoad: 0
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 2
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 256
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRDenoiserTypeDirect: 1
|
||||
m_PVRDenoiserTypeIndirect: 1
|
||||
m_PVRDenoiserTypeAO: 1
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 1
|
||||
m_PVRFilteringGaussRadiusAO: 1
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_LightingSettings: {fileID: 0}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 3
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
buildHeightMesh: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &1325409732
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1325409734}
|
||||
- component: {fileID: 1325409733}
|
||||
m_Layer: 0
|
||||
m_Name: Bootstrap
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1325409733
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1325409732}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 612d8b8b7afa48d68f187e4d51bae0cd, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.Core.GameBootstrap
|
||||
systemsScene: Systems
|
||||
startLevel: SC101_ConferenceHall
|
||||
--- !u!4 &1325409734
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1325409732}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Roots:
|
||||
- {fileID: 1325409734}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99c9720ab356a0642a771bea13969a05
|
||||
guid: 940e7dc5e84654c9fb808956223fc11e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eaad6a890d839422a94db2c27a839bd9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55882bf97662d4abbaf3691c8c0c9b4a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67a0ad6ebebd640a59b91b85221b30df
|
||||
guid: a4910059112fe4675827519a3f55afe5
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
Binary file not shown.
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73a81211deb844562a24ef6db1dc3c46
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 23800000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,432 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 10
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 0
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 256
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRDenoiserTypeDirect: 1
|
||||
m_PVRDenoiserTypeIndirect: 1
|
||||
m_PVRDenoiserTypeAO: 1
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_LightingSettings: {fileID: 0}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 3
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
buildHeightMesh: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &330585543
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 330585546}
|
||||
- component: {fileID: 330585545}
|
||||
- component: {fileID: 330585544}
|
||||
- component: {fileID: 330585547}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &330585544
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 330585543}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &330585545
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 330585543}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_Iso: 200
|
||||
m_ShutterSpeed: 0.005
|
||||
m_Aperture: 16
|
||||
m_FocusDistance: 10
|
||||
m_FocalLength: 50
|
||||
m_BladeCount: 5
|
||||
m_Curvature: {x: 2, y: 11}
|
||||
m_BarrelClipping: 0.25
|
||||
m_Anamorphism: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &330585546
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 330585543}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &330585547
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 330585543}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_RenderShadows: 1
|
||||
m_RequiresDepthTextureOption: 2
|
||||
m_RequiresOpaqueTextureOption: 2
|
||||
m_CameraType: 0
|
||||
m_Cameras: []
|
||||
m_RendererIndex: -1
|
||||
m_VolumeLayerMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 1
|
||||
m_VolumeTrigger: {fileID: 0}
|
||||
m_VolumeFrameworkUpdateModeOption: 2
|
||||
m_RenderPostProcessing: 1
|
||||
m_Antialiasing: 0
|
||||
m_AntialiasingQuality: 2
|
||||
m_StopNaN: 0
|
||||
m_Dithering: 0
|
||||
m_ClearDepth: 1
|
||||
m_AllowXRRendering: 1
|
||||
m_AllowHDROutput: 1
|
||||
m_UseScreenCoordOverride: 0
|
||||
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_RequiresDepthTexture: 0
|
||||
m_RequiresColorTexture: 0
|
||||
m_Version: 2
|
||||
m_TaaSettings:
|
||||
quality: 3
|
||||
frameInfluence: 0.1
|
||||
jitterScale: 1
|
||||
mipBias: 0
|
||||
varianceClampScale: 0.9
|
||||
contrastAdaptiveSharpening: 0
|
||||
--- !u!1 &410087039
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 410087041}
|
||||
- component: {fileID: 410087040}
|
||||
- component: {fileID: 410087042}
|
||||
m_Layer: 0
|
||||
m_Name: Directional Light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!108 &410087040
|
||||
Light:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 410087039}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 11
|
||||
m_Type: 1
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Intensity: 2
|
||||
m_Range: 10
|
||||
m_SpotAngle: 30
|
||||
m_InnerSpotAngle: 21.80208
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 2
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_CullingMatrixOverride:
|
||||
e00: 1
|
||||
e01: 0
|
||||
e02: 0
|
||||
e03: 0
|
||||
e10: 0
|
||||
e11: 1
|
||||
e12: 0
|
||||
e13: 0
|
||||
e20: 0
|
||||
e21: 0
|
||||
e22: 1
|
||||
e23: 0
|
||||
e30: 0
|
||||
e31: 0
|
||||
e32: 0
|
||||
e33: 1
|
||||
m_UseCullingMatrixOverride: 0
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingLayerMask: 1
|
||||
m_Lightmapping: 4
|
||||
m_LightShadowCasterMode: 0
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 1
|
||||
m_ColorTemperature: 5000
|
||||
m_UseColorTemperature: 1
|
||||
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_UseBoundingSphereOverride: 0
|
||||
m_UseViewFrustumForShadowCasterCull: 1
|
||||
m_ForceVisible: 0
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
--- !u!4 &410087041
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 410087039}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
|
||||
m_LocalPosition: {x: 0, y: 3, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
||||
--- !u!114 &410087042
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 410087039}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Version: 3
|
||||
m_UsePipelineSettings: 1
|
||||
m_AdditionalLightsShadowResolutionTier: 2
|
||||
m_LightLayerMask: 1
|
||||
m_RenderingLayers: 1
|
||||
m_CustomShadowLayers: 0
|
||||
m_ShadowLayerMask: 1
|
||||
m_ShadowRenderingLayers: 1
|
||||
m_LightCookieSize: {x: 1, y: 1}
|
||||
m_LightCookieOffset: {x: 0, y: 0}
|
||||
m_SoftShadowQuality: 1
|
||||
--- !u!1 &832575517
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 832575519}
|
||||
- component: {fileID: 832575518}
|
||||
m_Layer: 0
|
||||
m_Name: Global Volume
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &832575518
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 832575517}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IsGlobal: 1
|
||||
priority: 0
|
||||
blendDistance: 0
|
||||
weight: 1
|
||||
sharedProfile: {fileID: 11400000, guid: 10fc4df2da32a41aaa32d77bc913491c, type: 2}
|
||||
--- !u!4 &832575519
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 832575517}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Roots:
|
||||
- {fileID: 330585546}
|
||||
- {fileID: 410087041}
|
||||
- {fileID: 832575519}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7fa9631487c347788c76d7f8eac9692
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1fc9f8ca900943ce9f61d41d56bc763
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Collections;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
using NightclubArcadia.Core;
|
||||
|
||||
namespace NightclubArcadia.Cinematics
|
||||
{
|
||||
/// <summary>
|
||||
/// Points a CinemachineCamera at the player once the player exists.
|
||||
///
|
||||
/// Level cameras — the reveal cameras in particular — used to hold a serialized
|
||||
/// reference to the PlayerArmature. The player now lives in the Systems scene, so
|
||||
/// that reference cannot be serialized any more and has to be bound at runtime.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(CinemachineCamera))]
|
||||
public sealed class CinemachineFollowsPlayer : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Also drive LookAt, not just Follow.")]
|
||||
[SerializeField] bool alsoLookAt;
|
||||
|
||||
[Tooltip("Seconds to keep retrying while the Systems scene finishes loading.")]
|
||||
[SerializeField] float resolveTimeout = 5f;
|
||||
|
||||
IEnumerator Start()
|
||||
{
|
||||
var cam = GetComponent<CinemachineCamera>();
|
||||
var deadline = Time.unscaledTime + resolveTimeout;
|
||||
|
||||
while (SceneServices.Player == null && Time.unscaledTime < deadline)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
var player = SceneServices.Player;
|
||||
if (player == null)
|
||||
{
|
||||
Debug.LogError($"[CinemachineFollowsPlayer] {name}: no object tagged Player appeared " +
|
||||
$"within {resolveTimeout}s.", this);
|
||||
yield break;
|
||||
}
|
||||
|
||||
cam.Follow = player;
|
||||
if (alsoLookAt)
|
||||
{
|
||||
cam.LookAt = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cc7a0e83be949f5974b1f675c37c84e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a917e0f38654c5d9c73026e20ad3e16
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace NightclubArcadia.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry point. Loads the persistent Systems scene, then a level, additively.
|
||||
///
|
||||
/// Splitting the game across scenes is what lets a level be edited without touching
|
||||
/// the systems wiring, and stops a corrupted level from taking the dialogue runner,
|
||||
/// the UI layer and the player with it. The cost is that serialized references
|
||||
/// cannot cross a scene boundary — Unity nulls those — so the handful of level
|
||||
/// objects that need a system resolve it at runtime instead. See SceneServices.
|
||||
/// </summary>
|
||||
public sealed class GameBootstrap : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Persistent scene holding dialogue, skills, UI, the camera rig and the player.")]
|
||||
[SerializeField] string systemsScene = "Systems";
|
||||
|
||||
[Tooltip("Level to open on start. Leave empty to load only the systems layer.")]
|
||||
[SerializeField] string startLevel = "SC101_ConferenceHall";
|
||||
|
||||
IEnumerator Start()
|
||||
{
|
||||
yield return LoadIfNeeded(systemsScene);
|
||||
|
||||
if (!string.IsNullOrEmpty(startLevel))
|
||||
{
|
||||
yield return LoadIfNeeded(startLevel);
|
||||
|
||||
var level = SceneManager.GetSceneByName(startLevel);
|
||||
if (level.IsValid() && level.isLoaded)
|
||||
{
|
||||
// The active scene decides where new objects land and which
|
||||
// lighting settings apply, so it must be the level, not this one.
|
||||
SceneManager.SetActiveScene(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerator LoadIfNeeded(string sceneName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sceneName))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
var existing = SceneManager.GetSceneByName(sceneName);
|
||||
if (existing.IsValid() && existing.isLoaded)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
var op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
|
||||
if (op == null)
|
||||
{
|
||||
Debug.LogError($"[GameBootstrap] '{sceneName}' is not in the build settings.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 612d8b8b7afa48d68f187e4d51bae0cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
|
||||
namespace NightclubArcadia.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Which input device was most recently active, globally.
|
||||
///
|
||||
/// InteractionPrompt — and anything else that shows a button glyph — reads Current
|
||||
/// to decide between "[F]", "(X)" and "(✕)".
|
||||
///
|
||||
/// Requires the Input System package, with Active Input Handling set to
|
||||
/// "Input System Package (New)" or "Both".
|
||||
/// </summary>
|
||||
public static class InputDeviceTracker
|
||||
{
|
||||
public enum DeviceType { Keyboard, Xbox, PlayStation, Generic }
|
||||
|
||||
public static DeviceType Current { get; private set; } = DeviceType.Keyboard;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
static void Init()
|
||||
{
|
||||
InputSystem.onEvent += OnEvent;
|
||||
}
|
||||
|
||||
static void OnEvent(InputEventPtr eventPtr, InputDevice device)
|
||||
{
|
||||
// Only actual state changes — button, stick, key — not every event.
|
||||
if (!eventPtr.IsA<StateEvent>() && !eventPtr.IsA<DeltaStateEvent>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case Keyboard:
|
||||
case Mouse:
|
||||
Current = DeviceType.Keyboard;
|
||||
break;
|
||||
|
||||
case Gamepad pad:
|
||||
var name = pad.displayName.ToLowerInvariant();
|
||||
if (name.Contains("dualshock") || name.Contains("dualsense") || name.Contains("playstation"))
|
||||
{
|
||||
Current = DeviceType.PlayStation;
|
||||
}
|
||||
else if (name.Contains("xbox") || name.Contains("xinput"))
|
||||
{
|
||||
Current = DeviceType.Xbox;
|
||||
}
|
||||
else
|
||||
{
|
||||
Current = DeviceType.Generic;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "NightclubArcadia.Core",
|
||||
"rootNamespace": "NightclubArcadia.Core",
|
||||
"references": [
|
||||
"Unity.InputSystem"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a610a410f5944dca5c7961fee29bdff
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,79 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds objects that live in a different loaded scene.
|
||||
///
|
||||
/// Unity cannot serialize a reference across a scene boundary — the Inspector
|
||||
/// refuses it and any existing reference is nulled when the scenes are split. So a
|
||||
/// level object that needs the dialogue runner, or the player, has to resolve it at
|
||||
/// runtime. This is a lookup helper, not a service container: there is no
|
||||
/// registration step and nothing to keep in sync.
|
||||
///
|
||||
/// It is deliberately thin. FindFirstObjectByType is not cheap, so callers cache
|
||||
/// what they get in Awake rather than calling per frame, and an Inspector-assigned
|
||||
/// reference always wins — this only fills in what the split left null.
|
||||
/// </summary>
|
||||
public static class SceneServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Inspector value if set, otherwise the first one in any loaded scene. Silent:
|
||||
/// returns null when nothing is found.
|
||||
///
|
||||
/// Use this when the answer may legitimately not exist yet — during Awake, for
|
||||
/// instance, when the scene holding it may not have loaded.
|
||||
/// </summary>
|
||||
public static T TryResolve<T>(T assigned) where T : Object
|
||||
{
|
||||
if (assigned != null)
|
||||
{
|
||||
return assigned;
|
||||
}
|
||||
|
||||
// Include inactive: a system parked inactive at startup is still the object
|
||||
// we mean, and excluding it produces a confusing "not found" for something
|
||||
// sitting right there in the hierarchy.
|
||||
return Object.FindFirstObjectByType<T>(FindObjectsInactive.Include);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// As TryResolve, but logs an error when nothing is found. Only call this at the
|
||||
/// point the dependency is actually needed — calling it during Awake reports a
|
||||
/// failure that may simply be a scene that has not finished loading.
|
||||
/// </summary>
|
||||
public static T Resolve<T>(T assigned, Object context, string field) where T : Object
|
||||
{
|
||||
var found = TryResolve(assigned);
|
||||
if (found == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"[SceneServices] {context?.name}: could not resolve {field} ({typeof(T).Name}). " +
|
||||
"Is the Systems scene loaded?", context);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
static Transform player;
|
||||
|
||||
/// <summary>
|
||||
/// The player transform, by tag, cached. Null between scene loads if the
|
||||
/// systems scene has not come up yet, so callers must handle null.
|
||||
/// </summary>
|
||||
public static Transform Player
|
||||
{
|
||||
get
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
var go = GameObject.FindGameObjectWithTag("Player");
|
||||
player = go != null ? go.transform : null;
|
||||
}
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Drop the cache. Call when unloading a scene that held the player.</summary>
|
||||
public static void Forget() => player = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db6a827f17574ac1b7c92185a089300a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,69 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace NightclubArcadia.Dialogue
|
||||
{
|
||||
/// <summary>
|
||||
/// Trigger-zone interactable: player walks in range, presses E, and this
|
||||
/// starts the given Yarn node. The reverse of DialogueTransitionController's
|
||||
/// <<enter_environment>> — this is the "step into dialogue" half of the loop.
|
||||
/// </summary>
|
||||
public class DialogueInteractable : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private DialogueRunner dialogueRunner;
|
||||
[SerializeField] private GameObject dialogueUI;
|
||||
[SerializeField] private string yarnNodeName = "Bartender_Chat";
|
||||
|
||||
private bool playerInRange;
|
||||
private InputAction interactAction;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
interactAction = new InputAction("Interact");
|
||||
interactAction.AddBinding("<Keyboard>/e");
|
||||
interactAction.AddBinding("<Gamepad>/buttonNorth");
|
||||
interactAction.performed += _ =>
|
||||
{
|
||||
if (playerInRange)
|
||||
{
|
||||
StartConversation();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void OnEnable() => interactAction?.Enable();
|
||||
void OnDisable() => interactAction?.Disable();
|
||||
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
playerInRange = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
playerInRange = false;
|
||||
}
|
||||
}
|
||||
|
||||
async void StartConversation()
|
||||
{
|
||||
// Player controls are locked by DialogueTransitionController off the
|
||||
// runner's onDialogueStart event — nothing to do for that here.
|
||||
if (DialogueUIVisibility.Show(dialogueUI))
|
||||
{
|
||||
// Only reached if the UI was found deactivated; give TMP a
|
||||
// frame to re-cache its Canvas in OnEnable before any text is
|
||||
// generated.
|
||||
await Awaitable.NextFrameAsync();
|
||||
}
|
||||
|
||||
await dialogueRunner.StartDialogue(yarnNodeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99afbbd28c8054d59a7a0dec94f5ec8f
|
||||
@@ -11,7 +11,7 @@ namespace NightclubArcadia.Dialogue
|
||||
///
|
||||
/// The lock is driven by the DialogueRunner's own lifecycle events rather
|
||||
/// than by each interactable, so every entry point — auto-started nodes,
|
||||
/// NPCStandIn, DialogueInteractable — gets the same behaviour without
|
||||
/// DialogueInteractor — gets the same behaviour without
|
||||
/// having to remember to do it. Control locking is delegated to
|
||||
/// <see cref="PlayerControlLock"/> so the player menu can hold a second
|
||||
/// independent lock without re-enabling movement mid-conversation.
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace NightclubArcadia.Dialogue
|
||||
/// <summary>
|
||||
/// Shows and hides the dialogue UI *without* deactivating its GameObject.
|
||||
/// Forwards to <see cref="PanelVisibility"/> — kept as a thin wrapper so
|
||||
/// existing call sites (NPCStandIn, DialogueInteractable,
|
||||
/// existing call sites (DialogueInteractor,
|
||||
/// DialogueTransitionController) continue to compile unchanged.
|
||||
/// </summary>
|
||||
public static class DialogueUIVisibility
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapts NPCStandIn to the click-to-interact pipeline without modifying
|
||||
/// the existing proximity + keypress path.
|
||||
/// </summary>
|
||||
public sealed class ClickInteractableBridge : MonoBehaviour, IClickInteractable
|
||||
{
|
||||
[SerializeField] NPCStandIn npc;
|
||||
|
||||
public Transform ApproachPoint => transform;
|
||||
public float ApproachRadius => npc != null ? Mathf.Max(0.15f, npc.interactionRange - 0.5f) : 0.15f;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (npc == null)
|
||||
{
|
||||
npc = GetComponent<NPCStandIn>();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnApproached()
|
||||
{
|
||||
npc?.Interact();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5257f07d188de44eb9a04ba4d3a65fec
|
||||
@@ -0,0 +1,170 @@
|
||||
using NightclubArcadia.Core;
|
||||
using NightclubArcadia.Dialogue;
|
||||
using NightclubArcadia.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace NightclubArcadia.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// Anything the player can walk up to and talk to: a character, or an object with
|
||||
/// something to say.
|
||||
///
|
||||
/// Replaces NPCStandIn, which was written to be dropped on a sphere primitive and
|
||||
/// carried its identity in per-instance public fields. Two objects could claim the
|
||||
/// same character and disagree, and in practice did — the scene's second "Bartender"
|
||||
/// was the chair, renamed in the data but not in the hierarchy.
|
||||
///
|
||||
/// Identity now comes from an InteractableDefinition asset, so a prefab is the thing
|
||||
/// and the scene only places it. Also replaces DialogueInteractable, a trigger-zone
|
||||
/// variant of the same idea that was in no scene at all.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SphereCollider))]
|
||||
public sealed class DialogueInteractor : MonoBehaviour, IClickInteractable
|
||||
{
|
||||
[Header("Identity")]
|
||||
[SerializeField] InteractableDefinition definition;
|
||||
|
||||
[Header("Presentation (optional)")]
|
||||
[SerializeField] WorldSpaceLabel label;
|
||||
[SerializeField] InteractionPrompt prompt;
|
||||
|
||||
[Header("Overrides")]
|
||||
[Tooltip("Leave empty to use the Canvas under the DialogueRunner.")]
|
||||
[SerializeField] GameObject dialogueUI;
|
||||
|
||||
DialogueRunner runner;
|
||||
Transform player;
|
||||
InputAction interact;
|
||||
bool playerInRange;
|
||||
|
||||
public Transform ApproachPoint => transform;
|
||||
|
||||
public float ApproachRadius =>
|
||||
definition != null ? Mathf.Max(0.15f, definition.InteractionRange - 0.5f) : 0.15f;
|
||||
|
||||
/// <summary>
|
||||
/// The dialogue runner, resolved on demand and cached only on success.
|
||||
///
|
||||
/// Never resolved once in Awake: the runner lives in the Systems scene and this
|
||||
/// object lives in a level, so it can wake up before the runner exists. Caching a
|
||||
/// failure there left NPCs permanently mute for the session. See SceneOrderTests.
|
||||
/// </summary>
|
||||
public DialogueRunner ResolvedRunner =>
|
||||
runner != null ? runner : runner = SceneServices.TryResolve<DialogueRunner>(null);
|
||||
|
||||
Transform Player =>
|
||||
player != null ? player : player = SceneServices.Player;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (definition == null)
|
||||
{
|
||||
Debug.LogError($"[Interactor] {name} has no InteractableDefinition; it will do nothing.", this);
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
GetComponent<SphereCollider>().isTrigger = false;
|
||||
|
||||
if (label != null)
|
||||
{
|
||||
label.gameObject.SetActive(definition.ShowLabel);
|
||||
label.SetText(definition.DisplayName);
|
||||
}
|
||||
|
||||
prompt?.SetShown(false);
|
||||
|
||||
interact = new InputAction("Interact");
|
||||
interact.AddBinding("<Keyboard>/f");
|
||||
interact.AddBinding("<Gamepad>/buttonSouth");
|
||||
interact.performed += _ =>
|
||||
{
|
||||
if (playerInRange)
|
||||
{
|
||||
Interact();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void OnEnable() => interact?.Enable();
|
||||
|
||||
void OnDisable() => interact?.Disable();
|
||||
|
||||
void Update()
|
||||
{
|
||||
var target = Player;
|
||||
if (target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inRange = Vector3.Distance(transform.position, target.position) <= definition.InteractionRange;
|
||||
if (inRange == playerInRange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
playerInRange = inRange;
|
||||
prompt?.SetShown(inRange);
|
||||
}
|
||||
|
||||
/// <summary>Entry point for both the proximity keypress and click-to-move arrival.</summary>
|
||||
public void Interact()
|
||||
{
|
||||
var dialogue = ResolvedRunner;
|
||||
if (dialogue == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"[Interactor] {definition.DisplayName}: no DialogueRunner in any loaded scene. " +
|
||||
"It lives in Systems.unity — open Bootstrap, or Tools → Nightclub Arcadia → " +
|
||||
"Open Game Scenes.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (UIStateController.Instance != null && UIStateController.Instance.IsMenuOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dialogue.IsDialogueRunning)
|
||||
{
|
||||
StartDialogueAsync(dialogue);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnApproached() => Interact();
|
||||
|
||||
async void StartDialogueAsync(DialogueRunner dialogue)
|
||||
{
|
||||
// The dialogue UI is hidden when the player leaves a conversation via
|
||||
// <<enter_environment>>. Make it visible again before the first line renders.
|
||||
if (DialogueUIVisibility.Show(ResolveDialogueUI(dialogue)))
|
||||
{
|
||||
// Only reached if the UI was found deactivated; give TMP a frame to
|
||||
// re-cache its Canvas in OnEnable before any text is generated.
|
||||
await Awaitable.NextFrameAsync();
|
||||
}
|
||||
|
||||
await dialogue.StartDialogue(definition.YarnNode);
|
||||
}
|
||||
|
||||
GameObject ResolveDialogueUI(DialogueRunner dialogue)
|
||||
{
|
||||
if (dialogueUI != null)
|
||||
{
|
||||
return dialogueUI;
|
||||
}
|
||||
|
||||
var canvas = dialogue.GetComponentInChildren<Canvas>(true);
|
||||
if (canvas == null)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
$"[Interactor] No Canvas under {dialogue.name} for {definition.DisplayName}", this);
|
||||
return null;
|
||||
}
|
||||
return canvas.gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba3ce042c3b3457ba101f1c6643b983f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// What a thing in the world is called and which conversation it starts.
|
||||
///
|
||||
/// This replaces a set of public fields edited per scene object. The scaffold it
|
||||
/// grew out of had the name, colour, yarn node, ranges and font sizes all set on
|
||||
/// each sphere by hand, which meant two objects claiming to be the same character
|
||||
/// could disagree, and nothing outside the scene could see what existed.
|
||||
///
|
||||
/// Generated from Assets/Characters/characters.json — edit the JSON, not the asset.
|
||||
/// Hand edits are overwritten, the same contract as Skills and Candidates.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Nightclub Arcadia/Interactable Definition", order = 30)]
|
||||
public sealed class InteractableDefinition : ScriptableObject
|
||||
{
|
||||
[SerializeField] string id;
|
||||
[SerializeField] string displayName;
|
||||
[SerializeField] string yarnNode;
|
||||
[SerializeField] float interactionRange = 3f;
|
||||
|
||||
[Tooltip("Shown as a floating label. Off for scenery that should not announce itself.")]
|
||||
[SerializeField] bool showLabel = true;
|
||||
|
||||
public string Id => id;
|
||||
public string DisplayName => displayName;
|
||||
public string YarnNode => yarnNode;
|
||||
public float InteractionRange => interactionRange;
|
||||
public bool ShowLabel => showLabel;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>Editor-only, for the generator. Not part of the runtime surface.</summary>
|
||||
public void EditorSet(string newId, string newDisplayName, string newYarnNode,
|
||||
float newRange, bool newShowLabel)
|
||||
{
|
||||
id = newId;
|
||||
displayName = newDisplayName;
|
||||
yarnNode = newYarnNode;
|
||||
interactionRange = newRange;
|
||||
showLabel = newShowLabel;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f4df63859ea4e39910d900aa7a5510a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using NightclubArcadia.Core;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// The "[F]" that appears when the player is close enough to interact, showing the
|
||||
/// glyph for whichever input device was last used.
|
||||
///
|
||||
/// Separated from the interactor so the prompt can be positioned and styled in a
|
||||
/// prefab rather than constructed in code, and so anything else that needs a
|
||||
/// proximity prompt can reuse it.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(TextMeshPro))]
|
||||
public sealed class InteractionPrompt : MonoBehaviour
|
||||
{
|
||||
TextMeshPro text;
|
||||
bool shown;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
text = GetComponent<TextMeshPro>();
|
||||
SetShown(false);
|
||||
}
|
||||
|
||||
public void SetShown(bool value)
|
||||
{
|
||||
shown = value;
|
||||
if (text != null)
|
||||
{
|
||||
text.enabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (shown && text != null)
|
||||
{
|
||||
text.text = GlyphFor(InputDeviceTracker.Current);
|
||||
}
|
||||
}
|
||||
|
||||
static string GlyphFor(InputDeviceTracker.DeviceType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case InputDeviceTracker.DeviceType.Xbox: return "(X)";
|
||||
case InputDeviceTracker.DeviceType.PlayStation: return "(✕)";
|
||||
default: return "[F]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10b4e7c1069944b49acca9287528f275
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NightclubArcadia.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// A floating text label that turns to face the camera.
|
||||
///
|
||||
/// Lifted out of NPCStandIn, which created its label in Awake and billboarded it in
|
||||
/// LateUpdate. That worked, but it meant the text only existed at runtime and could
|
||||
/// not be seen or positioned in the Editor. This is a normal component on a normal
|
||||
/// child object, so a prefab can show what it will look like.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(TextMeshPro))]
|
||||
public sealed class WorldSpaceLabel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] bool billboard = true;
|
||||
|
||||
TextMeshPro text;
|
||||
Camera view;
|
||||
|
||||
void Awake() => text = GetComponent<TextMeshPro>();
|
||||
|
||||
public void SetText(string value)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
text = GetComponent<TextMeshPro>();
|
||||
}
|
||||
text.text = value;
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (!billboard)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Camera.main is a tagged lookup; cache it, but re-acquire if the camera was
|
||||
// destroyed with a scene, which happens when the Systems scene reloads.
|
||||
if (view == null)
|
||||
{
|
||||
view = Camera.main;
|
||||
if (view == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
transform.rotation = Quaternion.LookRotation(transform.position - view.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d24ca2949394cc78a1fdde5d83e08c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,48 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks which input device was most recently active, globally, across the whole game.
|
||||
/// NPCStandIn (and any other UI that shows button prompts) reads InputDeviceTracker.Current
|
||||
/// to decide whether to show "[F]", "(X)", "(✕)", etc.
|
||||
/// Requires the Input System package (Window > Package Manager > Input System),
|
||||
/// and Project Settings > Player > Active Input Handling set to
|
||||
/// "Input System Package (New)" or "Both".
|
||||
/// </summary>
|
||||
public static class InputDeviceTracker
|
||||
{
|
||||
public enum DeviceType { Keyboard, Xbox, PlayStation, Generic }
|
||||
|
||||
public static DeviceType Current { get; private set; } = DeviceType.Keyboard;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
static void Init()
|
||||
{
|
||||
InputSystem.onEvent += OnEvent;
|
||||
}
|
||||
|
||||
static void OnEvent(InputEventPtr eventPtr, InputDevice device)
|
||||
{
|
||||
// Only care about actual state changes (button/stick/key presses), not noise.
|
||||
if (!eventPtr.IsA<StateEvent>() && !eventPtr.IsA<DeltaStateEvent>()) return;
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case Keyboard:
|
||||
case Mouse:
|
||||
Current = DeviceType.Keyboard;
|
||||
break;
|
||||
|
||||
case Gamepad gp:
|
||||
string n = gp.displayName.ToLowerInvariant();
|
||||
if (n.Contains("dualshock") || n.Contains("dualsense") || n.Contains("playstation"))
|
||||
Current = DeviceType.PlayStation;
|
||||
else if (n.Contains("xbox") || n.Contains("xinput"))
|
||||
Current = DeviceType.Xbox;
|
||||
else
|
||||
Current = DeviceType.Generic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using TMPro;
|
||||
using Yarn.Unity;
|
||||
using NightclubArcadia.Dialogue;
|
||||
using NightclubArcadia.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Drop this on a sphere primitive to use it as a placeholder NPC:
|
||||
/// - Sets sphere color per-instance
|
||||
/// - Spawns a floating TextMeshPro name label that billboards to face the camera
|
||||
/// - Shows a proximity interaction prompt ("[F]", "(X)", "(✕)") that swaps based on
|
||||
/// the last input device used, via InputDeviceTracker
|
||||
/// - Press the interact button while in range to start a Yarn Spinner dialogue node
|
||||
/// Requires: TextMeshPro Essentials imported, Input System package installed,
|
||||
/// InputDeviceTracker.cs in the project, and a "Player" tag on your player object
|
||||
/// (or assign the Player field manually in the Inspector).
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SphereCollider))]
|
||||
public class NPCStandIn : MonoBehaviour
|
||||
{
|
||||
[Header("Identity")]
|
||||
public string npcName = "Unnamed NPC";
|
||||
public Color npcColor = Color.white;
|
||||
|
||||
[Header("Dialogue")]
|
||||
public DialogueRunner dialogueRunner;
|
||||
public string yarnStartNode = "Start";
|
||||
|
||||
[Tooltip("Optional. Left empty, the Canvas under the DialogueRunner is used.")]
|
||||
public GameObject dialogueUI;
|
||||
|
||||
[Header("Label")]
|
||||
public float labelHeight = 1.2f;
|
||||
public float labelFontSize = 4f;
|
||||
public Color labelColor = Color.white;
|
||||
|
||||
[Header("Interaction Prompt")]
|
||||
public Transform player; // auto-found by "Player" tag if left empty
|
||||
public float interactionRange = 3f;
|
||||
public float promptHeight = 0.7f;
|
||||
public float promptFontSize = 3f;
|
||||
|
||||
private TextMeshPro labelText;
|
||||
private TextMeshPro promptText;
|
||||
private Renderer rend;
|
||||
private Camera mainCam;
|
||||
private InputAction interactAction;
|
||||
private bool playerInRange;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
rend = GetComponent<Renderer>();
|
||||
rend.material.color = npcColor;
|
||||
|
||||
mainCam = Camera.main;
|
||||
|
||||
if (player == null)
|
||||
{
|
||||
GameObject found = GameObject.FindGameObjectWithTag("Player");
|
||||
if (found != null) player = found.transform;
|
||||
}
|
||||
|
||||
CreateLabel();
|
||||
CreatePrompt();
|
||||
|
||||
interactAction = new InputAction("Interact");
|
||||
interactAction.AddBinding("<Keyboard>/f");
|
||||
interactAction.AddBinding("<Gamepad>/buttonSouth");
|
||||
interactAction.performed += ctx =>
|
||||
{
|
||||
if (playerInRange) Interact();
|
||||
};
|
||||
}
|
||||
|
||||
void OnEnable() => interactAction?.Enable();
|
||||
void OnDisable() => interactAction?.Disable();
|
||||
|
||||
void CreateLabel()
|
||||
{
|
||||
GameObject labelObj = new GameObject($"{npcName}_Label");
|
||||
labelObj.transform.SetParent(transform);
|
||||
labelObj.transform.localPosition = Vector3.up * labelHeight;
|
||||
|
||||
labelText = labelObj.AddComponent<TextMeshPro>();
|
||||
labelText.text = npcName;
|
||||
labelText.fontSize = labelFontSize;
|
||||
labelText.color = labelColor;
|
||||
labelText.alignment = TextAlignmentOptions.Center;
|
||||
labelText.rectTransform.sizeDelta = new Vector2(2f, 0.5f);
|
||||
}
|
||||
|
||||
void CreatePrompt()
|
||||
{
|
||||
GameObject promptObj = new GameObject($"{npcName}_Prompt");
|
||||
promptObj.transform.SetParent(transform);
|
||||
promptObj.transform.localPosition = Vector3.up * promptHeight;
|
||||
|
||||
promptText = promptObj.AddComponent<TextMeshPro>();
|
||||
promptText.fontSize = promptFontSize;
|
||||
promptText.color = Color.yellow;
|
||||
promptText.alignment = TextAlignmentOptions.Center;
|
||||
promptText.rectTransform.sizeDelta = new Vector2(1.5f, 0.4f);
|
||||
promptObj.SetActive(false); // hidden until player is in range
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
float dist = Vector3.Distance(transform.position, player.position);
|
||||
bool inRangeNow = dist <= interactionRange;
|
||||
|
||||
if (inRangeNow != playerInRange)
|
||||
{
|
||||
playerInRange = inRangeNow;
|
||||
promptText.gameObject.SetActive(playerInRange);
|
||||
}
|
||||
|
||||
if (playerInRange)
|
||||
{
|
||||
promptText.text = GlyphFor(InputDeviceTracker.Current);
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (mainCam == null) return;
|
||||
|
||||
if (labelText != null)
|
||||
labelText.transform.rotation = Quaternion.LookRotation(
|
||||
labelText.transform.position - mainCam.transform.position);
|
||||
|
||||
if (promptText != null)
|
||||
promptText.transform.rotation = Quaternion.LookRotation(
|
||||
promptText.transform.position - mainCam.transform.position);
|
||||
}
|
||||
|
||||
static string GlyphFor(InputDeviceTracker.DeviceType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case InputDeviceTracker.DeviceType.Xbox: return "(X)";
|
||||
case InputDeviceTracker.DeviceType.PlayStation: return "(\u2715)"; // Cross button
|
||||
default: return "[F]";
|
||||
}
|
||||
}
|
||||
|
||||
public void Interact()
|
||||
{
|
||||
if (dialogueRunner == null)
|
||||
{
|
||||
Debug.LogWarning($"[NPCStandIn] No DialogueRunner assigned on {npcName}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (UIStateController.Instance != null && UIStateController.Instance.IsMenuOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dialogueRunner.IsDialogueRunning)
|
||||
{
|
||||
StartDialogueAsync();
|
||||
}
|
||||
}
|
||||
|
||||
async void StartDialogueAsync()
|
||||
{
|
||||
// The dialogue UI is hidden when the player leaves a conversation via
|
||||
// <<enter_environment>>. Make it visible again before the runner
|
||||
// renders its first line.
|
||||
if (DialogueUIVisibility.Show(ResolveDialogueUI()))
|
||||
{
|
||||
// Only reached if the UI was found deactivated; give TMP a frame
|
||||
// to re-cache its Canvas in OnEnable before any text is generated.
|
||||
await Awaitable.NextFrameAsync();
|
||||
}
|
||||
|
||||
await dialogueRunner.StartDialogue(yarnStartNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Canvas under the DialogueRunner, unless one was assigned explicitly.
|
||||
/// Resolved at call time (including inactive children) so this works
|
||||
/// without any per-NPC Inspector wiring.
|
||||
/// </summary>
|
||||
GameObject ResolveDialogueUI()
|
||||
{
|
||||
if (dialogueUI != null)
|
||||
{
|
||||
return dialogueUI;
|
||||
}
|
||||
|
||||
var canvas = dialogueRunner.GetComponentInChildren<Canvas>(true);
|
||||
if (canvas == null)
|
||||
{
|
||||
Debug.LogWarning($"[NPCStandIn] No Canvas found under {dialogueRunner.name} for {npcName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
dialogueUI = canvas.gameObject;
|
||||
return dialogueUI;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23d0ac85377c640a1900cfd13e89c389
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "NightclubArcadia.Game",
|
||||
"rootNamespace": "NightclubArcadia",
|
||||
"references": [
|
||||
"NightclubArcadia.Core",
|
||||
"NightclubArcadia.Skills",
|
||||
"NightclubArcadia.Locomotion.Math",
|
||||
"StarterAssets",
|
||||
"YarnSpinner.Unity",
|
||||
"Unity.Cinemachine",
|
||||
"Unity.InputSystem",
|
||||
"Unity.AI.Navigation",
|
||||
"Unity.TextMeshPro",
|
||||
"UnityEngine.UI"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d49f74ccc8b4e41aeb2d51faf439392
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -111,6 +111,12 @@ namespace NightclubArcadia.Player
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!agent.isOnNavMesh)
|
||||
{
|
||||
pendingInteractable = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
agent.stoppingDistance = 0.15f;
|
||||
agent.isStopped = false;
|
||||
agent.SetDestination(hit.position);
|
||||
@@ -136,6 +142,12 @@ namespace NightclubArcadia.Player
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!agent.isOnNavMesh)
|
||||
{
|
||||
pendingInteractable = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
agent.stoppingDistance = Mathf.Max(0.15f, interactable.ApproachRadius);
|
||||
agent.isStopped = false;
|
||||
agent.SetDestination(hit.position);
|
||||
@@ -147,7 +159,11 @@ namespace NightclubArcadia.Player
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
if (agent != null)
|
||||
// isOnNavMesh, not just a null check: the agent lives in the Systems scene
|
||||
// and the NavMesh is baked into the level, so between those two scenes
|
||||
// loading there is a window where the agent exists but is not on a mesh.
|
||||
// ResetPath and isStopped both log an error in that state.
|
||||
if (agent != null && agent.isOnNavMesh)
|
||||
{
|
||||
agent.ResetPath();
|
||||
agent.isStopped = true;
|
||||
|
||||
@@ -198,10 +198,8 @@ namespace NightclubArcadia.UI
|
||||
SetPrivate(transition, "dialogueUI", canvasGo);
|
||||
}
|
||||
|
||||
foreach (var npc in FindObjectsByType<NPCStandIn>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||
{
|
||||
npc.dialogueUI = canvasGo;
|
||||
}
|
||||
// Interactors used to be pushed this canvas here. DialogueInteractor resolves
|
||||
// it from the runner at the point of use instead, so there is nothing to push.
|
||||
}
|
||||
|
||||
DialogueMessageRow BuildMessageRowPrefab(Transform parent)
|
||||
|
||||
@@ -342,6 +342,9 @@ MonoBehaviour:
|
||||
skyOcclusionIntensityMultiplier:
|
||||
m_OverrideState: 1
|
||||
m_Value: 1
|
||||
worldOffset:
|
||||
m_OverrideState: 1
|
||||
m_Value: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &-1216621516061285780
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 3
|
||||
@@ -376,6 +379,9 @@ MonoBehaviour:
|
||||
highQualityFiltering:
|
||||
m_OverrideState: 1
|
||||
m_Value: 0
|
||||
filter:
|
||||
m_OverrideState: 1
|
||||
m_Value: 0
|
||||
downscale:
|
||||
m_OverrideState: 1
|
||||
m_Value: 0
|
||||
@@ -462,8 +468,6 @@ MonoBehaviour:
|
||||
- {fileID: -6288072647309666549}
|
||||
- {fileID: 7518938298396184218}
|
||||
- {fileID: -1410297666881709256}
|
||||
- {fileID: -7750755424749557576}
|
||||
- {fileID: -5139089513906902183}
|
||||
--- !u!114 &853819529557874667
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 3
|
||||
|
||||
@@ -100,16 +100,16 @@ MonoBehaviour:
|
||||
m_Keys: []
|
||||
m_Values:
|
||||
m_PrefilteringModeMainLightShadows: 3
|
||||
m_PrefilteringModeAdditionalLight: 4
|
||||
m_PrefilteringModeAdditionalLightShadows: 0
|
||||
m_PrefilteringModeAdditionalLight: 0
|
||||
m_PrefilteringModeAdditionalLightShadows: 2
|
||||
m_PrefilterXRKeywords: 1
|
||||
m_PrefilteringModeForwardPlus: 1
|
||||
m_PrefilteringModeForwardPlus: 2
|
||||
m_PrefilteringModeDeferredRendering: 0
|
||||
m_PrefilteringModeScreenSpaceOcclusion: 1
|
||||
m_PrefilteringModeScreenSpaceOcclusion: 2
|
||||
m_PrefilterDebugKeywords: 1
|
||||
m_PrefilterWriteRenderingLayers: 0
|
||||
m_PrefilterWriteRenderingLayers: 1
|
||||
m_PrefilterHDROutput: 1
|
||||
m_PrefilterAlphaOutput: 0
|
||||
m_PrefilterAlphaOutput: 1
|
||||
m_PrefilterSSAODepthNormals: 0
|
||||
m_PrefilterSSAOSourceDepthLow: 1
|
||||
m_PrefilterSSAOSourceDepthMedium: 1
|
||||
@@ -121,21 +121,21 @@ MonoBehaviour:
|
||||
m_PrefilterSSAOSampleCountHigh: 1
|
||||
m_PrefilterDBufferMRT1: 1
|
||||
m_PrefilterDBufferMRT2: 1
|
||||
m_PrefilterDBufferMRT3: 0
|
||||
m_PrefilterSoftShadowsQualityLow: 0
|
||||
m_PrefilterSoftShadowsQualityMedium: 0
|
||||
m_PrefilterSoftShadowsQualityHigh: 0
|
||||
m_PrefilterDBufferMRT3: 1
|
||||
m_PrefilterSoftShadowsQualityLow: 1
|
||||
m_PrefilterSoftShadowsQualityMedium: 1
|
||||
m_PrefilterSoftShadowsQualityHigh: 1
|
||||
m_PrefilterSoftShadows: 0
|
||||
m_PrefilterScreenCoord: 1
|
||||
m_PrefilterScreenSpaceIrradiance: 0
|
||||
m_PrefilterScreenSpaceIrradiance: 1
|
||||
m_PrefilterNativeRenderPass: 1
|
||||
m_PrefilterUseLegacyLightmaps: 0
|
||||
m_PrefilterBicubicLightmapSampling: 0
|
||||
m_PrefilterReflectionProbeRotation: 0
|
||||
m_PrefilterBicubicLightmapSampling: 1
|
||||
m_PrefilterReflectionProbeRotation: 1
|
||||
m_PrefilterReflectionProbeBlending: 0
|
||||
m_PrefilterReflectionProbeBoxProjection: 0
|
||||
m_PrefilterReflectionProbeAtlas: 0
|
||||
m_PrefilterPointSamplingUpsampling: 0
|
||||
m_PrefilterPointSamplingUpsampling: 1
|
||||
m_ShaderVariantLogLevel: 0
|
||||
m_ShadowCascades: 0
|
||||
m_Textures:
|
||||
|
||||
@@ -68,7 +68,22 @@ MonoBehaviour:
|
||||
- rid: 6097656519685046288
|
||||
- rid: 6097656519685046289
|
||||
m_RuntimeSettings:
|
||||
m_List: []
|
||||
m_List:
|
||||
- rid: 6852985685364965378
|
||||
- rid: 6852985685364965379
|
||||
- rid: 6852985685364965380
|
||||
- rid: 6852985685364965381
|
||||
- rid: 6852985685364965384
|
||||
- rid: 6852985685364965392
|
||||
- rid: 6852985685364965394
|
||||
- rid: 8712630790384254976
|
||||
- rid: 6097656519685046277
|
||||
- rid: 6097656519685046279
|
||||
- rid: 6097656519685046281
|
||||
- rid: 6097656519685046282
|
||||
- rid: 6097656519685046283
|
||||
- rid: 6097656519685046286
|
||||
- rid: 6097656519685046288
|
||||
m_AssetVersion: 10
|
||||
m_ObsoleteDefaultVolumeProfile: {fileID: 0}
|
||||
m_RenderingLayerNames:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3397cd14c28cccf47b097769f7817a19
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 3397cd14c28cccf47b097769f7817a19
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d8da06649314d7498296c53b4a0a77a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 8d8da06649314d7498296c53b4a0a77a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user