How to keep the clouds fixed in front of the moon?

Hello everyone!

I’d like to preface this post by mentioning that I’m more of an artist/3d modeler than a programmer. My scripting knowledge boils down to printing ‘hello world’ and changing a part’s color through a script. Regardless, I am a very stubborn noob, and once I notice a problem I can’t move on to anything else until I solve it.

With that being said, here is my issue:

I have created a cloud decal that I pasted on a giant, far away, transparent part that rotates in the sky.

But because this cloud is basically just a big ol’ sticker spinning in front of the moon if the player changes their perspective, e.g. moves too far away, the clouds and moon become misaligned.

Is there a way to prevent this? To keep the clouds always aligned with the moon?

My best guess was to keep the clouds always a fixed distance away from the player and push and pull it along with the player’s movements to give the impression that they are stationary - sort of how a skybox does it. From what I read, the best way of doing this might be using CFrame, but I had no luck in figuring it out.

I did attempt it by piecing together tutorials and bits from other people’s code. I would have gladly posted it here but I completely broke the code while trying to fix it and then deleted it out of frustration. I doubt it could have been salvaged anyway, as it didn’t work at all in the first place and I had no idea what I was doing.

Perhaps there is a better way of doing this that I missed entirely. Either way, any help is very much appreciated. Thank you for your attention!

Can you share how you’re rotating it? Are you doing that on the server (with a Script) or in the client (with a LocalScript)? Or is it using some mover object without a script?

Hello! The rotation is currently being done with a scrip inside the part itself:

image

local cloud = script.Parent

while true do
	cloud.Orientation = Vector3.new(cloud.Orientation.X, cloud.Orientation.Y, cloud.Orientation.Z - 0.01)
	wait (0.01)
end

Great. So delete that script and put a LocalScript in StarterPlayerScripts.

You need to move the thing on the client side, since it’s got to be in a different spot for everyone.

I also moved the rotation here, just so we don’t have the server and client fighting over where the thing should be. I also used CFrame for no reason other than I’m more familiar with it than Orientation.

-- define the part we'll reposition every frame
local part = workspace.Part

-- define the speed at which it'll rotate
local ROT_SPEED = math.rad(10) -- rads/sec

local lighting = game:GetService("Lighting")

-- store the original offset from 0, 0, 0
local offset = part.CFrame

-- store the angle it currently is...
local angle = 0
local function UpdateCloud(dt)
	-- ...and update it every frame based on how long the frame took
	angle += ROT_SPEED * dt
	-- start at the original position...
	part.CFrame = offset
		-- ...rotate by the current angle...
		* CFrame.Angles(0, 0, angle)
		-- ...and offset by the camera's position
		+ workspace.CurrentCamera.CFrame.Position
end

-- do all that every render frame, after the camera updates
game:GetService("RunService"):BindToRenderStep("UpdateCloud", Enum.RenderPriority.Camera.Value + 1, UpdateCloud)
1 Like