Hello, I am currently working on an FPS gun. Everything is done, but I would like to know how I make it so that when you hold right click, it aims down the sight, then goes back to normal when you release right-click.
I am assuming you have the viewmodel humanoidroot part set to the camera CFrame or something similar.
local goalCFrame = camera.CFrame
psuedoHRP.CFrame = goalCFrame
You can obtain a CFrame that goes from this HRP → sightCFrame
local STATIC_OFFSET = psuedoHRP.CFrame:ToObjectSpace(aimAttach.WorldCFrame)
If you notice this is also pretty similar to EgoMooses tutorial which I learnt from as well. I also recommend checking it out.
However here I chose to use both tween service and lerping. TweenService because it can provide multiple easing styles, lerping is just used to adjust the aiming CFrame offset from 0 to 1.
--outside the loop
local i = 0
local duration = 0.5 --Time it takes to get into aiming position
local STATIC_OFFSET = psuedoHRP.CFrame:ToObjectSpace(aimAttach.WorldCFrame)
--In the renderstep loop
local goalCFrame = camera.CFrame
psuedoHRP.CFrame = goalCFrame
if UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton2) then
i = math.min(i + dt/duration, 1)
else
i = math.max(i - dt/duration, 0)
end
local addedOffsetToAimAttach = STATIC_OFFSET:Inverse()*CFrame.new(0,-0.1,-3)
local lerpAlpha = TweenService:GetValue(i, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
psuedoHRP.CFrame *= CFrame.new():Lerp(addedOffsetToAimAttach, lerpAlpha)
This code was taken from my Spring viewmodel post which constructs the view model purely in code for sharing purposes.
This should be a good starting point for reference.
Because as you have noticed the rotation point of the gun when aiming is pretty weird which is because the gun is offset to the right of the view model.
Normally when aiming the gun becomes centered in the middle changing the rotation point through an aim animation.
I’ve tried my best with this, but I completely do not understand it. I have made a part in the model named “aimPart”. Please guide me on how I change my script.
Local Script:
local runService = game:GetService("RunService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local viewModel = replicatedStorage:WaitForChild("gunSystem"):WaitForChild("Guns"):WaitForChild(script.Parent.Name):Clone()
local camera = game.Workspace.CurrentCamera
local config = require(viewModel:WaitForChild("Config"))
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local h = char:WaitForChild("Humanoid") or char:FindFirstChild("Humanoid") or nil
local cframe = CFrame.new()
viewModel.Parent = game.ReplicatedStorage.unequippedGuns
local mouse = plr:GetMouse()
local tool = script.Parent
local walkAnimationSpeed = 5
local walkAnimationSize = 10
local recoilSpeed = 8
local recoilSize = 0.5
local equipConnection
local cooldown = false
local isHolding = false
local isEquipped = false
local animations = {
['Hold'] = viewModel.AnimationController.Animator:LoadAnimation(viewModel.Animations.hold),
['Shoot'] = viewModel.AnimationController.Animator:LoadAnimation(viewModel.Animations.Shoot)
}
if h ~= nil then
animations['CharacterHold'] = char:WaitForChild("Humanoid"):LoadAnimation(viewModel.CharacterAnimations.Hold)
animations['CharacterShoot'] = char:WaitForChild("Humanoid"):LoadAnimation(viewModel.CharacterAnimations.Shoot)
end
cframe = config.Offset_From_Camera
local function positionModel()
if plr.character then
viewModel:SetPrimaryPartCFrame(camera.CFrame * cframe)
if plr.character.Humanoid.MoveDirection.Magnitude > 0 then
cframe = cframe:Lerp(CFrame.new(config.Offset_From_Camera.X + math.sin(time() * walkAnimationSpeed) / walkAnimationSize, config.Offset_From_Camera.Y + math.cos(time() * walkAnimationSpeed) / walkAnimationSize, config.Offset_From_Camera.Z), 0.2)
else
cframe = cframe:Lerp(config.Offset_From_Camera, 0.2)
end
end
end
local function shoot(target)
if not cooldown then
cooldown = true
if plr.character:FindFirstChild(script.Parent.Name) then
animations['Shoot']:Play()
animations['CharacterShoot']:Play()
local sin = math.sin(time() * recoilSpeed) / recoilSize
cframe = cframe:Lerp(CFrame.new(config.Offset_From_Camera.X + math.sin(time() * walkAnimationSpeed) / walkAnimationSize, config.Offset_From_Camera.Y + math.cos(time() * walkAnimationSpeed) / walkAnimationSize, config.Offset_From_Camera.Z + sin), 0.2)
viewModel["Glock Sound"]:Play()
end
if target then
if target.Parent:FindFirstChild("Humanoid") then
game.ReplicatedStorage.gunSystem.Events.Shoot:FireServer(mouse.Target, script.Parent.Name)
end
end
wait(config.Cooldown_Between_Each_Click)
cooldown = false
end
end
tool.Activated:Connect(function()
if config.IsAutomatic == false then
shoot(mouse.Target)
end
end)
mouse.Button1Down:Connect(function()
if config.IsAutomatic == true then
isHolding = true
end
end)
mouse.Button1Up:Connect(function()
if config.IsAutomatic == true then
isHolding = false
end
end)
local function equip()
if not tool and viewModel then return end
for _, part in pairs(tool:GetChildren()) do
if part:IsA("BasePart") or part:IsA("UnionOperation") then
part.Transparency = 1
end
end
viewModel.Parent = camera
viewModel["LeftArm"].Color = plr.character["Body Colors"].LeftArmColor3
viewModel["RightArm"].Color = plr.character["Body Colors"].RightArmColor3
plr.CameraMode = Enum.CameraMode.LockFirstPerson
animations['Hold']:Play()
if h ~= nil then
animations['CharacterHold']:Play()
end
equipConnection = game["Run Service"].RenderStepped:Connect(function()
if char then
if plr.character.Humanoid.Health > 0 then
positionModel()
end
end
end)
end
local function unequip()
if not tool then return end
equipConnection:Disconnect()
viewModel.Parent = game.ReplicatedStorage.unequippedGuns
plr.CameraMode = Enum.CameraMode.Classic
if h ~= nil then
animations['CharacterHold']:Stop()
end
end
tool.Equipped:Connect(function()
isEquipped = true
mouse.Icon = "http://www.roblox.com/asset?id=79658449"
equip()
end)
tool.Unequipped:Connect(function()
isEquipped = false
mouse.Icon = "rbxasset://SystemCursors/Arrow"
unequip()
end)
runService.RenderStepped:Connect(function()
while isHolding == true and isEquipped == true do
wait(config.Cooldown_Between_Each_Click)
shoot(mouse.Target)
end
end)
AimCFrame will equal the offset as discussed previously between viewmodel rootpart or GetPivot and the aimpart cframe. This should be calculated the line before since this offset betwen aimpart and viewmodel rootpart changes due to animations commonly.
Then either use lerping to adjust this CFrame to CFrame.new() when the aim button is not pressed.