I’m currently trying to make a cutscene module for my game which will have lots of functions for all the advanced cutscenes I plan to make.
I have currently run into a problem where even though the transition between the cframes in the table are smoothed using Bezier curves, it still isn’t smooth when going from another section in the table with control points, and the turn is easily noticeable. It just looks bad.
I have tried changing the positions of each cframe, and changing the way they are interpolated but it doesn’t seem to work. I don’t know what to do.
Here is the entire script:
local CutsceneModule = {}
-- Variables --
local RunService = game:GetService("RunService")
local Lighting = game.Lighting
local Camera = workspace.CurrentCamera
local LocalPlayer = game.Players.LocalPlayer
local Character = LocalPlayer.CharacterAdded:Wait()
Character.Archivable = true
-- Helper Functions --
local function createCFrame(position, rotation)
return CFrame.new(position) * CFrame.Angles(math.rad(rotation.X), math.rad(rotation.Y), math.rad(rotation.Z))
end
-- Cubic Bezier formula
local function bezierLerp(t, p0, p1, p2, p3)
local u = 1 - t
local tt = t * t
local uu = u * u
local uuu = uu * u
local ttt = tt * t
local point = (uuu * p0) + (3 * uu * t * p1) + (3 * u * tt * p2) + (ttt * p3)
return point
end
local function playTweenSequence(camera, tweenData)
local totalDuration = 0
for i = 1, #tweenData, 4 do
totalDuration = totalDuration + tweenData[i].duration
end
local currentTime = 0
local function getInterpolatedCFrame(t)
local cumulativeTime = 0
for i = 1, #tweenData, 4 do
local segment = tweenData[i]
local controlPoint1 = tweenData[i + 1]
local controlPoint2 = tweenData[i + 2]
local endCFrame = tweenData[i + 3]
cumulativeTime = cumulativeTime + segment.duration
if t * totalDuration <= cumulativeTime then
local segmentStartTime = cumulativeTime - segment.duration
local localTime = (t * totalDuration - segmentStartTime) / segment.duration
local newPosition = bezierLerp(
localTime,
segment.startCFrame.Position,
controlPoint1,
controlPoint2,
endCFrame.Position
)
local startLookVector = segment.startCFrame.Position + segment.startCFrame.LookVector
local endLookVector = endCFrame.Position + endCFrame.LookVector
local newLookAtPosition = bezierLerp(
localTime,
startLookVector,
controlPoint1 + segment.startCFrame.LookVector,
controlPoint2 + endCFrame.LookVector,
endLookVector
)
return CFrame.new(newPosition, newLookAtPosition)
end
end
end
RunService.RenderStepped:Connect(function(deltaTime)
currentTime = currentTime + deltaTime
local alpha = math.clamp(currentTime / totalDuration, 0, 1)
local newCFrame = getInterpolatedCFrame(alpha)
camera.CFrame = newCFrame
end)
end
local function configureLighting(ambient, brightness, topColorShift, bottomColorShift, diffuseScale, specularScale, outdoorAmbient, clockTime, exposureCompensation)
Lighting.Ambient = ambient
Lighting.Brightness = brightness
Lighting.ColorShift_Top = topColorShift
Lighting.ColorShift_Bottom = bottomColorShift
Lighting.EnvironmentDiffuseScale = diffuseScale
Lighting.EnvironmentSpecularScale = specularScale
Lighting.OutdoorAmbient = outdoorAmbient
Lighting.ClockTime = clockTime
Lighting.ExposureCompensation = exposureCompensation
end
-- Cutscene --
function CutsceneModule.introcutscene()
Camera.CFrame = createCFrame(Vector3.new(31.987, 13.511, -1.683), Vector3.new(-24.155, 41.463, 0.29))
configureLighting(
Color3.new(0.196, 0.196, 0.196),
0,
Color3.new(0, 0, 0),
Color3.new(0, 0, 0),
1,
1,
Color3.new(0.255, 0.255, 0.255),
18,
-0.5
)
local tweenData = {
{
duration = 10,
startCFrame = createCFrame(Vector3.new(30.836, 12.545, 0.1), Vector3.new(-26.5, 36.9, 0))
},
Vector3.new(20.16, 10.127, -4.37),
Vector3.new(20.61, 8.524, 0),
createCFrame(Vector3.new(18.212, 6.139, -27.615), Vector3.new(0, 0, 0)),
{
duration = 3,
startCFrame = createCFrame(Vector3.new(18.212, 6.139, -27.615), Vector3.new(0, 0, 0))
},
Vector3.new(15.885, 5.786, -37.673),
Vector3.new(19.421, 6.312, -50.599),
createCFrame(Vector3.new(20.773, 7.799, -57.712), Vector3.new(-0.167, -1.201, 0)),
{
duration = 4,
startCFrame = createCFrame(Vector3.new(20.773, 7.799, -57.712), Vector3.new(-0.167, -1.201, 0))
},
Vector3.new(26.642, 9.576, -63.51),
Vector3.new(33.708, 9.954, -70.248),
createCFrame(Vector3.new(24.155, 10.804, -84.261), Vector3.new(-7.807, 34.146, 0))
}
playTweenSequence(Camera, tweenData)
end
-- End --
return CutsceneModule