Disregard - bad post

when i load the game in the roblox game client(not studio) the “proper tween” for experience does not save, but the experience value does… as you can see in the picture below. Am I even on the right track or do I need to do something different here? This is what happens before I add the remote event, however when i add the remote event in, the exp bar shows 0 as a default, because there is an error…

I have been working out the kinks on this, integrating DataStore and testing in the client, etc.

I got an error I cannot seem to figure out.

13:58:02.728 ServerScriptService.DataStore:20: attempt to index nil with ‘Size’ - Server - DataStore:20
13:58:02.729 Stack Begin - Studio
13:58:02.729 Script ‘ServerScriptService.DataStore’, Line 20 - function updateUI - Studio - DataStore:20
13:58:02.729 Stack End - Studio

suggestions?

Server side

function updateUI(player, expValue, TweenValue, textValue)
	currentExp = expValue
	over.Size = TweenValue
	text.Text = textValue
end


-- ON PLAYER ADDED --
game.Players.PlayerAdded:Connect(function(player)
	
	
	uiEvent.OnServerEvent:Connect(updateUI)

client side

function update()
	currentExp = exp.Value/maxExp.Value
	over.Size = UDim2.new(currentExp,0,1,0)
	text.Text = math.floor(currentExp * 100).. "%"
end



updateUI:FireServer(exp.Value/maxExp.Value, UDim2.new(currentExp,0,1,0), math.floor(currentExp * 100).. "%" )

exp.Changed:Connect(function()
	if exp.Value > maxExp.Value then
		leftOverExp = exp.Value - maxExp.Value
		exp.Value = leftOverExp
		playerLevel.Value = playerLevel.Value + 1
		LevelEvent:FireServer(playerLevel.Value)
		maxExp.Value = maxExp.Value * 1.25
	end
	testEvent:FireServer(exp.Value)
	updateUI:FireServer(exp.Value/maxExp.Value, UDim2.new(currentExp,0,1,0), math.floor(currentExp * 100).. "%" )
end)

Can highlight the line that’s giving an error?

Also why is the server updating the players UIs? Or is it updating like a leaderboard/billboard UI?

on the first script (server script) saying the Size Value is nil.

well I am unsure of how this works, maybe I do not need to even do this, maybe i’m doing something wrong. but the UI does not update until exp.Changed happens for some reason.

you got me thinking logically. I’m dumb and been jaded trying to figure all this out. My max exp value is not saving. That’s why. I have no idea why though.

Don’t worry everyone makes mistakes but glad you found out your problem. Its most likely something to do with your datastore script in general.

Also, you should make sure that your “over” variable exist since the error is saying its nil.

Anyway, goodluck!

maybe you can give some insight here? I figure out the problem, here is what i needed to do:

EXP OVERLAY LOCAL SCRIPT:

function update()
	currentExp = exp.Value/maxExp.Value
	over.Size = UDim2.new(currentExp,0,1,0)
	text.Text = math.floor(currentExp * 100).. "%"
end



update()

exp.Changed:Connect(function()
	if exp.Value > maxExp.Value then
		leftOverExp = exp.Value - maxExp.Value
		exp.Value = leftOverExp
		playerLevel.Value = playerLevel.Value + 1
		LevelEvent:FireServer(playerLevel.Value)
		maxExp.Value = maxExp.Value * 1.25
		maxExpEvent:FireServer(maxExp.Value)
	end
	testEvent:FireServer(exp.Value)
	update()
end)

SERVER SCRIPT HANDLER:

LevelEvent.OnServerEvent:Connect(function(player, value)
	player.leaderstats.Level.Value = value
end)

MaxExpEvent.OnServerEvent:Connect(function(player, value)
	player.playerStats.maxExperience.Value = value
end)

It is all working as it should now which is great.

The insight I am looking for is, It seems all my stats that are assigned to the local player will need remote events to correlate over to the game client in order to save in the Data Store… is this valid because the Data Store is getting and saving these values on the server side?

Thoughts:

From what I’m understanding. You have stats (levels, exp, etc) that are changed and managed on the client and then you fire the server to save those stats in the datastore?

If this is the case and I didn’t misread it then theoretically, yes you can do that BUT it is HIGHLY recommended you don’t handle sensitive data on the client as exploiters can manipulate it to their advantage.

E.g if you’re updating the players gold on the client and sending it to the server to “save it” then an exploiter can just send an infinite amount of gold and the server (not knowing any better) will just save that data.

My suggestion:

What I suggest you do is have everything important managed on the server (stats, calculations, etc) and then have the server send the information to the client to update it either by remote events, or if you’re using ValueBase’s (like stringValues, boolValues, etc) then just store them some place where the client can read it (such as replicatedStorage). Since all the player stats are managed on the server, you won’t need any data from the client and can just directly obtain it from the serverside.

The client should (in my opinion) only be handling effects, UI’s, player settings, and basic data (with a few other exceptions).

An example of “player settings” would be like a player disables effects/UI’s on their client (maybe because its laggy or annoying for them). In this case, if you wanted that setting to save when the player leaves (so they don’t have to keep setting it every time they rejoin), you would need to fire a remote with the setting and save that to the datastore. This is fine as they can’t really manipulate anything as it only affects them and their client.

An example of “basic information” would be when creating a gun. When the player clicks somewhere on the screen, you of course will need to send the click position to the server and verify it by doing sanity checks such as seeing if anything is blocking the player, whether the player actually hit someone, etc.

Remotes:

I’ve also noticed that you have a remote event for each stat:

LevelEvent.OnServerEvent:Connect(function(player, value)
	player.leaderstats.Level.Value = value
end)

MaxExpEvent.OnServerEvent:Connect(function(player, value)
	player.playerStats.maxExperience.Value = value
end)

Although there is no real “performance” issues (as far as I know) with having multiple remotes for everything single thing, it can end up cluttering both your game and your code as you might have 1000 remotes doing 1000 different things.

In my opinion you don’t need to use multiple remote events for each thing you want to do.

You could have a general event for “stats” and send another parameter that determines what the action is:

Event.OnServerEvent:Connect(function(player, EventType, Data) -- Data can be a table.
	if EventType == "UpdatePlayersSetting" then
		player.playerSetting.Value = Data.Value -- whatever you send as the data parameter
	elseif EventType == "DoABackFlip" then
		print("Does a backflip")
	end;
end)

Note the above is just an example and may have typos, etc

Also this doesn’t mean use only 1 remote event for EVERYTHING in your game. Just use it for a certain task.

Example: You can have 1 or 2 remotes for everything that deals with the shop/purchases. 1 or 2 remotes for everything that deals with a trade system, etc.

Conclusion

Anyway, hope this gives you some insight and helps!! You don’t have to follow all or any of the advice if you don’t want to! Feel free to dm me if you don’t understand something or I wasn’t clear!

Goodluck!!

2 Likes