when ever i turn/spin my camera the objects always jiggle/jitter how can i prevent this?
the code:
--[ Services ]--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
--[ Modules ]--
local Component = require(ReplicatedStorage.Packages.Component)
local Trove = require(ReplicatedStorage.Packages.Trove)
local SoundUtil = require(ReplicatedStorage.Packages.SoundUtil)
local PetModule = require(ReplicatedStorage.Modules.PetModule)
local VFXUtil = require(ReplicatedStorage.Packages.VFXUtil)
local ReplicatingUtil = require(ReplicatedStorage.Packages.ReplicatingUtil)
local SecretHatchEffectModule = require(ReplicatedStorage.Modules.SecretHatchEffectModule)
local BazierUtil = require(ReplicatedStorage.Packages.BazierUtil)
local Knit = require(ReplicatedStorage.Packages.Knit)
--[ Knit ]--
local EggAnim = Component.new({
Tag = "EggAnim",
})
--[ Variables ]--
local Camera = workspace.Camera
local Player = Players.LocalPlayer
local TotalObjects = 0
local Settings = {
SpacingY = 3,
SpacingX = 3.2,
SpacingZ = 1,
RawBreak = 8,
EggOffsetCFrame = CFrame.new(0,0,-6.5),
PetOffsetCFrame = CFrame.new(0,-1,-6.5) * CFrame.Angles(0, math.rad(180), 0),
-- [ Backpack ] --
Duration = 0.5,
}
EggAnim.RenderPriority = Enum.RenderPriority.Last.Value
--[ GUI ]--
--[ Functions ]--
function EggAnim:Construct()
self.Type = self.Instance:GetAttribute("Type")
self.Name = self.Instance:GetAttribute("Name")
self.NumberPosition = self.Instance:GetAttribute("NumberPosition") or nil
-- [ Egg ] --
if self.Type == "Egg" then
self.ExpectedPet = self.Instance:GetAttribute("ExpectedPet")
end
self.InitialCFrameValue = Instance.new("CFrameValue")
self.CFrameValue = Instance.new("CFrameValue")
self.PositionLerp = 0
self.Trove = Trove.new()
end
function EggAnim:InitPosition(dt)
local CurrentObjectPosition = self.NumberPosition
local IsTotalObjectsOdd = TotalObjects % 2 == 1 -- if total number of objects is odd
local IsCurrentObjectPositionOdd = CurrentObjectPosition % 2 == 1 -- numberposition of the objects is odd
local CurrentNumberOfPair = IsTotalObjectsOdd and math.floor((CurrentObjectPosition)/2) or math.floor((CurrentObjectPosition+1)/2)
local InitialCFrame = CFrame.new()
if not IsTotalObjectsOdd or (IsTotalObjectsOdd and CurrentObjectPosition ~= 1) then
local offsetMultiplier = IsTotalObjectsOdd and CurrentObjectPosition ~= 1 and CurrentNumberOfPair or (CurrentNumberOfPair - 1)
local XCFrame = IsCurrentObjectPositionOdd and (Settings.SpacingX/2) * CurrentNumberOfPair or -((Settings.SpacingX/2) * CurrentNumberOfPair)
local YCFrame = 0
local ZCFrame = -(Settings.SpacingZ * offsetMultiplier)
local AdditionalOffset = IsCurrentObjectPositionOdd and (self.Instance.PrimaryPart.Size.X/2 * offsetMultiplier) or -(self.Instance.PrimaryPart.Size.X/2 * offsetMultiplier)
XCFrame = XCFrame + AdditionalOffset
InitialCFrame = CFrame.new(XCFrame, YCFrame, ZCFrame)
end
local OffSet = Settings.EggOffsetCFrame
if self.Type == "Egg" then
OffSet = Settings.EggOffsetCFrame
elseif self.Type == "Pet" then
OffSet = Settings.PetOffsetCFrame
end
local TargetCFrame = Camera.CFrame * InitialCFrame * OffSet * self.CFrameValue.Value
self.Instance:PivotTo(TargetCFrame)
-- Return the target CFrame instead of immediately setting it
return TargetCFrame
end
function EggAnim:PlayEggAnimations()
self.CFrameValue.Value = CFrame.new(0, -8, 0)
local EggMoveUpAnim = TweenService:Create(self.CFrameValue, TweenInfo.new(0.5, Enum.EasingStyle.Quint), { Value = CFrame.new(0, 0, -1) })
local EggMoveForwardAnim = TweenService:Create(self.CFrameValue, TweenInfo.new(0.25, Enum.EasingStyle.Back), { Value = CFrame.new(0, 0, -1) })
local EggMoveBackAnim = TweenService:Create(self.CFrameValue, TweenInfo.new(0.2, Enum.EasingStyle.Back), { Value = CFrame.new(0, 0, -4) })
local EggTurnMiddleAnim = TweenService:Create(self.CFrameValue, TweenInfo.new(0.3, Enum.EasingStyle.Back), { Value = CFrame.Angles(0, 0, 0) * CFrame.new(0, 0, -1) })
EggMoveUpAnim:Play()
SoundUtil:PlaySFX("Egg Bouce Back")
EggMoveUpAnim.Completed:Wait()
task.wait(0.4)
local length = 5
local mult = 0.5
if PetModule.GetStat(self.ExpectedPet, "Rarity") == "Secret" then
length = 40
mult = 0.2
elseif PetModule.GetStat(self.ExpectedPet, "Rarity") == "Legendary" then
length = 20
mult = 0.3
end
for i = 1, length do
-- More gradual speed increase
local duration = math.max(0.3 / (1 + (i * mult)), 0.05) -- Starts at 0.3, decreases more slowly, minimum of 0.05
local EggTurnLeftAnim = TweenService:Create(self.CFrameValue,
TweenInfo.new(duration, Enum.EasingStyle.Back),
{ Value = CFrame.Angles(0, 0, math.rad(25)) * CFrame.new(0, 0, -1) }
)
local EggTurnRightAnim = TweenService:Create(self.CFrameValue,
TweenInfo.new(duration, Enum.EasingStyle.Back),
{ Value = CFrame.Angles(0, 0, math.rad(-25)) * CFrame.new(0, 0, -1) }
)
EggTurnLeftAnim:Play()
task.spawn(function()
SoundUtil:PlayDupeSFX("Egg Turned")
end)
EggTurnLeftAnim.Completed:Wait()
EggTurnRightAnim:Play()
task.spawn(function()
SoundUtil:PlayDupeSFX("Egg Turned")
end)
EggTurnRightAnim.Completed:Wait()
-- Clean up tweens
EggTurnLeftAnim:Destroy()
EggTurnRightAnim:Destroy()
end
EggTurnMiddleAnim:Play()
EggMoveBackAnim:Play()
EggTurnMiddleAnim.Completed:Wait()
SoundUtil:PlaySFX("Egg Start")
EggMoveBackAnim.Completed:Wait()
EggMoveForwardAnim:Play()
SoundUtil:PlaySFX("Egg Hatched")
EggMoveForwardAnim.Completed:Wait()
-- Cleanup
self.Trove:Add(EggMoveUpAnim)
self.Trove:Add(EggMoveForwardAnim)
self.Trove:Add(EggMoveBackAnim)
self.Trove:Add(EggTurnMiddleAnim)
self.Instance:RemoveTag("EggAnim")
end
function EggAnim:PlayPetAnimation()
local PetMoveBackAnim = TweenService:Create(self.CFrameValue, TweenInfo.new(0.2, Enum.EasingStyle.Linear), { Value = CFrame.new(0, 0, 0) })
local PetMoveDownAnim = TweenService:Create(self.CFrameValue, TweenInfo.new(0.3, Enum.EasingStyle.Quad), { Value = CFrame.new(0, -self.Instance.Base.Size.Y * 6, 0) })
if PetModule.GetStat(self.Name, "Rarity") == "Secret" then
task.spawn(function()
SecretHatchEffectModule:OnClientFunction(self.Name, self.Instance)
end)
end
local PetInfo = ReplicatingUtil:Replicate("PetHatchUI", "Billboards")
PetInfo.Parent = self.Instance.Base
if self.Shiny == true then
PetInfo.Container.Shiny.Visible = true
end
if PetModule.GetStat(self.Petname, "Rarity") == "Secret" then
PetInfo.Container.SecretPetName.Text = self.Name
PetInfo.Container.SecretRarity.Text = PetModule.GetStat(self.Name, "Rarity")
PetInfo.Container.SecretPetName.Visible = true
PetInfo.Container.SecretRarity.Visible = true
elseif PetModule.GetStat(self.Petname, "Rarity") == "Legendary" then
PetInfo.Container.LegendaryPetName.Text = self.Name
PetInfo.Container.LegendaryRarity.Text = PetModule.GetStat(self.Name, "Rarity")
PetInfo.Container.LegendaryPetName.Visible = true
PetInfo.Container.LegendaryRarity.Visible = true
else
PetInfo.Container.PetName.Text = self.Name
PetInfo.Container.Rarity.Text = PetModule.GetStat(self.Name, "Rarity")
PetInfo.Container.PetName.Visible = true
PetInfo.Container.Rarity.Visible = true
end
PetInfo.Enabled = true
if PetModule.GetStat(self.Name, "Rarity") == "Secret" then
local VFX = VFXUtil.new("Insert", "PetHatchVFX_Secret", {
Parent = self.Instance.Base
})
self.Trove:Add(VFX)
VFX:Emit()
elseif PetModule.GetStat(self.Name, "Rarity") == "Legendary" then
local VFX = VFXUtil.new("Insert", "PetHatchVFX_Legendary", {
Parent = self.Instance.Base
})
self.Trove:Add(VFX)
VFX:Emit()
else
local VFX = VFXUtil.new("Insert", "PetHatchVFX_Normal", {
Parent = self.Instance.Base
})
self.Trove:Add(VFX)
VFX:Emit()
end
task.wait(2)
PetMoveDownAnim:Play()
PetMoveDownAnim.Completed:Wait()
--[[
PetMoveBackAnim:Play()
PetMoveBackAnim.Completed:Wait()
]]
-- Cleanup
PetMoveBackAnim:Destroy()
PetMoveDownAnim:Destroy()
PetInfo:Destroy()
self.Instance:RemoveTag("EggAnim")
end
function EggAnim:UpdateObjectPositions()
local TakenPositons = {}
TotalObjects = 0
for _, egganim in EggAnim:GetAll() do
TotalObjects += 1
if not egganim.NumberPosition then
local NewPosition = 1
while TakenPositons[NewPosition] do
NewPosition += 1
end
TakenPositons[NewPosition] = true
egganim.NumberPosition = NewPosition
else
TakenPositons[egganim.NumberPosition] = true
end
-- Store current CFrame before updating position
egganim.InitialCFrameValue.Value = egganim.Instance:GetPivot()
egganim.PositionLerp = 0
end
end
function EggAnim:RenderSteppedUpdate(dt)
local targetCFrame = self:InitPosition(dt)
if self.PositionLerp < 1 then
self.PositionLerp = math.min(self.PositionLerp + dt * 2, 1)
local function quintOut(x)
return 1 - math.pow(1 - x, 5)
end
local easedLerp = quintOut(self.PositionLerp)
self.Instance:PivotTo(self.InitialCFrameValue.Value:Lerp(targetCFrame, easedLerp))
else
self.Instance:PivotTo(targetCFrame)
end
end
EggAnim.Started:Connect(function(self)
self:UpdateObjectPositions()
-- Set initial position immediately without lerping
local targetCFrame = self:InitPosition()
self.Instance:PivotTo(targetCFrame)
self.InitialCFrameValue.Value = targetCFrame
self.PositionLerp = 1 -- Set to 1 to prevent initial lerping
self.Trove:Add(self.Instance)
if self.Type == "Egg" then
self:PlayEggAnimations()
elseif self.Type == "Pet" then
self:PlayPetAnimation()
end
end)
EggAnim.Stopped:Connect(function(self)
self.Trove:Clean()
self:UpdateObjectPositions()
end)
return EggAnim