“When I open an egg, the pet model sometimes won’t spin. I don’t know what causing the issue.”
Video:
Module Script
local runService = game:GetService("RunService")
local tweenService = game:GetService("TweenService")
local Maid = require(script.Maid)
local Module3D = require(script.Module3D)
-->> Private methods
local function convertToModel(obj)
local model = Instance.new("Model")
model.Name = obj.Name
for _, child in ipairs(obj:GetChildren()) do
child.Parent = model
end
model.Parent = obj.Parent
obj:Destroy()
return model
end
-->> Class
local Viewport = {}
Viewport.__index = Viewport
Viewport.Types = require(script.Types)
function Viewport.new(viewport, viewportType)
local self = setmetatable({}, Viewport)
self._viewport = viewport
self._model3D = nil
self._maid = Maid.new()
self._resettingSpin = false
self._defaultCf = CFrame.new(0, 0, 0)
self._viewportType = viewportType or Viewport.Types.Default
self._depthMultiplier = self._viewportType.DepthMultiplier or 1
self._angle = 0
return self
end
function Viewport:Display(obj, frame)
local model = obj:IsA("Model") and obj or convertToModel(obj)
if self._model3D then
self._model3D:Destroy()
end
local model3D = Module3D:Attach3D(self._viewport, model)
model3D:SetCFrame(self._viewportType.Angle)
model3D:SetDepthMultiplier(self._depthMultiplier)
model3D.Visible = true
self._maid:GiveTask(model3D)
self._model3D = model3D
self._defaultCf = model3D:GetCFrame()
return self
end
function Viewport:SetDepthMultiplier(depthMultiplier)
self._depthMultiplier = depthMultiplier
return self
end
function Viewport:Spin(speed)
speed = speed or self._viewportType.Speed or 1
self._spin = self._maid:GiveTask(runService.RenderStepped:Connect(function(dt)
self._angle += dt*speed
self._angle %= (math.pi*2)
self._model3D:SetCFrame(self._defaultCf * CFrame.Angles(0, self._angle, 0))
end))
return self
end
function Viewport:StopSpin()
if self._resettingSpin and self._spin then
self._resettingSpin = false
elseif self._spin then
self._maid[self._spin] = nil
end
return self
end
function Viewport:ResetSpin(animDur, dynamicSpeed)
animDur = animDur or 0
self:StopSpin()
local alpha = 1
local startAngle = self._angle
local cf = self._model3D:GetCFrame()
if animDur > 0 then
local start = os.clock()
local easingStyle = Enum.EasingStyle.Quad
local easingDir = Enum.EasingDirection.Out
-->> Whether or not to change speed according to the distance
if dynamicSpeed then
local angle = 360 % math.deg(self._angle)
local speed = angle >= 180 and ((angle/2) / 180) or (angle / 180)
animDur *= speed
end
self._resettingSpin = true
-->> Lerp it back to its fully reset cframe
while os.clock() - start <= animDur and self._resettingSpin do
local dur = os.clock() - start
alpha = tweenService:GetValue(dur / animDur, easingStyle, easingDir)
self._model3D:SetCFrame(cf:Lerp(self._defaultCf, alpha))
self._angle = startAngle + (alpha * (self._defaultCf - startAngle))
runService.RenderStepped:Wait()
end
else
self._model3D:SetCFrame(self._defaultCf)
self._angle = 0
end
self._resettingSpin = false
return self
end
function Viewport:Destroy()
self._maid:DoCleaning()
self._maid = nil
self._model3D = nil
self._viewport = nil
end
return Viewport