How to make a train or a ship move forever?

Hello! I was thinking of making a ship, but I want it to give off the effect that it is moving forever. For example, I have played train games where you are on a train and it is constantly moving through say a tunnel without ending. I don’t know how I would make it so that the ship feels like it is constantly moving through the ocean without an end.

If anyone knows how I would do this, I would really appreciate any help! :slight_smile:

4 Likes

Maybe you can add small waves that ship makes while moving and loop them so it gives the effect of it moving.

Since the only things you’d see while on the open ocean are waves and clouds, put them in!
Also a wake similar to other ship games might help too. I put rolling Cylinders with decals for bow wake, and particles for the actual ship’s wake in this game:
https://www.roblox.com/games/160290799/USS-Bunker-Hill-with-Corsairs

2 Likes

Here’s a hint: move the background, not the ship.

You could do this in many ways, but for a ship, as other people have mentioned, you will probably only see ocean and clouds.

Some suggestions:

  • Particle emitters that shoot “waves” along your ship to give the illusion of movement
  • A wake effect as mentioned above, maybe using a Beam object
  • Clouds that move away from the ship and loop back once they get far enough

You could even add islands that sometimes appear in the distance and move along as if the ship is moving. Some immersive stuff such as the sound of waves, frothing effects along the sides of the ship, etc. would also help. The most important part is to make sure that all moving objects will eventually loop back so that the illusion can be kept going indefinitely.

4 Likes

Thanks alot for your suggestions!

I am not sure how to make them loop back. Do you have any help on this?

Have a script set the position of the objects back to the front of the ship once they reach a certain point.

For example, let’s say you have a ship that appears to be moving in the negative Z direction in global coordinates. A loop is continuously moving some clouds overhead in the positive Z direction to make it look like the ship is moving. Once the clouds reach a good distance, say 1000 in the Z direction, the position of the clouds will be set back to -1000 to begin the cycle again.

Example script:

while wait() do
	cloud.Position = cloud.Position - Vector3.new(0, 0, 1)
	if cloud.Position.Z >= 1000 then
		cloud.Position = Vector3.new(cloud.X, cloud.Y, -1000)
	end
end

Would this script work if I copy it?

Sorry I am not a very good scripter.

I made some corrections and tested it, and it seems to work. But, it only works with one cloud, which you should tweak to your preferences. You should also align it with the ship that you make.

local cloud = Instance.new("Part")
cloud.Anchored = true
cloud.BrickColor = BrickColor.White()
cloud.Position = Vector3.new(0, 100, 0)
cloud.Size = Vector3.new(100, 10, 100)
cloud.Parent = workspace.CurrentCamera

while wait() do
	cloud.Position = cloud.Position + Vector3.new(0, 0, 1)
	if cloud.Position.Z >= 1000 then
		cloud.Position = Vector3.new(cloud.Position.X, cloud.Position.Y, -1000)
	end
end
2 Likes

Thanks so much! I really appreciate the help.

So I just put this script into a part?

The script was written to be put in the Player’s PlayerScripts.

The bottom half of the script (the while loop) could be put into a part if you add this above it:

cloud = script.Parent

But if you are going to have a lot of clouds, it would probably be better if you have one script controlling all them.

Okay. Would the longer script you posted work for multiple clouds? If so, which part would i need to edit?

Here’s a modified version that makes 10 clouds. Just put this into StartPlayerScripts and it should work.

local clouds = {}

for i = 1,10 do  --make 10 clouds
	local cloud = Instance.new("Part")
	cloud.Anchored = true
	cloud.CanCollide = false
	cloud.BrickColor = BrickColor.White()
	cloud.Position = Vector3.new(math.random(-500,500), 100, math.random(-1000,1000))
	cloud.Size = Vector3.new(100, 10, 100)
	cloud.BottomSurface = Enum.SurfaceType.Smooth
	cloud.TopSurface = Enum.SurfaceType.Smooth
	cloud.Parent = workspace.CurrentCamera
	table.insert(clouds, cloud)
end

while wait() do
	for _, cloud in ipairs(clouds) do
		cloud.Position = cloud.Position + Vector3.new(0, 0, 1)
		if cloud.Position.Z >= 1000 then
			cloud.Position = Vector3.new(cloud.Position.X, cloud.Position.Y, -1000)
		end
	end
end
2 Likes

So I make 10 parts, and name them “Cloud” and put them all in the workspace?

This script does all of the cloud making and cloud moving. Just put it into StarterPlayer > StarterPlayerScripts. If you want more clouds, just edit the second number in the for loop (line 3) into anything you want. E.g. for 50 clouds, change it to

for i = 1, 50 do

Since this is client-sided though, not everyone will be seeing the same clouds.

Okay. Which direction does the ship need to face for this to work ?
Sorry so many questions.

No worries.

The ship should be facing the negative Z direction. If you have the orientation block in the top-right of your studio, the blue Z line will be facing towards you when you are looking forwards on the ship.

1 Like

Hey, I was wondering how would I edit the script to make small passing islands too?

You will have to make some islands first. Since they will probably be made of more than one brick, you could move them using :SetPrimaryPartCFrame() for Models.

Here’s a quick and dirty edit:

local clouds = {}
local islands = game:GetService("ReplicatedStorage").Islands:GetChildren()

for i = 1,10 do  --make 10 clouds
	local cloud = Instance.new("Part")
	cloud.Anchored = true
	cloud.CanCollide = false
	cloud.BrickColor = BrickColor.White()
	cloud.Position = Vector3.new(math.random(-500,500), 100, math.random(-1000,1000))
	cloud.Size = Vector3.new(100, 10, 100)
	cloud.BottomSurface = Enum.SurfaceType.Smooth
	cloud.TopSurface = Enum.SurfaceType.Smooth
	cloud.Parent = workspace.CurrentCamera
	table.insert(clouds, cloud)
end

spawn(function()
	while wait(math.random(30, 90)) do  --make an island every 30 to 90 seconds
		local island = islands[math.random(#islands)]:Clone()
		local Y= island.PrimaryPart.Size.Y/2
		local X = math.random(250,1000)*(math.random(0,1)-0.5)*2
		island:SetPrimaryPartCFrame(CFrame.new(X, Y, -1000))
		island.Parent = workspace.CurrentCamera
		spawn(function()
			for Z = -1000, 1000 do
				wait()
				island:SetPrimaryPartCFrame(CFrame.new(X, Y, Z))
			end
			island:Destroy()
		end)
	end
end)

while wait() do
	for _, cloud in ipairs(clouds) do
		cloud.Position = cloud.Position + Vector3.new(0, 0, 1)
		if cloud.Position.Z >= 1000 then
			cloud.Position = Vector3.new(math.random(-500,500), cloud.Position.Y, -1000)
		end
	end
end

I also made one small change to the cloud moving section so that you won’t be seeing the same cloud patterns all the time.

In order for this to work, you need to have a Folder called “Islands” in ReplicatedStorage. Inside this folder you can have any number of different island Models (name them anything you want).

For the islands themselves, you must set the Model’s PrimaryPart to a part that is touching the ocean (the script assumes that sea level is Y = 0).

One last note: the script also assumes that the ship is near or at the origin (0,0,0). The islands move at most 250 studs from the origin. If you want to change this, you will have to edit the numbers on this line:

local X = math.random(250,1000)*(math.random(0,1)-0.5)*2  --range is 250 to 1000 studs
2 Likes

Thanks so much for this. I really appreciate you taking time to help me with all this!