fix(g7): спавн через __rbxl_spawn_part + Heartbeat вместо task.spawn
Корни:
1. task.spawn(function() task.wait() end) → 'attempt to yield across
a C-call boundary' — task.spawn в shim синхронно зовёт fn из JS.
Замена: накопление dt в RunService.Heartbeat → spawnCube() каждые 1.5с.
2. Instance.new('Part', workspace) с последующим .Anchored=false
создавал anchored=true примитив + патч → primitiveManager не пересоздавал
rigid body, куб не падал. Новый хелпер __rbxl_spawn_part(opts) шлёт
sceneCreate с правильным anchored СРАЗУ — куб создаётся динамическим
и падает.
This commit is contained in:
parent
8021ed6a20
commit
c9acb4fb3b
@ -510,22 +510,24 @@ coinSound.SoundId = "coin"; coinSound.Volume = 1
|
||||
local winSound = Instance.new("Sound", workspace)
|
||||
winSound.SoundId = "win"; winSound.Volume = 1
|
||||
|
||||
-- Каждые 1.5 сек роняем куб
|
||||
task.spawn(function()
|
||||
while not won do
|
||||
task.wait(1.5)
|
||||
if won then break end
|
||||
local cube = Instance.new("Part", workspace)
|
||||
cube.Size = Vector3.new(0.8, 0.8, 0.8)
|
||||
cube.Position = Vector3.new(math.random(-6, 6), 14, math.random(-6, 6))
|
||||
cube.Color = Color3.fromRGB(255, 204, 51)
|
||||
cube.Material = Enum.Material.Neon
|
||||
cube.Anchored = false -- падает под действием гравитации
|
||||
-- Каждые 1.5 сек роняем куб (через Heartbeat — task.spawn не умеет yield)
|
||||
local RunService = game:GetService("RunService")
|
||||
local _spawnTimer = 0
|
||||
|
||||
-- Куб исчезает через 6с если не поймали
|
||||
local function spawnCube()
|
||||
-- Используем хелпер __rbxl_spawn_part — он сразу создаёт примитив
|
||||
-- с правильными свойствами (включая anchored=false → реальная гравитация).
|
||||
local cube = __rbxl_spawn_part({
|
||||
type = "cube",
|
||||
x = math.random(-6, 6), y = 14, z = math.random(-6, 6),
|
||||
sx = 0.8, sy = 0.8, sz = 0.8,
|
||||
color = "#ffcc33",
|
||||
anchored = false, -- падает
|
||||
canCollide = true,
|
||||
})
|
||||
if not cube then return end
|
||||
Debris:AddItem(cube, 6)
|
||||
|
||||
-- Ловля: при касании игроком +1 очко
|
||||
local caught = false
|
||||
cube.Touched:Connect(function(hit)
|
||||
if caught or won then return end
|
||||
@ -546,6 +548,14 @@ task.spawn(function()
|
||||
__rbxl_spawn_particles("confetti", px, py + 3, pz, 3, 3)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
RunService.Heartbeat:Connect(function(dt)
|
||||
if won then return end
|
||||
_spawnTimer = _spawnTimer + (dt or 0.016)
|
||||
if _spawnTimer >= 1.5 then
|
||||
_spawnTimer = 0
|
||||
spawnCube()
|
||||
end
|
||||
end)`,
|
||||
},
|
||||
|
||||
@ -1826,6 +1826,41 @@ export function registerRobloxShim(lua, opts) {
|
||||
count: Number(count) || 1,
|
||||
});
|
||||
});
|
||||
// Спавн примитива (паритет с JS game.scene.spawn) — кладёт в сцену
|
||||
// примитив с указанным состоянием (включая anchored/canCollide). Возвращает
|
||||
// id примитива (число) для дальнейших операций.
|
||||
let _nextSpawnedId = 800000 + Math.floor(Math.random() * 10000);
|
||||
global.set('__rbxl_spawn_part', (opts) => {
|
||||
try {
|
||||
const id = _nextSpawnedId++;
|
||||
const o = opts || {};
|
||||
send('sceneCreate', {
|
||||
primId: id,
|
||||
type: String(o.type || 'cube'),
|
||||
x: +o.x || 0, y: +o.y || 0, z: +o.z || 0,
|
||||
sx: +o.sx || 1, sy: +o.sy || 1, sz: +o.sz || 1,
|
||||
color: o.color || '#A0A0A0',
|
||||
anchored: o.anchored !== false,
|
||||
canCollide: o.canCollide !== false,
|
||||
});
|
||||
// Создаём Lua-side представление для скриптов
|
||||
const fakePrim = {
|
||||
id, name: o.name || `Spawned_${id}`,
|
||||
x: +o.x || 0, y: +o.y || 0, z: +o.z || 0,
|
||||
sx: +o.sx || 1, sy: +o.sy || 1, sz: +o.sz || 1,
|
||||
color: o.color || '#A0A0A0',
|
||||
anchored: o.anchored !== false,
|
||||
canCollide: o.canCollide !== false,
|
||||
};
|
||||
const part = newPart(fakePrim, send);
|
||||
partById.set(id, part);
|
||||
return part;
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('[__rbxl_spawn_part]', e?.message || e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// Позиция игрока для удобства — отдельные функции для x/y/z, чтобы
|
||||
// wasmoon не оборачивал результат в userdata-proxy.
|
||||
global.set('__rbxl_player_x', () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user