I'm making a town, and i'd like one side of the town to be night, and the other, day. I do not mean a Day/Night cycle. If that is possible, then i'd like to know how. All help is appreciated, thank you in advance.
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.
local Players, ReplicatedStorage, Stepped = game:GetService("Players"), game:GetService("ReplicatedStorage"), game:GetService("RunService").Stepped; local Part = workspace:WaitForChild("Part"); -- Size Dimensions = <80, 40, 80> local Size, Position = Part.Size, Part.Position; local Region = Region3.new(Position-Size/2, Position+Size/2); --[[ Region3.new() requires 2 vectors, and using those two vectors, creates a "box". In the example above, I use one of the bottom corners and one of the top corners to create a region approx. the size of the part. ]]-- 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).
while Stepped:Wait() do local Reg = game:FindPartsInRegion3WithIgnoreList(Region, {Part}, math.huge); -- Reg is essentially an array with all the parts that are in that region, excluding that part that we have in the workspace for _, obj in pairs(Reg) do local Player = Players:GetPlayerFromCharacter(obj.Parent); if Player and not PlayersInRegion[Player] then PlayersInRegion[Player] = "checked"; ReplicatedStorage.change:FireClient(Player, 22); elseif Player and PlayersInRegion[Player] then PlayersInRegion[Player] = "checked" end end for Player, _ in pairs(PlayersInRegion) do if PlayersInRegion[Player] ~= "checked" then ReplicatedStorage.change:FireClient(Player, 15.5) PlayersInRegion[Player] = nil else PlayersInRegion[Player] = true end end end
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.
-- LocalScript local ReplicatedStorage, Lighting, TweenService = game:GetService("ReplicatedStorage"), game:GetService("Lighting"), game:GetService("TweenService") ReplicatedStorage.change.OnClientEvent:Connect(function(ct) end)
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.
local ReplicatedStorage, Lighting, TweenService = game:GetService("ReplicatedStorage"), game:GetService("Lighting"), game:GetService("TweenService") ReplicatedStorage.change.OnClientEvent:Connect(function(ct) ct = tonumber(ct) or Lighting.ClockTime -- I do this as a sanity check, not necessary TweenService:Create(Lighting, TweenInfo.new(1), {ClockTime = ct}):Play() end)
Now you will have a smooth and efficient way of changing the Time in different areas. Here's the full code:
-- SERVER SCRIPT local Players, ReplicatedStorage, Stepped = game:GetService("Players"), game:GetService("ReplicatedStorage"), game:GetService("RunService").Stepped; local Part = workspace:WaitForChild("Part"); -- put your part here -- Size Dimensions = <80, 40, 80> local Size, Position = Part.Size, Part.Position; local Region = Region3.new(Position-Size/2, Position+Size/2); --[[ Region3.new() requires 2 vectors, and using those two vectors, creates a "box". In the example above, I use one of the bottom corners and one of the top corners to create a region approx. the size of the part. ]]-- local PlayersInRegion = {}; while Stepped:Wait() do local Reg = game:FindPartsInRegion3WithIgnoreList(Region, {Part}, math.huge); -- Reg is essentially an array with all the parts that are in that region, excluding that part that we have in the workspace for _, obj in pairs(Reg) do local Player = Players:GetPlayerFromCharacter(obj.Parent); if Player and not PlayersInRegion[Player] then PlayersInRegion[Player] = "checked"; ReplicatedStorage.change:FireClient(Player, 22); -- change this with your RemoteEvent elseif Player and PlayersInRegion[Player] then PlayersInRegion[Player] = "checked" end end for Player, _ in pairs(PlayersInRegion) do if PlayersInRegion[Player] ~= "checked" then ReplicatedStorage.change:FireClient(Player, 15.5) PlayersInRegion[Player] = nil else PlayersInRegion[Player] = true end end end -- LOCAL SCRIPT local ReplicatedStorage, Lighting, TweenService = game:GetService("ReplicatedStorage"), game:GetService("Lighting"), game:GetService("TweenService") ReplicatedStorage.change.OnClientEvent:Connect(function(ct) -- change this with your remote event ct = tonumber(ct) or Lighting.ClockTime -- I do this as a sanity check, not necessary TweenService:Create(Lighting, TweenInfo.new(1), {ClockTime = ct}):Play() end) --[[ WHAT YOU NEED A RemoteEvent A Part or Two Vector3 Values ]]--
Happy Coding :)
yes, but its not exactly that you can make one place night time.. instead, you make it so when a player goes to a place, some code on client side (in a localscript
) runs to make it night for only that player, and when they leave the place, you make it day time again..
I'm not sure if you can make the world half day and half night. But for players, you can locally change the daytime specifically for them to whatever you want.