Car AI/Chasing Module [open-source][o.o.p]

car AI is an user-friendly, open source and OOP module that allows roblox’s cars to do lots of thing, such as chasing players/targets, pathfinding your car through a maze and much more! Here you will find examples, templates, instructions and more.

TRAILER

INSTRUCTIONS

  1. Import your working car model and place it in the workspace ; this means that the model must have a driver seat, and everything must be welded correctly. I suggest editing the car in the template file.

  2. Insert an attachment onto the driver seat and position it near the bumper, as shown in the photo.

  3. Then add a server script into the car model. The script should first require the module, then create a new AI car object (local newAI = mod.new(carModel, bumperAttachment)). Then you only need to choose one of the 3 methods i made to choose how your AI car will drive itself. The code is going to look like this.

EXAMPLES

  • Pathfinding car chasing another car. Here we can see how the car can easily reverse to continue the chase.

    carclip2

  • AI car directly chasing directly a target withouth using pathfinding resulting in a more performance friendly result (good for open maps).

    carclip1

LINKS & DOWNLOAD

Here is the download links of the template model .
And also our discord server if you need any support or help.
Finally here is the link of the full module.

source here
local signal = require(script.Signal)

local carAI = {}

function carAI.new(car : Model, bumper : Attachment)
	local new = setmetatable({}, carAI)
	
	new.car = car
	new.seat = car:FindFirstChildOfClass("VehicleSeat")
	new.pathfindingFailed = signal.new()
	new.pathfindingCompleted = signal.new()
	new.bumper = new.seat:FindFirstChildOfClass("Attachment") or bumper
	
	local seat = new.seat
	local bumper = new.bumper
	
	function new.checkForward()
		local rayParams = RaycastParams.new()
		rayParams.FilterDescendantsInstances = { seat.Parent}

		local vehicleLength = seat.Parent:GetExtentsSize().Z
		local vehicleWidth = math.ceil( seat.Parent:GetExtentsSize().X/2)

		for i = -vehicleWidth, vehicleWidth do
			local result = workspace:Raycast( seat.Position + Vector3.new(i,0,0), seat.CFrame.LookVector*vehicleLength/2,rayParams)
			if result and result.Instance and result.Instance:IsGrounded() then
				return result.Instance
			end
		end
	end
	

	function new.steerToTarget(target : Vector3)
		local rot = math.atan2(target.Z-bumper.WorldPosition.Z,target.X-bumper.WorldPosition.X)

		local desiredAngle = math.deg(rot)+seat.Orientation.Y+90
		if desiredAngle > 180 then
			desiredAngle = -(360-desiredAngle)
		elseif desiredAngle <-180 then
			desiredAngle = 360+desiredAngle
		end	
		
		local turndir = desiredAngle/15
		local speed = math.abs(20/desiredAngle)

		if desiredAngle > 100 or desiredAngle < -100 and (bumper.WorldPosition - target).Magnitude < 10 then
			turndir = -turndir
			speed = -0.2
		end

		seat.ThrottleFloat = speed
		seat.SteerFloat = turndir
		seat.Torque = 6
	end
	


	function new.pathToTarget(target : Part)
		local path = game:GetService("PathfindingService"):FindPathAsync(bumper.WorldPosition, target.Position)
	
		if path.Status == Enum.PathStatus.Success then
			local normalWaypoints = path:GetWaypoints()
			local keyWaypoints = {}
			local diff1 = Vector2.new(0,0)

			for i, v in pairs(normalWaypoints) do
				if i ~= #normalWaypoints then
					local difference = (Vector2.new(v.Position.X,v.Position.Z) - Vector2.new(normalWaypoints[i+1].Position.X,normalWaypoints[i+1].Position.Z))
					local isTrue = workspace:Raycast(v.Position,Vector3.new(0,-5,0))

					if ((diff1 - difference).Magnitude) > 0.5 then
						table.insert(keyWaypoints,v)
					end
					diff1 = difference
				end			
			end

			table.insert(keyWaypoints, normalWaypoints[#normalWaypoints])

			for i, v in pairs(keyWaypoints) do
				local currentDist = math.huge

				while (v.Position - bumper.WorldPosition ).Magnitude > 6 do

					if (bumper.WorldPosition  - v.Position).Magnitude >= currentDist and seat.Velocity.Magnitude < 5 then
						if new.checkForward() then
							local turn = 0.5
							if math.random(2) == 1 then turn = -0.5 end
							seat.ThrottleFloat = -0.2
							seat.SteerFloat = turn
							wait(1)
							seat.ThrottleFloat = 0
							seat.SteerFloat = 0				
						end
					end

					if car == nil then
						break
					end

					currentDist = (bumper.WorldPosition - v.Position).Magnitude
					new.steerToTarget(v.Position)
					wait()
				end
			end

			new.pathfindingCompleted:Fire(true)
		else
			new.pathfindingFailed:Fire(true)
		end

	end
	
	function new.advancedPath(target)
		local params = RaycastParams.new(); params.FilterType = Enum.RaycastFilterType.Exclude; params.FilterDescendantsInstances = {seat.Parent, target}
		local obstacles = workspace:Raycast(seat.Position, target.Position, params)

		if obstacles ~= nil then
			new.pathToTarget(target)
		else
			new.steerToTarget(target.Position)
		end
	end
	
	return new
end

return carAI

This module development started just a couple of days ago and our ai cars are able to go pretty much everywhere. Please help me keep this project alive, and let me down in the comments of the post if you found bugs or any feedback.

Created by @gianfragolo , @asadfai

37 Likes

Honestly super cool work, this will help small time developers out a lot especially with learning AI as it isn’t a super beginner friendly concept. Will check it out myself and play around with it a bit!

2 Likes

Honestly, this actually looks really sick, nice work :+1:

Thanks a lot! im probably gonna keep working on this project too.

Thanks, let me know if you find any bugs or have any ideas of what i could add

This is really helpful, even if there certain outdated functions being used like wait() i’m fine with that, and i mostly do stuff on the client-side that it doesn’t bother me what wait i use and it’s not like they are really easy to replace anyway.

Regardless, thank you very much for making this.

Thanks a lot, ill try fixing my code asap! This is my first model to get such recognition and i will add also a tank chassis/ai included to help people making military games

1 Like

Looks cool. Would be nice to see a video of it in actions instead of an animation.

Hi,

This looks sweet and fun, thanks for sharing!

How can different cars be tuned to do different things? Like one is slow, another med, and another fast?

OR smarter or dumber.

Maybe too, just add a working car with the stuff in it to your example model, so it has an AI model and a car we can drive … meaning a car we can drive that is setup, and the AI car will chase us in the 2nd car we are in…

and can you copy and paste the code of this, so we can do the same?

and or how do I get it to chase me… I have a car…from the tool box… (I tried to mod the AI car and got rid of the dummy and script… but then it flew up in the air)…

Hi! For the speed of the car that is not a problem i am going to implement it that right now since i just need to change a couple of numbers. I can easily make a tetmplate model that chases the player or another car.

CAR AI UPDATE

In this new update i added a new template file that has 2 cars, one of the player and one for the A.I chaser.

Get it for free HERE!

NOTES

I had suggestion to implement a speed parameter to the AI cars but i somehow can’t implement it in my current car (roblox default jeep). The next big update will probably be tank support for the AI. (working tank track, shooting system, max dep., max elev. and more)

CREDITS

@gianfragolo for making it , @Lord_BradyRocks for suggestions and ideas. And whole fancy lobster club for support and help.

1 Like

There are already a few gifs that showcase the Ai. Animation is just a bouns :wink:

Works great but i would suggest you used ShapeCast instead of ray cast because the car can get stuck on the sides and it doesnt alawys detect as a line

Oh that is a good idea i am going to implement it right now!

edit : Are you talking about pathfinding? If yes shapecasts have nothing to with it, neither raycast @BlueDeveloper24

Could you update the code with shapecast(you dont have to use for -i,i if you have shapecast/blockcast)

Edit: Im not talking about pathfinding, im talking about when the car is stuck in front of a part

The only time i used raycast in this module is to check if there are walls in between of the target. I don’t think this would change anything since when obstacles are between the target the system will simply use pathfinding