diff --git a/rbxl-importer/src/__pycache__/converter.cpython-314.pyc b/rbxl-importer/src/__pycache__/converter.cpython-314.pyc index 4e9d3db..85731e3 100644 Binary files a/rbxl-importer/src/__pycache__/converter.cpython-314.pyc and b/rbxl-importer/src/__pycache__/converter.cpython-314.pyc differ diff --git a/rbxl-importer/src/converter.py b/rbxl-importer/src/converter.py index c86bbf8..3478cd8 100644 --- a/rbxl-importer/src/converter.py +++ b/rbxl-importer/src/converter.py @@ -294,6 +294,19 @@ class Converter: for inst in self.model.instances: self._convert_one(inst, scene) + # Spawn fallback: если SpawnLocation в карте НЕ был (или дефолт 0,2,0 + # остался) — поднимаем выше самой высокой Part'ы. Иначе игрок + # появляется внутри Anchored=True геометрии и не может двигаться. + sp = scene.get('spawnPoint', {'x': 0, 'y': 2, 'z': 0}) + if sp.get('x') == 0 and sp.get('y') == 2 and sp.get('z') == 0: + prims = scene.get('primitives', []) + if prims: + max_top = max( + (p['y'] + p.get('sy', 1) / 2) for p in prims + if isinstance(p.get('y'), (int, float)) + ) + scene['spawnPoint'] = {'x': 0, 'y': max_top + 5, 'z': 0} + # Финальный отчёт о скипнутых классах for cls, n in sorted(self.stats.skipped_classes.items(), key=lambda x: -x[1])[:30]: self.stats.warnings.append(f"skipped {n}× {cls}") @@ -690,11 +703,12 @@ class Converter: 'neutral': not bool(props.get('Neutral', True)) and team_color.code != 0, }) - # Spawn должен быть чуть выше — Roblox SpawnLocation это плоская плита, - # юзер появляется на её верхней грани. + # Spawn должен быть значительно выше — старые Roblox-карты часто имеют + # толстый Floor выше плиты, юзер появляется внутри стены/пола если + # не дать запас. +5 единиц достаточно — гравитация уронит на пол. scene['spawnPoint'] = { 'x': pos['x'], - 'y': pos['y'] + 1.5, # отступ вверх чтобы не залипнуть в плите + 'y': pos['y'] + 5, 'z': pos['z'], }