Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5b302b3e3 | ||
|
|
2b35d3f754 | ||
|
|
382f6c7f63 |
+114
@@ -0,0 +1,114 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# EXCEPTION — a scene that is serialized as BINARY
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# DialogueTest.unity is a Unity binary SerializedFile, not YAML, despite the
|
||||||
|
# project being set to Force Text. It contains 128 lone CR bytes, so treating it
|
||||||
|
# as text would have git rewrite them as line endings and corrupt the scene.
|
||||||
|
#
|
||||||
|
# Remove this line the moment the file is genuinely text — verify with:
|
||||||
|
# head -c 20 NightclubArcadia/Assets/Scenes/DialogueTest.unity # want %YAML 1.1
|
||||||
|
# Background and the fix: docs/restructure-plan.md §0.1
|
||||||
|
/NightclubArcadia/Assets/Scenes/DialogueTest.unity binary
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 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
|
*.tar.gz
|
||||||
*.7z
|
*.7z
|
||||||
*.rar
|
*.rar
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Local build and test output (Makefile targets)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
/.test-results/
|
||||||
|
/build/
|
||||||
|
|||||||
@@ -58,6 +58,36 @@ AI Navigation 2.0.14, ProBuilder 6.1.2, Test Framework 1.7.0. Yarn Spinner is an
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 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. Unity from the command line
|
||||||
|
|
||||||
### 3.0 Two different tools, both present
|
### 3.0 Two different tools, both present
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# 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 ## 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 (none exist yet)
|
||||||
|
@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 -o $(CURDIR)/build/NightclubArcadia.app
|
||||||
|
|
||||||
|
lock: ## Fail if the Unity Editor has the project open
|
||||||
|
@if pgrep -fl "Unity.app/Contents/MacOS/Unity" | grep -v AssetImportWorker | grep -q .; 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)
|
||||||
Executable
+44
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Summarise an NUnit results file and exit non-zero if anything failed.
|
||||||
|
|
||||||
|
Unity's own docs state there is no common exit-code definition across the
|
||||||
|
components under test, so the results XML is the authority, not $?.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
|
||||||
|
def main(path):
|
||||||
|
try:
|
||||||
|
root = ET.parse(path).getroot()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"no results at {path} — the run did not get far enough to write one")
|
||||||
|
return 1
|
||||||
|
except ET.ParseError as exc:
|
||||||
|
print(f"could not parse {path}: {exc}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
total = int(root.get("total") or 0)
|
||||||
|
passed = int(root.get("passed") or 0)
|
||||||
|
failed = int(root.get("failed") or 0)
|
||||||
|
skipped = int(root.get("skipped") or 0)
|
||||||
|
|
||||||
|
for case in root.iter("test-case"):
|
||||||
|
if case.get("result") == "Passed":
|
||||||
|
continue
|
||||||
|
print(f"FAIL {case.get('fullname')}")
|
||||||
|
message = case.find("failure/message")
|
||||||
|
if message is not None and message.text:
|
||||||
|
for line in message.text.strip().splitlines()[:6]:
|
||||||
|
print(f" {line}")
|
||||||
|
|
||||||
|
if total == 0:
|
||||||
|
print("no tests ran")
|
||||||
|
else:
|
||||||
|
print(f"{passed}/{total} passed" + (f", {skipped} skipped" if skipped else ""))
|
||||||
|
return 1 if failed else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1] if len(sys.argv) > 1 else ".test-results/editmode.xml"))
|
||||||
Reference in New Issue
Block a user