Land Explorer in HomeCamp with boot loading, journal UI, and CDN publish tooling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-11-04 16:18:01 +08:00
co-authored by Cursor
parent 9eec364f30
commit 80678ec499
405 changed files with 48053 additions and 420302 deletions
+73 -11
View File
@@ -340,8 +340,8 @@ public static class BuildHomeCamp
}
Add<Tonemapping>().mode.value = TonemappingMode.Neutral;
var color = Add<ColorAdjustments>();
// Noon frame + another ~20% brightness (EV += log2(1.2)); mild contrast keeps shade soft-PBR.
color.postExposure.value = .74f; color.contrast.value = 10; color.saturation.value = 5; color.hueShift.value = 0;
// Keep the sunny palette while retaining roof and paving highlights in the home screen.
color.postExposure.value = .30f; color.contrast.value = 10; color.saturation.value = 5; color.hueShift.value = 0;
color.colorFilter.value = Color.white;
var white = Add<WhiteBalance>(); white.temperature.value = 6; white.tint.value = 0;
var bloom = Add<Bloom>(); bloom.threshold.value = 1.15f; bloom.intensity.value = .12f; bloom.scatter.value = .55f;
@@ -415,6 +415,7 @@ public static class BuildHomeCamp
camera.allowHDR = true; camera.allowMSAA = true;
var data = camera.GetUniversalAdditionalCameraData();
data.renderPostProcessing = true; data.volumeLayerMask = 1 << Layer;
data.renderShadows = true;
return camera;
}
static Light Light(Scene scene, Transform parent)
@@ -425,10 +426,10 @@ public static class BuildHomeCamp
// Key: warm sun. Fill comes from a separate baked skylight so Subtractive maps do not crush backfaces.
// Fully Baked sun: cast shadows live in the lightmap RGB. Mixed/Subtractive still needs
// realtime shadow maps, which offscreen camera.Render does not produce — so review looked shadowless.
// Noon key: high elevation, +30% intensity vs prior look-dev; shade deepened in bake/shaders.
light.color = new Color(1, .98f, .94f); light.intensity = 2.15f; light.shadows = LightShadows.Soft;
light.lightmapBakeType = LightmapBakeType.Baked; light.shadowAngle = 4;
light.shadowStrength = .94f; light.shadowBias = .05f; light.shadowNormalBias = .3f;
// Noon key: warm sun with realtime soft shadows for buildings, explorer and companions.
light.color = new Color(1, .98f, .94f); light.intensity = 1.95f; light.shadows = LightShadows.Soft;
light.lightmapBakeType = LightmapBakeType.Realtime; light.shadowAngle = 4;
light.shadowStrength = .85f; light.shadowBias = .05f; light.shadowNormalBias = .3f;
light.cullingMask = 1 << Layer; go.transform.rotation = Quaternion.Euler(68, 50, 0);
BakeFillLight(scene, parent);
return light;
@@ -471,12 +472,13 @@ public static class BuildHomeCamp
renderer.sharedMaterial = AssetDatabase.LoadAssetAtPath<Material>(Root + "/backdrop.mat");
renderer.shadowCastingMode = ShadowCastingMode.Off; renderer.receiveShadows = false;
const float distance = 75;
var halfHeight = distance * Mathf.Tan(camera.fieldOfView * Mathf.Deg2Rad * .5f);
var width = halfHeight * 2 * 1080f / 1920;
var height = width / 1.5f;
go.transform.position = camera.transform.position + camera.transform.forward * distance + camera.transform.up * (halfHeight - height * .5f);
// Wide enough for 3:4 tablets and tall enough for 9:22 ultra-long displays with margin.
const float width = 72f;
const float height = 56f;
const float topHeight = 52f;
go.transform.position = camera.transform.position + camera.transform.forward * distance + camera.transform.up * (topHeight - height * .5f);
go.transform.rotation = camera.transform.rotation;
go.transform.localScale = new Vector3(width * 1.04f, height * 1.04f, 1);
go.transform.localScale = new Vector3(width, height, 1);
SetLayer(go);
}
@@ -529,6 +531,66 @@ public static class BuildHomeCamp
foreach (var house in new[] { "MainHouse", "HouseLeft", "HouseRight" })
root.transform.Find(house).position += Vector3.down * .08f;
Put("fountain", "Fountain", 0, .8f, 4.4f, true);
// Place protagonist Explorer in the central plaza (scaled 4x for isometric camp readability)
var explorerPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Bundles/Characters/Human/Explorer/Explorer.prefab");
if (explorerPrefab != null)
{
var explorerGo = (GameObject)PrefabUtility.InstantiatePrefab(explorerPrefab, root.transform);
explorerGo.name = "Explorer";
float expY = GroundY(ground, 0, -3.5f);
explorerGo.transform.position = new Vector3(0, expY, -3.5f);
explorerGo.transform.localScale = Vector3.one * 4.0f;
// Face towards camera / player by default
explorerGo.transform.rotation = Quaternion.Euler(0, 180f, 0);
SetLayer(explorerGo);
placements.Add("Explorer protagonist groundY=" + expY.ToString("F3"));
}
// Place wandering companions in the camp (scaled 4x for isometric readability)
var petDefs = new[]
{
(path: "Assets/Bundles/Characters/Animal/FireCat/FireCat_Companion.prefab", name: "Pet_FireCat", x: -3.8f, z: 1.2f, r: 2.8f, s: 3.40f),
(path: "Assets/Bundles/Characters/Animal/RockBallStudio/RockBallStudio_Companion.prefab", name: "Pet_RockBall", x: 2.6f, z: -1.8f, r: 2.8f, s: 3.00f),
(path: "Assets/Bundles/Characters/Animal/BudBud/BudBud_Companion.prefab", name: "Pet_BudBud", x: -1.6f, z: 4.2f, r: 2.6f, s: 3.20f)
};
var petWandererType = AppDomain.CurrentDomain.GetAssemblies()
.Select(a => a.GetType("HotUpdate.Gameplay.CampPetWanderer"))
.FirstOrDefault(t => t != null);
foreach (var petDef in petDefs)
{
var petPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(petDef.path);
if (petPrefab == null) continue;
var petGo = (GameObject)PrefabUtility.InstantiatePrefab(petPrefab, root.transform);
petGo.name = petDef.name;
float petY = GroundY(ground, petDef.x, petDef.z);
petGo.transform.position = new Vector3(petDef.x, petY, petDef.z);
petGo.transform.localScale = Vector3.one * petDef.s;
// Default facing towards camera for -Z models
petGo.transform.rotation = Quaternion.Euler(0, 0, 0);
SetLayer(petGo);
var col = petGo.GetComponent<CapsuleCollider>();
if (col == null)
{
col = petGo.AddComponent<CapsuleCollider>();
col.center = new Vector3(0, 0.45f, 0);
col.radius = 0.4f;
col.height = 1.0f;
}
if (petWandererType != null)
{
var wanderer = petGo.GetComponent(petWandererType);
if (wanderer == null) wanderer = petGo.AddComponent(petWandererType);
var centerField = petWandererType.GetField("wanderCenter");
if (centerField != null) centerField.SetValue(wanderer, new Vector3(petDef.x, petY, petDef.z));
var radiusField = petWandererType.GetField("wanderRadius");
if (radiusField != null) radiusField.SetValue(wanderer, petDef.r);
}
placements.Add($"{petDef.name} groundY={petY:F3}");
}
// Keep canopy trees behind the roofs so they frame the backdrop without dunking HouseLeft in shadow.
// Nearer canopy slots are placed after the viewer vector, as DGX meshes when ready.
// TreeRearLeft / TreeRearRight stay cards: they sit behind the roofs and another 2000 tris each is not worth it.