You can write your topic however you want, but you need to answer these questions:
-
**What do you want to achieve? I want to make the photos the player takes save.
-
**What is the issue? The photos aren’t persisting across sessions.
-
**What solutions have you tried so far? I tried a lot of things, but I can’t seem to get it to work.
It is printing the data, but, i think the issue is to do with the localscript, or it retrieving the data from the severscrpt.
my local script (photo taker thing)
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local Debris = game:GetService("Debris")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
-- Get the necessary GUI elements
local gui = player:WaitForChild("PlayerGui"):WaitForChild("Camera")
local photoFrame = gui:WaitForChild("PhotoFrame")
local viewport = photoFrame:WaitForChild("ViewportFrame")
local photoAlbum = gui:WaitForChild("PhotoAlbum")
local photoList = photoAlbum:WaitForChild("Photos")
local uiGridLayout = photoList:WaitForChild("UIGridLayout") -- Using UIGridLayout instead of UIListLayout
local cameranoise = game.StarterPlayer.StarterCharacterScripts.click
-- Position PhotoAlbum in the center
photoAlbum.Size = UDim2.new(.8, 0, .8, 0) -- Adjust the size as needed
photoAlbum.Position = UDim2.new(0.5, 0, 0.5, 0) -- Center the frame on screen
photoAlbum.AnchorPoint = Vector2.new(0.5, 0.5) -- Set the anchor point to the center
photoAlbum.BackgroundColor3 = Color3.fromRGB(30, 30, 30) -- Background color
photoAlbum.BackgroundTransparency = 0.2
photoAlbum.BorderSizePixel = 0
photoAlbum.Visible = false -- Initially hidden
-- Set UIGridLayout for grid arrangement
uiGridLayout.CellSize = UDim2.new(0, 130, 0, 130) -- Size of each photo
uiGridLayout.FillDirection = Enum.FillDirection.Horizontal -- Arrange items horizontally
uiGridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center -- Center the items horizontally
uiGridLayout.VerticalAlignment = Enum.VerticalAlignment.Top -- Align the items at the top vertically
-- Function to update the canvas size for scrolling
local function updateCanvasSize()
local photoCount = #photoList:GetChildren() -- Get the number of photos
local columnCount = math.floor(photoList.AbsoluteSize.X / uiGridLayout.CellSize.X.Offset) -- How many columns can fit horizontally
local rowCount = math.ceil(photoCount / columnCount) -- Calculate rows based on the number of photos and columns
-- Add some space at the bottom to prevent clipping of the last row
local extraPadding = 10 -- Adjust the padding value as necessary
-- Update canvas size based on rows, with added extra padding
local newCanvasSize = UDim2.new(0, 0, 0, rowCount * uiGridLayout.CellSize.Y.Offset + extraPadding) -- Adjust canvas height based on rows
photoList.CanvasSize = newCanvasSize
end
local function addFakeSkybox(viewport, camPos)
-- Skybox images (you'll need to set these to the correct sky textures)
local skyboxImages = {
Front = "rbxassetid://6444884337", -- Replace with actual skybox image IDs
Back = "rbxassetid://6444884337",
Left = "rbxassetid://6444884337",
Right = "rbxassetid://6444884337",
Up = "rbxassetid://6412503613",
Down = ""
}
-- Function to create a face of the skybox
local function makeFace(imageId, position, rotation)
local part = Instance.new("Part")
part.Size = Vector3.new(500, 500, 1)
part.Anchored = true
part.CanCollide = false
part.Transparency = 1
part.CFrame = CFrame.new(camPos + position) * rotation
part.Parent = viewport
local surfaceGui = Instance.new("SurfaceGui")
surfaceGui.Face = Enum.NormalId.Front
surfaceGui.AlwaysOnTop = true
surfaceGui.LightInfluence = 0
surfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud
surfaceGui.PixelsPerStud = 50
surfaceGui.Adornee = part
surfaceGui.Parent = part
local image = Instance.new("ImageLabel")
image.Size = UDim2.fromScale(1, 1)
image.Image = imageId
image.BackgroundTransparency = 1
image.BorderSizePixel = 0
image.Parent = surfaceGui
end
local dist = 300 -- Distance from camera for the skybox faces
-- Create skybox faces with different orientations
makeFace(skyboxImages.Front, Vector3.new(0, 0, -dist), CFrame.Angles(0, math.pi, 0))
makeFace(skyboxImages.Back, Vector3.new(0, 0, dist), CFrame.new())
makeFace(skyboxImages.Left, Vector3.new(-dist, 0, 0), CFrame.Angles(0, math.pi / 2, 0))
makeFace(skyboxImages.Right, Vector3.new(dist, 0, 0), CFrame.Angles(0, -math.pi / 2, 0))
makeFace(skyboxImages.Up, Vector3.new(0, dist, 0), CFrame.Angles(math.pi / 2, 0, 0))
makeFace(skyboxImages.Down, Vector3.new(0, -dist, 0), CFrame.Angles(-math.pi / 2, 0, 0))
end
local function takePhoto()
print("Taking photo...")
photoFrame.Visible = true
-- Create a new camera for the viewport
local camClone = Instance.new("Camera")
camClone.CFrame = camera.CFrame * CFrame.new(0, 0, -2) -- Slightly move it back
viewport.CurrentCamera = camClone
-- Clear old clones in the viewport
for _, child in ipairs(viewport:GetChildren()) do
if child:IsA("BasePart") then
child:Destroy()
end
end
-- Add fake skybox to viewport
addFakeSkybox(viewport, camClone.CFrame.Position)
-- Clone visible BaseParts (excluding terrain)
for _, obj in ipairs(workspace:GetDescendants()) do
if obj:IsA("BasePart") and obj.Transparency < 1 and not obj:IsDescendantOf(workspace.Terrain) then
local success, clone = pcall(function() return obj:Clone() end)
if success then
clone.Anchored = true
clone.Parent = viewport
else
print("Failed to clone object: " .. obj.Name)
end
end
end
-- Simulate flash
local flash = Instance.new("Frame")
flash.Size = UDim2.fromScale(1, 1)
flash.BackgroundColor3 = Color3.new(1, 1, 1)
flash.BackgroundTransparency = 0
flash.ZIndex = 10
flash.Parent = gui
TweenService:Create(flash, TweenInfo.new(0.3), {BackgroundTransparency = 1}):Play()
Debris:AddItem(flash, 0.5)
-- Save to album
local photoClone = photoFrame:Clone()
photoClone.Visible = true
photoClone.Size = UDim2.new(0, 130, 0, 130)
photoClone:ClearAllChildren()
local newViewport = Instance.new("ViewportFrame")
newViewport.Size = UDim2.fromScale(1, 1)
newViewport.BackgroundTransparency = 1
newViewport.CurrentCamera = camClone
newViewport.Parent = photoClone
-- Clone parts into new viewport
for _, obj in ipairs(viewport:GetChildren()) do
if obj:IsA("BasePart") then
local partClone = obj:Clone()
partClone.Anchored = true
partClone.Parent = newViewport
end
end
photoClone.Parent = photoList
updateCanvasSize()
wait(1)
print("Photo taken and added to album.")
end
--load
local function loadSavedPhotos()
local savedData = game.ReplicatedStorage:WaitForChild("GetSavedPhotos"):InvokeServer()
-- Print the entire savedData to understand its structure
print("Saved Data: ", savedData)
-- Check if savedData is valid
if not savedData or #savedData == 0 then
print("No saved photos found.")
return
end
-- Iterate through the savedData to load each photo
for _, photo in ipairs(savedData) do
print("Loaded photo data: ", photo) -- Debugging the structure of each photo
local cfComponents = photo.cf
local cf = CFrame.new(unpack(cfComponents)) -- Recreate the CFrame from the saved components
print("Loaded CFrame: ", cf) -- Debug the CFrame
-- Create a camera and set its position to the saved CFrame
local camClone = Instance.new("Camera")
camClone.CFrame = cf
-- Continue your photo creation logic...
end
-- If no data is printed here, check the structure of savedData on the server-side
print("Loaded", #savedData, "saved photos.")
updateCanvasSize() -- Update the UI to account for the new photos
end
game.Players.PlayerAdded:Connect(function()
task.wait(1)
loadSavedPhotos()
end)
and my server script (saver thing)
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local photoStore = DataStoreService:GetDataStore("PhotoAlbumStore")
local savePhotoEvent = ReplicatedStorage:WaitForChild("SavePhotoEvent")
-- Save a new photo when client sends it
savePhotoEvent.OnServerEvent:Connect(function(player, camCFrame)
local userId = tostring(player.UserId)
local success, currentData = pcall(function()
return photoStore:GetAsync(userId)
end)
if not success then
warn("Failed to load photo data for", player.Name)
currentData = {}
end
currentData = currentData or {}
table.insert(currentData, {cf = {camCFrame:components()}})
local saveSuccess, err = pcall(function()
photoStore:SetAsync(userId, currentData)
end)
if not saveSuccess then
warn("Failed to save photo for", player.Name, err)
else
print("Saved photo for", player.Name)
end
end)
-- ✅ ADD THIS PART BELOW
local getSavedPhotos = ReplicatedStorage.GetSavedPhotos
getSavedPhotos.OnServerInvoke = function(player)
print("step1")
local userId = tostring(player.UserId)
local success, data = pcall(function()
return photoStore:GetAsync(userId)
end)
if success and data then
print("step2")
return data
else
warn("Could not load saved photos for", player.Name)
return {}
end
end
-- ✅ END OF ADDED PART
-- Optional: Load on join and do something
Players.PlayerAdded:Connect(function(player)
local userId = tostring(player.UserId)
local success, data = pcall(function()
return photoStore:GetAsync(userId)
end)
if success and data then
-- Can be sent to client for display
print("Loaded photo data for", player.Name, data)
else
warn("Could not load photo data", player.Name)
end
end)
any suggestions or fixes on why its not working?