How would I manage thousands of units using raycasts to move in an RTS game?

I am using Atrazine’s guide on lowering network usage in RTS games. Some of the things he does is not render the units on the server and CFraming the units.

I am trying to replicate how he moves his units. Using his method, he uses a heightmap to get and move units along the y-axis. I don’t know how I would make a heightmap and so I am currently using raycasts.
The problem arises that I am using two raycasts per unit per second. This adds up as each unit is grouped into regiments.

Is there any other method I can use that still involves CFraming the units (on the client side) while still have the units be able to react to height changes that is scalable to 1000 or so units?

I should note that raycasts don’t fire while a unit is moving. The beginning of a round is going to be resource intensive as all the players are moving their units.

What exactly are you asking? Simple words please.

A heightmap is where darker spots are higher and lighter spots are lower. Just use like Inkscape or Krita

I’m trying to replicate games like the Total War and Warhammer series where they have thousands of units moving.

I’m currently trying to find a more efficient way to determine the y-coordinate of the unit while it moves.

How would I implement a heightmap though?

So you basically want to keep doing part.Position.Y?

Yeah, I’m trying to move the units up and down based on terrain since they use CFrames instead of physics

Could I have a picture or video or code snippet? Or maybe a drawing of your visualization?

You’ve been awfully quiet, and I can’t find the ‘RE’ So I’ll just repost the code:

local meanpoint = Vector2.new(0,0) -- the X and Z for the middle of all the raycasting
local castsize = Vector2.new(100,100) -- the X and Z sizes for all the raycasting
local castdistance = 0.1 -- the distance between each raycast
local castheight = 1000 -- the distance up for the raycast
local castdist = 3000 -- the distance downard for the raycast

castsize += Vector2.new(castdistance,castdistance) -- for reasons
local half = castsize/2
local start = meanpoint - half
local endpoint = meanpoint + half

local factor = 1/castdistance

local raycasttable = {}

local xdif = -start.X
local zdif = -start.Y

-- NOTE: with the current size, it will take about 1/4 minute, and this is for 100 by 100 studs, so be aware of the time of this code

for x = start.X, endpoint.X, castdistance do
	task.wait() -- give it a little break between each couple raycasts or if your size is less than 2048*2048, then you can probably omit this, it just might take a while
	inner = {}
	table.insert(raycasttable, inner)
	for z = start.Y, endpoint.Y, castdistance do
		local zindex
		local params = RaycastParams.new()
		params.IgnoreWater = false
		params.RespectCanCollide = true -- if this wasn't on, then your characters might be walking on untouchable parts
		local result = workspace:Raycast( -- raycast of course
			Vector3.new(x, castheight, z),
			Vector3.new(0, -castdist, 0),
			params
		)
		if not result then continue end
		table.insert(inner, result.Position.Y) -- set the y
	end
end

local function gety(x,z) -- so we know the distance is castdistance
	local exactx = math.round(x*factor)/factor
	local exactz = math.round(z*factor)/factor
	local xindex = math.round((exactx+xdif)*factor + 1)
	local zindex = math.round((exactz+zdif)*factor + 1)
	local y = raycasttable[xindex][zindex]
	-- if you wanted you could add something to smooth it out
	return y
end

local randompartpos = Vector3.new(-17.9,0,-50)
local y = gety(randompartpos.X, randompartpos.Z)
print(y)
1 Like

Hi yes, sorry I did get it to work. I will let you know the results and help you with your issue when I’m back from school

2 Likes

I fixed my issue already. Thanks for being willing!

Found the ‘RE’