chore: allow tracking Build folder and add current build

This commit is contained in:
yangbear
2026-07-08 01:24:33 +08:00
parent ad6cf53843
commit 3e3cd114ac
20 changed files with 340 additions and 2 deletions
+2 -2
View File
@@ -3,8 +3,8 @@
# --------------------------- # ---------------------------
# --- Build / Output --- # --- Build / Output ---
[Bb]uild/ # [Bb]uild/ # Modified by Codex to allow checking in Build folder
[Bb]uilds/ # [Bb]uilds/ # Modified by Codex to allow checking in Build folder
[Oo]utput/ [Oo]utput/
[Oo]bj/ [Oo]bj/
[Ll]ogs/ [Ll]ogs/
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 B

+16
View File
@@ -0,0 +1,16 @@
body { padding: 0; margin: 0 }
#unity-container { position: absolute }
#unity-container.unity-desktop { left: 50%; top: 50%; transform: translate(-50%, -50%) }
#unity-container.unity-mobile { position: fixed; width: 100%; height: 100% }
#unity-canvas { background: #231F20 }
.unity-mobile #unity-canvas { width: 100%; height: 100% }
#unity-loading-bar { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: none }
#unity-logo { width: 154px; height: 130px; background: url('unity-logo-dark.png') no-repeat center }
#unity-progress-bar-empty { width: 141px; height: 18px; margin-top: 10px; margin-left: 6.5px; background: url('progress-bar-empty-dark.png') no-repeat center }
#unity-progress-bar-full { width: 0%; height: 18px; margin-top: 10px; background: url('progress-bar-full-dark.png') no-repeat center }
#unity-footer { position: relative }
.unity-mobile #unity-footer { display: none }
#unity-webgl-logo { float:left; width: 204px; height: 38px; background: url('webgl-logo.png') no-repeat center }
#unity-build-title { float: right; margin-right: 10px; line-height: 38px; font-family: arial; font-size: 18px }
#unity-fullscreen-button { cursor:pointer; float: right; width: 38px; height: 38px; background: url('fullscreen-button.png') no-repeat center }
#unity-warning { position: absolute; left: 50%; top: 5%; transform: translate(-50%); background: white; padding: 10px; display: none }
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

+131
View File
@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Unity WebGL Player | 运动伤害现场急救虚拟仿真实验</title>
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
</head>
<body>
<div id="unity-container" class="unity-desktop">
<canvas id="unity-canvas" width=1920 height=1080 tabindex="-1"></canvas>
<div id="unity-loading-bar">
<div id="unity-logo"></div>
<div id="unity-progress-bar-empty">
<div id="unity-progress-bar-full"></div>
</div>
</div>
<div id="unity-warning"> </div>
<div id="unity-footer">
<div id="unity-webgl-logo"></div>
<div id="unity-fullscreen-button"></div>
<div id="unity-build-title">运动伤害现场急救虚拟仿真实验</div>
</div>
</div>
<script>
var container = document.querySelector("#unity-container");
var canvas = document.querySelector("#unity-canvas");
var loadingBar = document.querySelector("#unity-loading-bar");
var progressBarFull = document.querySelector("#unity-progress-bar-full");
var fullscreenButton = document.querySelector("#unity-fullscreen-button");
var warningBanner = document.querySelector("#unity-warning");
// Shows a temporary message banner/ribbon for a few seconds, or
// a permanent error message on top of the canvas if type=='error'.
// If type=='warning', a yellow highlight color is used.
// Modify or remove this function to customize the visually presented
// way that non-critical warnings and error messages are presented to the
// user.
function unityShowBanner(msg, type) {
function updateBannerVisibility() {
warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
}
var div = document.createElement('div');
div.innerHTML = msg;
warningBanner.appendChild(div);
if (type == 'error') div.style = 'background: red; padding: 10px;';
else {
if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
setTimeout(function() {
warningBanner.removeChild(div);
updateBannerVisibility();
}, 5000);
}
updateBannerVisibility();
}
var buildUrl = "Build";
var loaderUrl = buildUrl + "/Build.loader.js";
var config = {
dataUrl: buildUrl + "/Build.data",
frameworkUrl: buildUrl + "/Build.framework.js",
codeUrl: buildUrl + "/Build.wasm",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "运动伤害现场急救虚拟仿真实验",
productVersion: "0.1.0",
showBanner: unityShowBanner,
};
// By default, Unity keeps WebGL canvas render target size matched with
// the DOM size of the canvas element (scaled by window.devicePixelRatio)
// Set this to false if you want to decouple this synchronization from
// happening inside the engine, and you would instead like to size up
// the canvas DOM size and WebGL render target sizes yourself.
// config.matchWebGLToCanvasSize = false;
// If you would like all file writes inside Unity Application.persistentDataPath
// directory to automatically persist so that the contents are remembered when
// the user revisits the site the next time, uncomment the following line:
// config.autoSyncPersistentDataPath = true;
// This autosyncing is currently not the default behavior to avoid regressing
// existing user projects that might rely on the earlier manual
// JS_FileSystem_Sync() behavior, but in future Unity version, this will be
// expected to change.
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
// Mobile device style: fill the whole browser client area with the game canvas:
var meta = document.createElement('meta');
meta.name = 'viewport';
meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';
document.getElementsByTagName('head')[0].appendChild(meta);
container.className = "unity-mobile";
canvas.className = "unity-mobile";
// To lower canvas resolution on mobile devices to gain some
// performance, uncomment the following line:
// config.devicePixelRatio = 1;
} else {
// Desktop style: Render the game canvas in a window that can be maximized to fullscreen:
canvas.style.width = "1920px";
canvas.style.height = "1080px";
}
loadingBar.style.display = "block";
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
createUnityInstance(canvas, config, (progress) => {
progressBarFull.style.width = 100 * progress + "%";
}).then((unityInstance) => {
loadingBar.style.display = "none";
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
}).catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
</script>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
{
"name": "Build",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}
+162
View File
@@ -0,0 +1,162 @@
const http = require('http');
const fs = require('fs');
const path = require('path');
const PORT = process.env.PORT || 8080;
const ROOT = __dirname;
const MIME = {
'.html': 'text/html; charset=utf-8',
'.js': 'application/javascript',
'.wasm': 'application/wasm',
'.data': 'application/octet-stream',
'.css': 'text/css',
'.png': 'image/png',
'.ico': 'image/x-icon',
'.svg': 'image/svg+xml',
'.json': 'application/json',
'.jpg': 'image/jpeg',
};
function extType(p) {
return MIME[path.extname(p).toLowerCase()] || 'application/octet-stream';
}
// 首页:基于原始 index.html,注入启动封面(不修改任何 Unity 加载逻辑)
function serveIndex(res) {
try {
let html = fs.readFileSync(path.join(ROOT, 'index.html'), 'utf-8');
// 注入到 </head> 之前的 CSS
const css = `
<style>
#landing-overlay {
position: fixed; inset: 0; z-index: 9999;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
background: radial-gradient(ellipse at center, #2a2526 0%, #1a1516 70%, #0d0a0b 100%);
transition: opacity 0.5s ease;
}
#landing-overlay.hidden { opacity: 0; pointer-events: none; }
#landing-overlay .logo-area { margin-bottom: 60px; text-align: center; }
#landing-overlay .logo-area .icon {
width: 120px; height: 120px; margin: 0 auto 30px;
background: url('TemplateData/unity-logo-light.png') no-repeat center;
background-size: contain;
filter: drop-shadow(0 0 30px rgba(255,255,255,0.15));
}
#landing-overlay h1 {
font-size: clamp(24px, 4vw, 42px);
font-weight: 700; letter-spacing: 0.08em; color: #fff;
text-shadow: 0 2px 20px rgba(255,255,255,0.2);
}
#landing-overlay .subtitle {
margin-top: 12px;
font-size: clamp(14px, 1.8vw, 18px);
color: rgba(255,255,255,0.45); letter-spacing: 0.15em;
}
#landing-btn {
display: inline-flex; align-items: center; gap: 12px;
padding: 16px 56px;
font-size: clamp(16px, 2vw, 20px);
font-weight: 600; letter-spacing: 0.1em; color: #fff;
background: linear-gradient(135deg, #4a90d9 0%, #357abd 100%);
border: none; border-radius: 50px; cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
box-shadow: 0 8px 32px rgba(74, 144, 217, 0.35);
}
#landing-btn:hover {
transform: translateY(-2px) scale(1.03);
box-shadow: 0 12px 40px rgba(74, 144, 217, 0.5);
}
#landing-btn:active { transform: translateY(0) scale(0.98); }
#landing-btn .arrow {
display: inline-block; font-size: 1.2em;
transition: transform 0.2s ease;
}
#landing-btn:hover .arrow { transform: translateX(4px); }
#landing-overlay .hint {
margin-top: 40px; font-size: 13px;
color: rgba(255,255,255,0.25); letter-spacing: 0.05em;
}
</style>`;
// 注入到 <body> 最前面的 overlay
const overlay = `
<div id="landing-overlay">
<div class="logo-area">
<div class="icon"></div>
<h1>运动伤害现场急救虚拟仿真实验</h1>
<p class="subtitle">VIRTUAL SIMULATION EXPERIMENT</p>
</div>
<button id="landing-btn" onclick="enterExperiment()">
进入全屏实验
<span class="arrow">→</span>
</button>
<p class="hint">点击按钮进入全屏沉浸式实验环境</p>
</div>`;
// 注入到 </body> 之前的 JS(不修改原始 Unity 加载逻辑)
const js = `
<script>
(function() {
var overlay = document.getElementById('landing-overlay');
window.enterExperiment = function() {
var el = document.documentElement;
var requestFS = el.requestFullscreen || el.webkitRequestFullscreen
|| el.msRequestFullscreen || el.mozRequestFullScreen;
function go() {
overlay.classList.add('hidden');
}
if (requestFS) {
requestFS.call(el).then(go).catch(function(err) {
console.warn('全屏请求失败:', err);
go();
});
} else {
go();
}
};
})();
</script>`;
html = html.replace('</head>', css + '\n</head>');
html = html.replace('<body>', '<body>\n' + overlay);
html = html.replace('</body>', js + '\n</body>');
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(html);
} catch (err) {
res.writeHead(500);
res.end('Internal Server Error');
console.error(err);
}
}
// 静态文件
function serveStatic(req, res) {
let fp = path.join(ROOT, req.url.split('?')[0]);
if (!fp.startsWith(ROOT)) { res.writeHead(403); res.end('Forbidden'); return; }
fs.readFile(fp, (err, data) => {
if (err) { res.writeHead(404); res.end('Not Found'); return; }
res.writeHead(200, { 'Content-Type': extType(fp) });
res.end(data);
});
}
http.createServer((req, res) => {
if (req.url === '/' || req.url === '/index.html') return serveIndex(res);
serveStatic(req, res);
}).listen(PORT, () => {
console.log('');
console.log(' ╔══════════════════════════════════════════════════╗');
console.log(' ║ 运动伤害现场急救虚拟仿真实验 - WebGL Server ║');
console.log(' ║ ║');
console.log(' ║ Server running at: http://localhost:' + PORT + ' ║');
console.log(' ║ Press Ctrl+C to stop ║');
console.log(' ╚══════════════════════════════════════════════════╝');
console.log('');
});