
Key RequiredUniversal

local RS = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local Players = game:GetService("Players")
local plr = Players.LocalPlayer
local cam = workspace.CurrentCamera
if shared.SteoryHub_Cleanup then
pcall(shared.SteoryHub_Cleanup)
end
local remote
pcall(function()
local m = RS:WaitForChild("NexusVRCharacterModel", 8)
remote = m:WaitForChild("UpdateInputs", 8)
local ready = m:FindFirstChild("ReplicationReady")
if ready then
ready:FireServer()
end
end)
local CFG = {
sendRate = 1 / 30,
smooth = 22,
reach = 3.5,
}
local S = {
enabled = false,
noclip = true,
hud = true,
}
local sin, cos, exp, clamp, abs = math.sin, math.cos, math.exp, math.clamp, math.abs
local V3 = Vector3.new
local DOWN = V3(0, -1, 0)
local conns = {}
local function bind(signal, fn)
conns[#conns + 1] = signal:Connect(fn)
end
local function newHand(sign)
local rest = V3(sign * 1.0, -0.7, -0.6)
return {
sign = sign,
shoulder = V3(sign * 1.0, 0.6, 0),
rest = rest,
pos = rest,
vel = V3(0, 0, 0),
target = rest,
roll = 0,
rollTarget = 0,
cf = CFrame.new(rest),
dir = DOWN,
}
end
local hands = {L = newHand(-1), R = newHand(1)}
local headSmooth = nil
local state = {valid = false, rootCF = CFrame.new(), headCF = CFrame.new(), dirL = DOWN, dirR = DOWN}
local function make(class, props, parent)
local o = Instance.new(class)
for k, v in pairs(props) do
o[k] = v
end
o.Parent = parent
return o
end
local function getParent()
if gethui then
local ok, g = pcall(gethui)
if ok and g then return g end
end
local ok, core = pcall(function() return game:GetService("CoreGui") end)
if ok and core then
local tested = pcall(function()
local t = Instance.new("Folder")
t.Parent = core
t:Destroy()
end)
if tested then return core end
end
return plr:WaitForChild("PlayerGui")
end
local parentGui = getParent()
if parentGui:FindFirstChild("SteoryHub_MobileJoyFixed") then
parentGui.SteoryHub_MobileJoyFixed:Destroy()
end
local gui = make("ScreenGui", {
Name = "SteoryHub_MobileJoyFixed",
ResetOnSpawn = false,
DisplayOrder = 99999,
IgnoreGuiInset = true,
}, parentGui)
local panel = make("Frame", {
Size = UDim2.fromOffset(200, 100),
Position = UDim2.fromOffset(16, 16),
BackgroundColor3 = Color3.fromRGB(12, 14, 20),
BackgroundTransparency = 0.2,
BorderSizePixel = 0,
Active = true,
Draggable = true,
}, gui)
make("UICorner", {CornerRadius = UDim.new(0, 10)}, panel)
make("UIStroke", {Color = Color3.fromRGB(0, 200, 255), Transparency = 0.5, Thickness = 1.2}, panel)
local titleLabel = make("TextLabel", {
Size = UDim2.new(1, 0, 0, 30),
Position = UDim2.fromOffset(0, 5),
BackgroundTransparency = 1,
Text = "<b>STEORYHUB · VR</b>",
TextColor3 = Color3.fromRGB(225, 235, 245),
Font = Enum.Font.Code,
TextSize = 12,
}, panel)
local vrToggleBtn = make("TextButton", {
Size = UDim2.new(0.9, 0, 0, 45),
Position = UDim2.new(0.05, 0, 0.42, 0),
BackgroundColor3 = Color3.fromRGB(150, 40, 40),
Text = "Ligar Modo VR",
TextColor3 = Color3.new(1, 1, 1),
Font = Enum.Font.GothamBold,
TextSize = 14,
BorderSizePixel = 0,
}, panel)
make("UICorner", {CornerRadius = UDim.new(0, 8)}, vrToggleBtn)
local joystickGui = make("Frame", {
Size = UDim2.fromScale(1, 1),
BackgroundTransparency = 1,
Visible = false,
}, gui)
local function createBlockedJoystick(position, sideLabel)
local blocker = make("TextButton", {
Size = UDim2.fromOffset(180, 180),
Position = position,
AnchorPoint = Vector2.new(0.5, 0.5),
BackgroundTransparency = 1,
Text = "",
AutoButtonColor = false,
}, joystickGui)
local base = make("Frame", {
Size = UDim2.fromOffset(120, 120),
Position = UDim2.fromScale(0.5, 0.5),
AnchorPoint = Vector2.new(0.5, 0.5),
BackgroundColor3 = Color3.fromRGB(40, 40, 40),
BackgroundTransparency = 0.4,
BorderSizePixel = 0,
}, blocker)
make("UICorner", {CornerRadius = UDim.new(1, 0)}, base)
local label = make("TextLabel", {
Size = UDim2.fromScale(1, 1),
BackgroundTransparency = 1,
Text = sideLabel,
TextColor3 = Color3.fromRGB(200, 200, 200),
Font = Enum.Font.GothamBold,
TextSize = 13,
}, base)
local knob = make("Frame", {
Size = UDim2.fromOffset(55, 55),
Position = UDim2.fromScale(0.5, 0.5),
AnchorPoint = Vector2.new(0.5, 0.5),
BackgroundColor3 = Color3.fromRGB(0, 170, 255),
BackgroundTransparency = 0.1,
BorderSizePixel = 0,
}, base)
make("UICorner", {CornerRadius = UDim.new(1, 0)}, knob)
return blocker, knob
end
local joyLeftBlocker, joyLeftKnob = createBlockedJoystick(UDim2.new(0.18, 0, 0.72, 0), "Mão Esq")
local joyRightBlocker, joyRightKnob = createBlockedJoystick(UDim2.new(0.82, 0, 0.72, 0), "Mão Dir")
local leftInputId, rightInputId = nil, nil
local leftDelta = Vector2.new(0, 0)
local rightDelta = Vector2.new(0, 0)
local joyRadius = 50
joyLeftBlocker.InputBegan:Connect(function(input)
if not S.enabled then return end
if input.UserInputType == Enum.UserInputType.Touch and not leftInputId then
leftInputId = input
input:Capture()
end
end)
joyRightBlocker.InputBegan:Connect(function(input)
if not S.enabled then return end
if input.UserInputType == Enum.UserInputType.Touch and not rightInputId then
rightInputId = input
input:Capture()
end
end)
UIS.InputChanged:Connect(function(input)
if not S.enabled then return end
if input == leftInputId then
local center = joyLeftBlocker.AbsolutePosition + Vector2.new(90, 90)
local current = input.Position
local diff = Vector2.new(current.X, current.Y) - center
if diff.Magnitude > joyRadius then
diff = diff.Unit * joyRadius
end
joyLeftKnob.Position = UDim2.new(0.5, diff.X, 0.5, diff.Y)
leftDelta = diff / joyRadius
elseif input == rightInputId then
local center = joyRightBlocker.AbsolutePosition + Vector2.new(90, 90)
local current = input.Position
local diff = Vector2.new(current.X, current.Y) - center
if diff.Magnitude > joyRadius then
diff = diff.Unit * joyRadius
end
joyRightKnob.Position = UDim2.new(0.5, diff.X, 0.5, diff.Y)
rightDelta = diff / joyRadius
end
end)
local function resetJoysticks()
leftInputId, rightInputId = nil, nil
leftDelta, rightDelta = Vector2.new(0, 0), Vector2.new(0, 0)
joyLeftKnob.Position = UDim2.fromScale(0.5, 0.5)
joyRightKnob.Position = UDim2.fromScale(0.5, 0.5)
end
UIS.InputEnded:Connect(function(input)
if input == leftInputId then
leftInputId = nil
leftDelta = Vector2.new(0, 0)
joyLeftKnob.Position = UDim2.fromScale(0.5, 0.5)
elseif input == rightInputId then
rightInputId = nil
rightDelta = Vector2.new(0, 0)
joyRightKnob.Position = UDim2.fromScale(0.5, 0.5)
end
end)
vrToggleBtn.MouseButton1Click:Connect(function()
S.enabled = not S.enabled
if S.enabled then
vrToggleBtn.BackgroundColor3 = Color3.fromRGB(40, 150, 60)
vrToggleBtn.Text = "Desligar VR"
joystickGui.Visible = true
else
vrToggleBtn.BackgroundColor3 = Color3.fromRGB(150, 40, 40)
vrToggleBtn.Text = "Ligar Modo VR"
joystickGui.Visible = false
resetJoysticks()
state.valid = false
end
end)
local function makeMarker(color, letter)
local f = make("Frame", {
Size = UDim2.fromOffset(22, 22),
AnchorPoint = Vector2.new(0.5, 0.5),
BackgroundColor3 = color,
BackgroundTransparency = 0.55,
BorderSizePixel = 0,
Visible = false,
}, gui)
make("UICorner", {CornerRadius = UDim.new(1, 0)}, f)
make("UIStroke", {Color = color, Thickness = 2, Transparency = 0.1}, f)
make("TextLabel", {
Size = UDim2.fromScale(1, 1),
BackgroundTransparency = 1,
Text = letter,
TextColor3 = Color3.new(1, 1, 1),
TextSize = 12,
Font = Enum.Font.GothamBold,
}, f)
return f
end
local markerL = makeMarker(Color3.fromRGB(255, 80, 80), "E")
local markerR = makeMarker(Color3.fromRGB(70, 140, 255), "D")
local function rotBetween(from, to)
local dot = clamp(from:Dot(to), -1, 1)
local axis = from:Cross(to)
if axis.Magnitude < 1e-4 then
if dot > 0 then return CFrame.new() end
return CFrame.fromAxisAngle(Vector3.xAxis, math.pi)
end
return CFrame.fromAxisAngle(axis.Unit, math.acos(dot))
end
local joints = {}
local function refreshJoints(char)
if joints.char == char and joints.neck and joints.neck.Parent then return end
joints.char = char
joints.neck = char:FindFirstChild("Neck", true)
joints.L = char:FindFirstChild("Left Shoulder", true) or char:FindFirstChild("LeftShoulder", true)
joints.R = char:FindFirstChild("Right Shoulder", true) or char:FindFirstChild("RightShoulder", true)
end
local function applyJoints()
if not S.enabled or not state.valid then return end
local char = plr.Character
if not char then return end
refreshJoints(char)
local n, l, r = joints.neck, joints.L, joints.R
if n and n.Part0 then
n.Transform = n.C0.Rotation:Inverse() * n.Part0.CFrame.Rotation:Inverse() * state.headCF.Rotation * n.C1.Rotation
end
if l and l.Part0 then
local fr = l.Part0.CFrame * l.C0
l.Transform = rotBetween(DOWN, fr:VectorToObjectSpace(state.dirL))
end
if r and r.Part0 then
local fr = r.Part0.CFrame * r.C0
r.Transform = rotBetween(DOWN, fr:VectorToObjectSpace(state.dirR))
end
end
local function stepSpring(h, target, dt)
local w = CFG.smooth
local e = exp(-w * dt)
local x = h.pos - target
local tmp = h.vel + x * w
h.pos = target + (x + tmp * dt) * e
h.vel = (h.vel - tmp * w * dt) * e
end
local function buildHandCF(h)
local v = h.pos - h.shoulder
local dir = v.Magnitude > 0.05 and v.Unit or DOWN
h.dir = dir
local up = abs(dir.Y) > 0.98 and V3(0, 0, -1) or Vector3.yAxis
h.cf = CFrame.lookAt(h.pos, h.pos + dir, up)
end
local lastSend = 0
bind(RunService.RenderStepped, function(dt)
dt = math.min(dt, 0.1)
cam = workspace.CurrentCamera
local char = plr.Character
local root = char and char:FindFirstChild("HumanoidRootPart")
if not root or not S.enabled then
state.valid = false
markerL.Visible = false
markerR.Visible = false
return
end
local now = os.clock()
local rootCF = root.CFrame
local chest = rootCF.Position + rootCF.UpVector * 0.5 + rootCF.LookVector * 1.2
local moveL = V3(leftDelta.X * 1.8, -leftDelta.Y * 1.8, 0)
local moveR = V3(rightDelta.X * 1.8, -rightDelta.Y * 1.8, 0)
local targetL = rootCF:PointToObjectSpace(chest + cam.CFrame:VectorToWorldSpace(V3(-0.8, 0, 0) + moveL))
local targetR = rootCF:PointToObjectSpace(chest + cam.CFrame:VectorToWorldSpace(V3(0.8, 0, 0) + moveR))
hands.L.target = targetL
hands.R.target = targetR
for _, h in pairs({hands.L, hands.R}) do
stepSpring(h, h.target, dt)
buildHandCF(h)
end
local headPos = rootCF.Position + V3(0, 2, 0)
local headTarget = CFrame.new(headPos) * cam.CFrame.Rotation
if headSmooth then
headSmooth = headSmooth:Lerp(headTarget, 1 - exp(-dt * 18))
else
headSmooth = headTarget
end
state.valid = true
state.rootCF = rootCF
state.headCF = headSmooth
state.dirL = rootCF:VectorToWorldSpace(hands.L.dir)
state.dirR = rootCF:VectorToWorldSpace(hands.R.dir)
applyJoints()
if remote and now - lastSend >= CFG.sendRate then
lastSend = now
remote:FireServer(headSmooth, rootCF * hands.L.cf, rootCF * hands.R.cf)
end
if S.hud then
local pl, onL = cam:WorldToViewportPoint(rootCF:PointToWorldSpace(hands.L.pos))
local pr, onR = cam:WorldToViewportPoint(rootCF:PointToWorldSpace(hands.R.pos))
markerL.Visible = onL
markerR.Visible = onR
markerL.Position = UDim2.fromOffset(pl.X, pl.Y)
markerR.Position = UDim2.fromOffset(pr.X, pr.Y)
else
markerL.Visible = false
markerR.Visible = false
end
end)
local ncAcc = 0
bind(RunService.Stepped, function(_, dt)
applyJoints()
if S.noclip then
ncAcc = ncAcc + dt
if ncAcc >= 0.1 then
ncAcc = 0
for _, other in ipairs(Players:GetPlayers()) do
if other ~= plr and other.Character then
for _, p in ipairs(other.Character:GetChildren()) do
if p:IsA("BasePart") then
p.CanCollide = false
end
end
end
end
end
end
end)
shared.SteoryHub_Cleanup = function()
for _, c in ipairs(conns) do
c:Disconnect()
end
S.enabled = false
if gui then gui:Destroy() end
shared.SteoryHub_Cleanup = nil
end



é FE?
na real esse script me deu até uma ideia, valeu por deixar open source :D
@WuzRERBorn You're welcome, thank you very much for using.