Touching areas that would be in contact with the sun's light

The main idea is that, as you could somewhat infer from the topic’s title, if a player makes contact with an area that is under direct contact with the sun’s light on, a script would run. E.g. if the player is in a building and leaves it, going out into an area where the sun would be able to “shine” on them, i.e. no shadows, then the appropriate script would run.

However, I can’t seem to think of a legitimate way to do this - I’ve thought of making it so there’s a model/folder that holds parts that will be manually placed under areas with sunlight, and once those are touched, the scripts would run, though as you can imagine, while it works, it isn’t the most effective way to go about the problem.

If more details are needed, please ask, this is my first time using this feature (scripting support), so I’m not entirely sure whether this is a satisfactory/workable amount of detail.

9 Likes

In case you’re satisfied with detecting whether a player has a roof above their head, you could opt for a short (~10 studs) ray directly upwards to check if there’s something above them. Repeating this frequently should give a more or less accurate result. This of course wouldn’t work for

but it’d work to simulate ‘outside’ and ‘inside’ lighting. Performance-wise a ray this short would cause little problems, just make sure to keep it short.

1 Like

Because lighting is handled internally by Roblox, you can’t precisely measure the light’s landing spots. To determine lighting, you can utilize part.Transparency. This will help because transparent surfaces allow light through, while opaque surfaces do not. Like @TaaRt’s solution, you could use a raycast upwards to detect a roof but the problem here is that light can shine in many directions. To fix this, you can either:

  • Scan through a parts list and detect where parts are transparent and calculate the player’s distance accordingly to determine angle and whether or not they are in the light.
  • Raycast in a bunch of directions and see which part is transparent. (Apparently you can raycast thousands of times a second if it’s done once, so this shouldn’t be an issue at intervals)
2 Likes

A hacky and very bad way to do this is by hard coding the environment conditions, lets take the image below as an example:

Imagine a player is standing in the shadow


At ClockTime 7, the sun light is blocked by the part

Not until ClockTime 11, the sun light is directly on the area that was once covered:

So between 7 and 11 am, the script won’t run, anything after 11 and let’s say 17, the script will run.

Another concern is having the player in the right spot and right time, it would probably take some more hard coding :woman_shrugging:

1 Like

Thanks for your replies.

In regards to this, as you mentioned, it would work regardless of whether a shadow is present or not, however the sun’s ability to become in contact with the player is an essential part of the game, you could say that without it, the rest of the game becomes unplayable, where shadows as also important.

I can imagine this method working, however it seems it may be a little difficult to replicate. As a novice to using rays, the wiki on Rays basically gives me the idea that for this, you need to loop around creating multiple rays in half the possible directions (excluding below player) and then somehow see what parts these rays come in contact with, along with that part’s transparency - correct me if I’m wrong on that part. So, that would work for things like being inside, but say you’re outside and in a shadow of a wall, how would that work, seeing as half of the rays would tell you that the parts on that side are there, whilst the other half would tell you that the sun’s there? Like I said, I’ve never used rays before, so this is just theoretically based.

The game won’t have a day and night cycle, to be specific, it’ll be fixed to a certain time - I don’t know what time seeing as this isn’t my idea and I, personally, don’t know too much about the genre itself.

Also, as you said, it’s a “very bad” way to do this.

If the ray’s hit object returns nil, you can infer that the player is outside and therefore assume it’s in the light.

1 Like

I see, but then, how would that account for shadows, since if you’re in a shadow, logically speaking you;d have some ray’s return nil, and some not return nil. Thinking about it even more, I mentioned earlier using rays in all directions, but if I also look at that in a logical perspective, then due to horizontal rays, if the player was on the same x axis to the building, then certain rays would go off?

Like I said, I’m an absolute novice to rays and ray casting, and honestly speaking, I don’t fully understand the concept. If you find it a little difficult to explain to a total novice (not that I can blame you, I’d find it hard myself), then could you provide possible sources for a way to understand?

Thanks.

1 Like

I doubt this would be very resource friendly, but one solution is to index all the parts that cast shadows, then re-create the algorithm that figures out how objects cast shadows and use that to find if the character is within that region.

I’m confident you could easily plot a few points and get some nice regions to go off of.

Now, I wouldn’t recommend this because to do this for thousands of 3d objects in lua, your CPU might as well catch fire right now.

3 Likes

i was thinking about this recently. isn’t there some clever maths that could be done with Lighting.GeographicLatitude/Lighting:GetSunDirection()?

2 Likes

I don’t know how large the map would be, but seeing as it’s SCP, i.e. Sci-Fi Genre, I’d assume that there would be lots of smaller parts around the map for finer details, where this, as you mentioned, wouldn’t be very resource friendly and wouldn’t guarantee that the actual game would be in a playable state (gaming computers only, for example).

I’m inquiring into this with the actual map creator, but assuming that we use this, this mentions that the size of a shadow is the Object’s Height/Sun tangent. Getting the object’s height would be a simple matter, but for the sun tangent you’d need to do math.tan(altitude), how would you access the altitude of the sun? Or is this something that’s assumed through the time of day? After you work out the shadow’s length, would you use Lighting:GetSunDirection to figure out which direction the shadow actually lies?

1 Like

In reality, you could honestly just plug in numbers until it looks about right, once you get to about 10000, 10k and 30k really don’t change the shadows that much since the graph is exponential.

If you wanted a solution which detects shadows, you could cast a ray from the player to the sun. If anything intersects, the player is in a shadow. If nothing does, then you are fine. Getting the sun’s position would be a challenge, but it would most likely just be some math.

Wouldn’t you be able to locate the position using Rays and Lighting:GetSunDirection, seeing as the direction is from (0,0,0), then you should, in theory, be able to use Rays to find it? Or is this not feasible? As I mentioned in an earlier post, I’m a novice to Rays, with my only knowledge on it being when I wiki searched Rays 1 hour ago.

If I could figure out the details, it seems like this is probably the best/most efficient method (that I can use and understand) for this task.

They said that the map would be pretty huge, so if you add in a lot of minute details to a large map, then put this on top, I doubt players would be able to play for long, if at all.

Though, thanks for your suggestion.

1 Like

Make a ray from the character 100 units up to the sun. You would have to figure out the difference in the direction depending on the player position.

If you are worried about lag, do not calculate every frame and only calculate every few seconds. Additionally, change the 100 studs to a smaller value. Rays are not very expensive if you do not overuse them.

local rayy = Ray.new(rootPart.Positon, upToSunDirection*100)
local part = workspace:FindPartOnRay(rayy)
if not part then
--Outside
else
--Inside
end
1 Like

I see, that code reference is both helpful in the sense of code and with helping me ascertain what you were talking about in that post. I understand what you’re saying, so as a question to this:

(In order to find the value of the variable upToSunDirection)

If I were to use Lighting:GetSunDirection to figure out the direction the sun is from (0,0,0). Then use something like a ray (Would that work?) between the player and (0,0,0) to find the direction from the player to there (or vice versa), then use some maths like trigonometry (?) to figure out the direction between the player and the sun, would that work? Perhaps I’m misunderstanding the function between Lighting:GetSunDirection, so I’ll experiment with it in studio for a bit.

EDIT: Attempting to load studio crashed my device - further investigation results in errors being displayed in relation to loading places, so I may be unable to test this. (EDIT: Got it open, testing now 11m after posting)

I set up a quick test using a relatively short ray (30 studs) aimed at the direction from the sun, it appears to do roughly what you are looking for (localscript in a player character)

local rayDirection = game.Lighting:GetSunDirection()

local char = game.Players.LocalPlayer.Character

local RAY_LENGTH = 30

game:GetService("RunService"):BindToRenderStep("SunService",Enum.RenderPriority.Camera.Value + 1,function()
	local ray = Ray.new(char.HumanoidRootPart.Position,rayDirection * RAY_LENGTH)
	local partFound = workspace:FindPartOnRay(ray,char)
	if partFound then
		print("Found something blocking sun:",partFound)
	else
		print("No shadow")
	end
end)

game.Lighting:GetPropertyChangedSignal("TimeOfDay"):Connect(function()
	rayDirection = game.Lighting:GetSunDirection()
end)

It binds a function to renderstep which checks whether there are parts on the ray cast starting from the character and extending 30 studs in the direction of the sun. The main limitations are the ray length versus performance; it may become an issue if the sun is high up and the ray length doesn’t suffice to detect a part there.

40 Likes

Aye. thanks, it seems to work after testing it a few times in different scenarios. Seems like I was over-thinking things when it came to the sun’s direction.

Though I’m marking your post as the solution, I’d still like to give credit to @REALTimothy0812 as his explanation was helpful in actually understanding what that code that you’ve provided does, as in the end, if I don’t learn from this and just copy your code, it wouldn’t be very productive. :stuck_out_tongue:

5 Likes