Hi, I’m making a Star Wars droid companion system where the primary, secondary and tertiary colours are fully customisable. The model is structured like this:
This is the current code I have, though it doesn’t seem to work and I just wanted to know if there was a better and actually functional way of doing this:
-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
-- Droid Module
local DroidModule = require(ReplicatedStorage:FindFirstChild("Droids").DroidModule)
-- RemoteEvent
local DroidEvent = ReplicatedStorage:FindFirstChild("Droids").DroidEvent
-- Datastore
local DataStore = DataStoreService:GetDataStore("Development1")
-- Save Function
local function SaveData(Player, Character)
local DroidName
print("Data saved")
for i,v in pairs(DroidModule) do
if Character:FindFirstChild(v.Title) then
DroidName = Character:FindFirstChild(v.Title)
end
end
local DroidColours = {
["DroidName"] = DroidName.Name,
["PrimaryRed"] = DroidName.Body.Primary.Head.Color.R,
["PrimaryGreen"] = DroidName.Body.Primary.Head.Color.G,
["PrimaryBlue"] = DroidName.Body.Primary.Head.Color.B,
["SecondaryRed"] = DroidName.Body.Secondary.Head.Color.R,
["SecondaryGreen"] = DroidName.Body.Secondary.Head.Color.G,
["SecondaryBlue"] = DroidName.Body.Secondary.Head.Color.B,
["TertiaryRed"] = DroidName.Body.Tertiary.Head.Color.R,
["TertiaryGreen"] = DroidName.Body.Tertiary.Head.Color.G,
["TertiaryBlue"] = DroidName.Body.Tertiary.Head.Color.B,
}
DataStore:SetAsync(Player.UserId, function()
return DroidColours
end)
end
-- Load Function
local function LoadData(Player, Character)
local DroidColours
local success, err = pcall(function()
DroidColours = DataStore:GetAsync(Player.UserId)
end)
if success then
for i,v in ipairs(DroidColours) do
local NewDroid = ReplicatedStorage.Droids:FindFirstChild(DroidColours[1]):Clone()
for i,primary in (NewDroid.Body.Primary:GetChildren()) do
primary.Color = Color3.fromRGB(DroidColours[2], DroidColours[3], DroidColours[4])
end
for i,secondary in (NewDroid.Body.Secondary:GetChildren()) do
secondary.Color = Color3.fromRGB(DroidColours[5], DroidColours[6], DroidColours[7])
end
for i,tertiary in (NewDroid.Body.Secondary:GetChildren()) do
tertiary.Color = Color3.fromRGB(DroidColours[8], DroidColours[9], DroidColours[10])
end
NewDroid.Parent = Character
end
end
end
-- Player
game.Players.PlayerAdded:Connect(function(Player)
local Character = Player.Character or Player.CharacterAdded:Wait()
LoadData(Player, Character)
end)
game.Players.PlayerRemoving:Connect(function(Player)
local Character = Player.Character or Player.CharacterAdded:Wait()
SaveData(Player, Character)
end)
Do you have a BindToClose function? When testing in studio it could be that the game closes before it had time to save.
Also it’s a lot more efficient to store your colors as hex instead of R G and B values
-- Save Function
local function SaveData(Player, Character)
local DroidName
print("Data saved")
for i,v in pairs(DroidModule) do
if Character:FindFirstChild(v.Title) then
DroidName = Character:FindFirstChild(v.Title)
end
end
local DroidColours = {
["DroidName"] = DroidName.Name,
["PrimaryRed"] = DroidName.Body.Primary.Head.Color.R,
["PrimaryGreen"] = DroidName.Body.Primary.Head.Color.G,
["PrimaryBlue"] = DroidName.Body.Primary.Head.Color.B,
["SecondaryRed"] = DroidName.Body.Secondary.Head.Color.R,
["SecondaryGreen"] = DroidName.Body.Secondary.Head.Color.G,
["SecondaryBlue"] = DroidName.Body.Secondary.Head.Color.B,
["TertiaryRed"] = DroidName.Body.Tertiary.Head.Color.R,
["TertiaryGreen"] = DroidName.Body.Tertiary.Head.Color.G,
["TertiaryBlue"] = DroidName.Body.Tertiary.Head.Color.B,
}
print(DroidColours.DroidName)
DataStore:SetAsync(Player.UserId, function()
return DroidColours
end)
end
Doesn’t print anything when saving data, though when loading data I get invalid argument #1 to 'ipairs' (table expected, got nil) for line for i,v in ipairs(DroidColours) do
Function:
-- Load Function
local function LoadData(Player, Character)
local DroidColours
local success, err = pcall(function()
DroidColours = DataStore:GetAsync(Player.UserId)
end)
if success then
for i,v in ipairs(DroidColours) do
local NewDroid = ReplicatedStorage.Droids:FindFirstChild(DroidColours[1]):Clone()
for i,primary in (NewDroid.Body.Primary:GetChildren()) do
primary.Color = Color3.fromRGB(DroidColours[2], DroidColours[3], DroidColours[4])
end
for i,secondary in (NewDroid.Body.Secondary:GetChildren()) do
secondary.Color = Color3.fromRGB(DroidColours[5], DroidColours[6], DroidColours[7])
end
for i,tertiary in (NewDroid.Body.Secondary:GetChildren()) do
tertiary.Color = Color3.fromRGB(DroidColours[8], DroidColours[9], DroidColours[10])
end
NewDroid.Parent = Character
end
end
end
I rewrote the code to a much simpler version, I think it is an issue with defining Character when the player is leaving, any ideas?
-- DataStoreService
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("Development")
-- Services
local Players = game:GetService("Players")
-- Save Function
local function SaveData(Player, Character)
local key = Player.UserId
local data = {
Player.Droids.Equipped.Value,
Player.Droids.Owned.Value
}
local success, err = pcall(function()
DataStore:SetAsync(key, data)
end)
if success then
print("Data saved")
end
end
game.Players.PlayerRemoving:Connect(function(Player)
local Character = Player.CharacterRemoving:Wait()
SaveData(Player, Character)
end)
game:BindToClose(function()
for i,Player in (Players:GetPlayers()) do
local Character = Player.CharacterRemoving:Wait()
SaveData(Player, Character)
end
end)
-- Load Function
local function LoadData(Player, Character)
local key = Player.UserId
local data
local success, err = pcall(function()
data = DataStore:GetAsync(key)
end)
if success and data then
Player.Droids.Equipped.Value = data[1]
Player.Droids.Owned.Value = data[2]
end
print(Character.Name)
end
game.Players.PlayerAdded:Connect(function(Player)
local Character = Player.CharacterAdded:Wait()
LoadData(Player, Character)
end)
-- DataStoreService
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("Development")
-- Services
local Players = game:GetService("Players")
-- Save Function
local function SaveData(Player)
local key = Player.UserId
local data = {
Player.Droids.Equipped.Value,
Player.Droids.Owned.Value
}
local success, err = pcall(function()
DataStore:SetAsync(key, data)
end)
if success then
print("Data saved")
end
end
game.Players.PlayerRemoving:Connect(function(Player)
SaveData(Player)
end)
game:BindToClose(function()
for _, Player in pairs(Players:GetPlayers()) do
SaveData(Player)
end
end)
-- Load Function
local function LoadData(Player)
local key = Player.UserId
local data
local success, err = pcall(function()
data = DataStore:GetAsync(key)
end)
if success and data then
Player.Droids.Equipped.Value = data[1]
Player.Droids.Owned.Value = data[2]
else
warn("Failed to load data: " .. err)
end
end
game.Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
LoadData(Player)
end)
end)