Which one gets better performance in these approach?

Hello you!
I’ve come across a dilemma here. Which one is better, using module script or using normal scripts to control the units?

  • What does the code do and what are you not satisfied with?
    For now, it handles the movement of a unit in an RTS-make-army-and-fight game.

  • What potential improvements have you considered?
    For one, using the modular approach lets me have less headache coding the logic in the long run (still more headache-y in the short term though)

  • How (specifically) do you want to improve the code?
    Choose one, I just want to know what’s better
    (Also I accept better code for the timing of when to stop. lol)

Modular Approach :

-- This is an example Lua code block
local _module = require(game:GetService("ServerScriptService"):WaitForChild("UnitMainLogic"):WaitForChild("LandUnit"))

_module.Initialize(script)

Normal Approach :
(Note that module.Initialize is the same as this whole code block)

local  _remotes = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents")
local _logicHelper = require(game:GetService("ServerScriptService"):WaitForChild("UnitLogicHelper"))

local model = script.Parent
local _speed = model.Settings._speed
local _moveVelocity = model.MoveVelocity
local _gyro = model.Gyro

repeat
	wait(0.1)
until model:CanSetNetworkOwnership()
model:SetNetworkOwner(nil)

local function Here()
	local here;
	if model:IsA("BasePart") then
		here = model.Position
	else
		here = model.PrimaryPart.Position
	end
	return here
end

local function ActivatePhysics()
	_moveVelocity.Velocity += Vector3.new(0,-9.81,0)
end

local now = os.time()
function Move (player, unitArray, positionArray)
	now = os.time()
	local _index = _logicHelper.GetUnitIndex(model,unitArray)
	local vector3 = positionArray[_index]
	if vector3 == nil then
		return
	end
	local _rotTarget = Vector3.new(vector3.x,model.Position.y,vector3.z)
	local rotation = CFrame.lookAt(Here(),_rotTarget) 
	local velocity = (vector3 - Here()).Unit * _speed.Value * Vector3.new(1,0,1)	
	_moveVelocity.Velocity = Vector3.new(velocity.x, _moveVelocity.Velocity.y, velocity.z)
	_gyro.CFrame = rotation
	_gyro.MaxTorque = Vector3.new(1,1,1) * 40000000
	
	local _timeTaken = (vector3 - Here()).Magnitude / _speed.Value
	print(_timeTaken)
	
	repeat
		wait(0.1)
	until os.time() - now > _timeTaken
	now = os.time()
	_moveVelocity.Velocity = Vector3.new(0,_moveVelocity.Velocity.y,0)
end


ActivatePhysics()
_remotes.OnSetPosition.OnServerEvent:Connect(Move)

Both code works, but I have a bias that the normal approach works better for performance. Am I imagining things or is there no difference at all?

Also this is why I’m asking :
Blue cuboid is the one with module script,
Green cuboid is the one with normal script.

Or is it that my Initialize() code is just less good?
I do notice some weird times where the unit just stop too early. (see : Green cuboid)

I think the modular approach is better, so therefore you don’t have to keep going around using the same code and just using a simple line of code to initialize something, it also helps because you could add parameters for customization instead of manual customization.

2 Likes

Ok, thanks for your feedback. Have a cookie :cookie: :slight_smile:
I think I might need better code for moving the unit itself.
(See unit movement in The Conquerors 3, that’s what I’m trying to achieve right now)

1 Like

[SOLUTION]

Ok, I have managed to find out the cause of the inaccuracy of my movement system.
Apparently, it’s not a lag or network problem, it’s because I use os.time() which updates at a 1-second interval.
So to overcome this problem, I need to make os.time() update faster.

But how?!

I present to you : (drum rolls ( for _ = 1,10 do print("be rb be brb rb ") wait(0.1) end))
tick()!!
tick() is like os.time() but more cool :sunglasses:
with tick() you can get more precision in time control.

Very, very cool
Now my unit move like TC3 soldiers nicely
Again, very, very :sunglasses:

hey
just curious, but how do you code the select units box?

Hello,
I just ripped the code from an existing dev forum. lol.
Here’s the code if you or anyone wants to use it :

local _player = game.Players.LocalPlayer
local Mouse = _player:GetMouse()
local RunService = game:GetService("RunService")
local camera = workspace.CurrentCamera
local UIS = game:GetService("UserInputService")
local LastHit = Vector2.new(Mouse.x, Mouse.y)
local  Boxselect = _player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("SelectionFrame") ---- Selection Gui
local Cache = {} -- For the Mouse Start and end positions
local _searchParent = script._searchParent.Value


local function SearchForObjects(Objects,HitCache, r1, r2) ---- Math  and conditions and stuff....(Adapted from source above)
	if r1 and r2 then
		local a1, a2 = Vector2.new(math.min(r1.x, r2.x), math.min(r1.y, r2.y)), Vector2.new(math.max(r1.x, r2.x), math.max(r1.y, r2.y));
		local rel, x, y;
		local ObjectsFound = HitCache or {}
		for i, obj in pairs(Objects) do
			if obj == nil then -- Remove destroyed parts
				table.remove(Objects,i)
			end
			rel = camera.CoordinateFrame:ToObjectSpace(obj.CFrame);
			x, y = rel.x / -rel.z, rel.y / -rel.z;
			if (a1.x) < x and x < (a2.x) and (a1.y < y and y < a2.y) and rel.z < 0  then
				ObjectsFound[obj] = obj
			end
		end
		return ObjectsFound
	end
end



local function HitCache(ModelFolder) ----Function For adding mouse target to the hit cache
	if Mouse.Target and table.find(ModelFolder, Mouse.Target)  then
		Cache[Mouse.Target] = Mouse.Target
	end
end



local function CalcSlope(vec) --- Calculate Slope of Object space cords
	local rel=workspace.CurrentCamera.CoordinateFrame:pointToObjectSpace(vec)
	return Vector2.new(rel.x/-rel.z, rel.y/-rel.z)
end







local function ModelsToPart( ModelFolder ) -- Transform any models into parts
	local Table = {}
	for _, obj in  pairs(ModelFolder:GetChildren()) do
		if obj:IsA("Model") then
			local BoundingBox = Instance.new("Part")
			BoundingBox.Name = obj.Name
			BoundingBox.Anchored = true
			BoundingBox.Transparency = 1
			BoundingBox.CanCollide = false
			local AABB_Pos, AABB_Size = obj:GetBoundingBox()
			BoundingBox.Size = AABB_Size
			BoundingBox.CFrame = AABB_Pos
			BoundingBox.Parent = obj
			table.insert(Table , BoundingBox)
		elseif obj:IsA("BasePart") then
			table.insert(Table , obj)
		end
	end
	return Table 
end

local  AllModels = ModelsToPart(_searchParent)
_searchParent.ChildAdded:Connect(function(child)
	table.insert(AllModels,child)
end)
_searchParent.ChildRemoved:Connect(function(child)
	
end)
local MouseDown = false
local StartSlope
local EndSlope



local _time = os.time()
UIS.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		_time = os.time()
		local MousePos =  Vector2.new(Mouse.x, Mouse.y)
		Cache  = {} ---Reset Cache
		Boxselect.Visible = true
		StartSlope = CalcSlope(Mouse.Hit.p) 
		LastHit = MousePos
		HitCache(AllModels)
		MouseDown = true
	end
end)




UIS.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		if os.time() - _time > 0.1 then
			local MousePos =  Vector2.new(Mouse.x, Mouse.y)
			LastHit = MousePos
			EndSlope = CalcSlope(Mouse.Hit.p) 
			HitCache(AllModels)
			local Objects = SearchForObjects(AllModels, Cache , StartSlope, EndSlope)
			local _table = {}
			for _, Obj in pairs(Objects) do
				table.insert(_table,Obj)
				print(Obj.Name.." Found!") --Print What we found
				
				
			end	
			script.OnModelsSelected:Fire(_table)
		end

		MouseDown =false
		Boxselect.Visible = false
	end
end)



RunService.RenderStepped:Connect(function() --- For Selection GUI
	if MouseDown then
		local Hit = Vector2.new(Mouse.x, Mouse.y)
		local 	Distance = (LastHit - Hit).Magnitude
		local Center = (LastHit + Hit) / 2
		local DistX = math.abs(LastHit.X - Hit.X) 
		local DistZ = math.abs(LastHit.Y - Hit.Y)
		Boxselect.Position = Boxselect.Position:Lerp( UDim2.new(0, Center.X,0,  Center.Y), 1) 
		Boxselect.Size =   Boxselect.Size:Lerp( UDim2.new(0, DistX,0, DistZ ), 1) 
	end
end)

I modified it a bit to fit my game, but you can adjust the script by listening to the error messages. Cheers. :smile:

Ok, I found the original post :

Thank you very much! I will check it out.