Hey, I believe the best way to do what you're trying to achieve is to use something called a Region3
value and the function game:FindPartsInRegion3WithIgnoreList. We can detect if a player is in this region in space to make sure that they are in the area you want. I'll use a Part named "Part" this example, and made it invisible (Transparency = 1)
. This part covers the area I WANT to cover. (Make sure you Part's CanCollide
property is set to false and the Part's Size is big enough to cover the entire area you want to cover. i.e; half of the town) We can calculate the Region3
value as seen in the following code block.
01 | local Players, ReplicatedStorage, Stepped = game:GetService( "Players" ), game:GetService( "ReplicatedStorage" ), game:GetService( "RunService" ).Stepped; |
02 | local Part = workspace:WaitForChild( "Part" ); |
04 | local Size, Position = Part.Size, Part.Position; |
06 | local Region = Region 3. new(Position-Size/ 2 , Position+Size/ 2 ); |
11 | local PlayersInRegion = { } ; |
As you may have noticed, I also create a table named PlayersInRegion
to keep track of who's in the region and who isn't. Now, we need to create a loop that checks for us who and who isn't in the region (specifically every step).
01 | while Stepped:Wait() do |
02 | local Reg = game:FindPartsInRegion 3 WithIgnoreList(Region, { Part } , math.huge ); |
04 | for _, obj in pairs (Reg) do |
05 | local Player = Players:GetPlayerFromCharacter(obj.Parent); |
06 | if Player and not PlayersInRegion [ Player ] then |
07 | PlayersInRegion [ Player ] = "checked" ; |
08 | ReplicatedStorage.change:FireClient(Player, 22 ); |
09 | elseif Player and PlayersInRegion [ Player ] then |
10 | PlayersInRegion [ Player ] = "checked" |
13 | for Player, _ in pairs (PlayersInRegion) do |
14 | if PlayersInRegion [ Player ] ~ = "checked" then |
15 | ReplicatedStorage.change:FireClient(Player, 15.5 ) |
16 | PlayersInRegion [ Player ] = nil |
18 | PlayersInRegion [ Player ] = true |
So, you may be asking, what is happening in the two for loops? Basically, we first loop through the array (Reg
) of items that are in the region (excluding the part; we add in an ignore list that ignores the part). Then we check if the object in each index is a Player AND has not previously been recorded in the PlayersInRegion
table because this means the player has entered the area we want to cover. I use a RemoteEvent
under ReplicatedStorage
and Fire what ClockTime we want a Client to be in. I'll explain this later. If we don't find the player, we can still use this loop for another aspect, whenever a player leaves the Region. If we find a player that is in the Region that has been here before, we set their table value as "checked".
In the second loop, we check which players are not "checked", meaning they aren't in the area anymore. We then fire the other time we want to the client and set their value to nil
(because they aren't in the area anymore). However, if they are checked, we simply set it back to true to repeat this entire process.
Now, I fired data to the client, meaning we need to set up a LocalScript as well.
2 | local ReplicatedStorage, Lighting, TweenService = game:GetService( "ReplicatedStorage" ), game:GetService( "Lighting" ), game:GetService( "TweenService" ) |
4 | ReplicatedStorage.change.OnClientEvent:Connect( function (ct) |
We set up a Connection to receive client-side calls from the RemoteEvent called "changed". As you can see, I have defined some variables: ReplicatedStorage, Lighting (where you change the time), and TweenService (to smoothly change the time). The ct
parameter in the Event is simply the ClockTime property of Lighting that we will change the time to. If you don't know what ClockTime is please see this. Anyways, we will cleanly Tween the day so that it doesn't look forced.
1 | local ReplicatedStorage, Lighting, TweenService = game:GetService( "ReplicatedStorage" ), game:GetService( "Lighting" ), game:GetService( "TweenService" ) |
3 | ReplicatedStorage.change.OnClientEvent:Connect( function (ct) |
4 | ct = tonumber (ct) or Lighting.ClockTime |
5 | TweenService:Create(Lighting, TweenInfo.new( 1 ), { ClockTime = ct } ):Play() |
Now you will have a smooth and efficient way of changing the Time in different areas. Here's the full code:
03 | local Players, ReplicatedStorage, Stepped = game:GetService( "Players" ), game:GetService( "ReplicatedStorage" ), game:GetService( "RunService" ).Stepped; |
04 | local Part = workspace:WaitForChild( "Part" ); |
06 | local Size, Position = Part.Size, Part.Position; |
08 | local Region = Region 3. new(Position-Size/ 2 , Position+Size/ 2 ); |
13 | local PlayersInRegion = { } ; |
15 | while Stepped:Wait() do |
16 | local Reg = game:FindPartsInRegion 3 WithIgnoreList(Region, { Part } , math.huge ); |
18 | for _, obj in pairs (Reg) do |
19 | local Player = Players:GetPlayerFromCharacter(obj.Parent); |
20 | if Player and not PlayersInRegion [ Player ] then |
21 | PlayersInRegion [ Player ] = "checked" ; |
22 | ReplicatedStorage.change:FireClient(Player, 22 ); |
23 | elseif Player and PlayersInRegion [ Player ] then |
24 | PlayersInRegion [ Player ] = "checked" |
27 | for Player, _ in pairs (PlayersInRegion) do |
28 | if PlayersInRegion [ Player ] ~ = "checked" then |
29 | ReplicatedStorage.change:FireClient(Player, 15.5 ) |
30 | PlayersInRegion [ Player ] = nil |
32 | PlayersInRegion [ Player ] = true |
40 | local ReplicatedStorage, Lighting, TweenService = game:GetService( "ReplicatedStorage" ), game:GetService( "Lighting" ), game:GetService( "TweenService" ) |
42 | ReplicatedStorage.change.OnClientEvent:Connect( function (ct) |
43 | ct = tonumber (ct) or Lighting.ClockTime |
44 | TweenService:Create(Lighting, TweenInfo.new( 1 ), { ClockTime = ct } ):Play() |
Happy Coding :)