놀이터 밖 배경 충돌을 끄고 지면·접근 소품 역할 유지
This commit is contained in:
@@ -76,7 +76,7 @@ namespace MagnetismHeroes.Tests
|
||||
string name = decoration.prefab.name;
|
||||
bool solid = name == "MeadowClearing" || name == "GentleHill" || name.Contains("Tree") || name.Contains("Limestone") || name == "SlateBoulder" || name == "OpenStoneArch" || name == "MossStoneSteps";
|
||||
var colliders = decoration.prefab.GetComponentsInChildren<Collider>(true);
|
||||
if (solid) Assert.That(colliders, Is.Not.Empty, name + " needs a shape-matched collider.");
|
||||
if (solid) Assert.That(colliders, Is.Not.Empty, name + " needs a shape-matched collider; runtime disables inaccessible instances, while authoring uses terrain for surface probes.");
|
||||
else Assert.That(colliders, Is.Empty, name + " is small vegetation or unreachable scenery.");
|
||||
foreach (var collider in colliders)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MagnetismHeroes.Core;
|
||||
@@ -112,6 +113,58 @@ namespace MagnetismHeroes.Tests
|
||||
Capture("world1-ten-single-groups-phone-default", "Validated synthetic Core FreePlay fixture of ten single groups; underlying stage 1 UI remains puzzle. Used for like-for-like Editor resource observation only.");
|
||||
Assert.That(_app.Presenter.Balls.Count, Is.EqualTo(10));
|
||||
}
|
||||
[UnityTest] public IEnumerator AllThirtyRuntimeEnvironmentsOnlyBlockWithReachableScenery()
|
||||
{
|
||||
var errors = new List<string>(); int distant = 0, reachable = 0, selected = 0;
|
||||
for (int id = 1; id <= 30; id++)
|
||||
{
|
||||
_app.StartStage(id); _app.Voice.Clear(); yield return null; yield return null; Physics.SyncTransforms();
|
||||
var playground = _app.Environment.PlaygroundBounds;
|
||||
foreach (var collider in _app.Environment.GetComponentsInChildren<MeshCollider>())
|
||||
{
|
||||
var surface = collider.GetComponent<MeshRenderer>().bounds;
|
||||
bool outside = collider.name != "MeadowClearing" && !playground.Intersects(surface);
|
||||
if (outside)
|
||||
{
|
||||
distant++;
|
||||
if (collider.enabled) errors.Add($"Stage {id} unreachable {collider.name} still blocks at {surface}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
reachable++;
|
||||
Assert.That(collider.enabled && !collider.isTrigger, Is.True, $"Stage {id} reachable {collider.name} must block.");
|
||||
}
|
||||
bool hit = false;
|
||||
foreach (var direction in new[] { Vector3.up, Vector3.down, Vector3.left, Vector3.right, Vector3.forward, Vector3.back })
|
||||
{
|
||||
float distance = surface.extents.magnitude + 1;
|
||||
hit |= Physics.RaycastAll(surface.center + direction * distance, -direction, distance * 2)
|
||||
.Any(item => item.collider == collider);
|
||||
}
|
||||
if (outside && hit) errors.Add($"Stage {id} background {collider.name} still receives a Physics ray.");
|
||||
if (!outside) Assert.That(hit, Is.True, $"Stage {id} reachable {collider.name} no longer blocks a Physics ray.");
|
||||
}
|
||||
Assert.That(Physics.Raycast(new Vector3(0, .1f, 0), Vector3.down, out var ground, 2), Is.True);
|
||||
Assert.That(ground.collider.GetComponentInParent<BoardEnvironment>(), Is.SameAs(_app.Environment), "Visible play ground must still block.");
|
||||
Debug.Log($"Stage {id} ground ray y={ground.point.y:R}, aerial bounds min y={playground.min.y:R}, difference={ground.point.y - playground.min.y:R}");
|
||||
foreach (var ball in _app.Presenter.Balls.Values)
|
||||
{
|
||||
bool found = false;
|
||||
foreach (float pitch in new[] { 20f, 45f, 70f })
|
||||
for (int yaw = 0; yaw < 360 && !found; yaw += 30)
|
||||
{
|
||||
View(yaw, pitch, 12); var point = _app.Presenter.Camera.WorldToViewportPoint(ball.transform.position);
|
||||
if (point.z <= 0 || point.x < .05f || point.x > .95f || point.y < .05f || point.y > .95f) continue;
|
||||
var ray = _app.Presenter.Camera.ViewportPointToRay(point);
|
||||
found = Physics.Raycast(ray, out var first, 100) && first.collider == ball.GetComponent<SphereCollider>();
|
||||
}
|
||||
Assert.That(found, Is.True, $"Stage {id} sphere {ball.BallId} no longer selectable by first hit."); selected++;
|
||||
}
|
||||
}
|
||||
Debug.Log($"Runtime scenery roles: 30 stages, {distant} distant colliders, {reachable} reachable colliders, {selected} selectable spheres.");
|
||||
Assert.That(distant, Is.GreaterThan(0)); Assert.That(reachable, Is.GreaterThan(0));
|
||||
Assert.That(errors, Is.Empty, string.Join("\n", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,14 @@ namespace MagnetismHeroes.UnityRuntime.Presentation
|
||||
(corner & 2) == 0 ? bounds.min.y : bounds.max.y,
|
||||
(corner & 4) == 0 ? bounds.min.z : bounds.max.z)));
|
||||
PlaygroundBounds = worldBounds;
|
||||
Physics.SyncTransforms();
|
||||
foreach (Transform prop in transform)
|
||||
{
|
||||
// The clearing supports the aerial volume from just below its lower boundary.
|
||||
if (!prop.gameObject.activeSelf || prop.name == "MeadowClearing(Clone)") continue;
|
||||
foreach (var collider in prop.GetComponentsInChildren<Collider>())
|
||||
if (!PlaygroundBounds.Intersects(collider.bounds)) collider.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user