This is a little bit of a weird question, but I was messing around in Garry’s Mod, when I found a pretty nice looking weapon sway addon (sorry for the lag):
I’m wondering, is it possible to make something that looks this good in Roblox? I’d assume it is, since GMod addons are made in Lua as far as I know.
Not much else to say, but I’d like to mention that I have so far tried to use spring, tweens, lerping, sine waves, and none of it looked as good as I would hope.
There are many ways to do this, however the first that comes to mind to me is a neat trick you can do to use BodyMovers, or Roblox’ relatively new Contraints, I recommend you make use of a AlignOrientation Constraint.
The general process you want to go for is to create the viewport model in workspace on the client, you want to ensure that you place it somwhere the player cannot access and that is out of sight. You then use the AlignOrientation Constraint to ensure that the viewmodel faces in the correct direction.
Inside a LocalScript, or a Script with its RunContext set to Client, you can make use of RunService’s event called “OnRenderStepped”, this event triggers every frame that your client updates, but right before it is rendered. Inside this event, you want to copy the orientation of the viewmodel in workspace, and apply it to your actual viewmodel placed inside your ViewportFrame’s Canera.
This works around the limitations of not being able to use Contraints on models inside ViewportFrames, and should achieve a similar effect to what you see in the video you provided.
Okay- even though the solution provided by stef would probably work just as well, I ended up settling on using springs. It may not look the same or the best, but I think I can make do with it!
If anyone is curious, this is the code:
local RunService = game:GetService('RunService')
local Spring = require(script:WaitForChild('Spring'))
local Viewmodel = workspace:WaitForChild('Viewmodel')
local SwaySpring = Spring.new()
local BobSpring = Spring.new()
local function Bob(addition)
return math.sin(tick() * addition * 1.3) * 0.5
end
local Player = game:GetService('Players').LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
RunService.RenderStepped:Connect(function(dt)
-- Get mouse velocity
local Delta = game.UserInputService:GetMouseDelta()
-- Shoving
SwaySpring:shove(Vector3.new(-Delta.X/500, Delta.Y/500, 0))
BobSpring:shove(Vector3.new(Bob(5), Bob(10), Bob(5)) / 10 * (Character.PrimaryPart.Velocity.Magnitude) / 10)
-- Updating springs
local UpdatedSway = SwaySpring:update(dt)
local UpdatedBob = BobSpring:update(dt)
-- Applying springs
Viewmodel:PivotTo(
workspace.CurrentCamera.CFrame *
CFrame.new(UpdatedSway.X, UpdatedSway.Y, 0) *
CFrame.new(UpdatedBob.X, UpdatedBob.Y, 0)
)
end)