Hi everyone, i’ve been running into a quite interesting issue when building my First Person Gun/Item Framework
-
What do you want to achieve? → Get rid of the flickering
-
What is the issue? → Animation flickering straight after cloning the Viewmodel to the Camera instance
-
What solutions have you tried so far?
- Parenting the Viewmodel after loading the anims (does not work cause AnimationController’s cannot load anims outside of workspace)
- Parenting the Item Model after loading the anims (does not work cause the arms/viewmodel still flickers)
- Prevent rendering the first frame in the update function (still flickers)
- Look for solution on the devforum - nothing that worked for my case
Let’s dive a little bit deeper into my specific Situation:
I am building a First Person Item/Gun Framework which utilizes Viewmodels inside the player Camera to display the items client sided in first person
I have a central ModuleScript that handles all the functionality, here is a simplified version of it:
-- This function gets called once when the equip signal is triggered
-- In my case from my custom hotbar
function module.equipItem(itemInstance : Instance)
-- Unequip current item before equipping another
-- this just resets some values and destroys the view model
module.unequip()
local item = itemInstance:Clone()
-- Unrelated code Removed for simplicity
-- Move Item to Viewmodel --
local viewModel = ViewmodelTemplate:Clone()
local handleMotor = viewModel:WaitForChild("HumanoidRootPart").Handle
handleMotor.Part1 = handle
item.Parent = viewModel
-- Add Default Sounds --
-- Unrelated code Removed for simplicity (Creates sound instances etc)
-- Init Runtime Vars --
-- currentItem and currentViewmodel are global vars here
currentViewmodel = viewModel
viewModel.Parent = Camera
currentItem = item
-- Unrelated code Removed for simplicity (Sets some unrelated vars for the current item)
task.spawn(function()
local equipAnimationTrack = nil
local holdAnimationTrack = nil
if (animations:FindFirstChild("Equip")) then
equipAnimationTrack = viewModel.AnimationController.Animator:LoadAnimation(animations.Equip)
end
if (animations:FindFirstChild("Hold")) then
holdAnimationTrack = viewModel.AnimationController.Animator:LoadAnimation(animations.Hold)
end
-- This is a thing i saw in a different devforum post
-- https://devforum.roblox.com/t/animationtrackplay-should-immediately-initialize-the-first-animation-pose/2965721
-- Does not change behaviour
game:GetService("RunService").PreAnimation:Wait()
equipSound:Play()
if (equipAnimationTrack) then
equipAnimationTrack:Play(0)
wait(equipAnimationTrack.Length)
end
if (holdAnimationTrack) then
local fade = 0
if (equipAnimationTrack) then
fade = 0.1
end
holdAnimationTrack:Play(fade)
end
-- Check if the item is still the one we started equipping
-- This prevents setting ready=true if unequipped during the animation/wait
if (currentItem ~= item) then return end
itemIsReady = true
-- Play Hold Animation --
local holdAnimation = animations:FindFirstChild("Hold")
if (holdAnimation) then
local holdTrack = viewModel.AnimationController:LoadAnimation(holdAnimation)
holdTrack:Play(0)
end
end)
end
-- Method gets called on RenderStepped
function module.updateClient(delta)
local Character = LocalPlayer.Character
if (not Character) then return end
if (not currentViewmodel) then return end
if (not currentItem) then return end
-- Position the viewmodel to the camera --
currentViewmodel.HumanoidRootPart.CFrame = game.Workspace.Camera.CFrame
-- Unrelated code Removed for simplicity
end
To explain it a bit
When i call the equip method a new instance of the viewmodel gets created along with the item model
then the model gets motored with the viewmodel etc.
then the item gets parented to the viewmodel
after that a new task gets spawned (this is needed because i want to wait for the animations etc and the set the itemIsReady var)
inside that task the whole equip animation logic is handeled
Here is a video of the issue happening:
Basically when i equip a item the viewmodel gets cloned into the camera but the animation only plays one frame later - this means my viewmodel is in the idle position for one frame.
Can anyone think of a solution to resolve this issue?