This is my third time talking about NPC kart issues. Because the last two threads I posted had been neglected without any reply. Anyway, back onto main topic.
Before this and the two other threads existed, I had been thinking about kart with AI feature for it and had researched by looking for some useful threads on DevForum page, but only found very few of them (the people from there mostly marked Roblox’s built-in pathfinding, which is only for humanoid, as solutions for the whole NPC kart) and yet they weren’t good for my taste.
A while later, I stumbled upon this video on YouTube and made up main tasks for NPC kart. They would be:
- Always set its Throttle value to 1 (forward)
- Force it to drive on first node point of track then check next node by using magnitude (depends on kart’s top speed)
- Use signed angle to check angles between kart and current node points, while it depends on kart’s facing direction. If angle is positive, its Steer value will be set to -1 (left) and vice versa
These tasks did good job for NPC kart, but then I realized that it did not reach the goal like what I saw from that video I showed above. Here’s the only problem: Its steering behavior always turned left and right, and barely drove straight (sometimes got stuck when hit wall), which caused unnatural driving
Code:
(AI script)
local function GetHeadingToPoint(point)
local cframe = DriveSeat.CFrame - DriveSeat.Position + Vehicle.PrimaryPart.Position
return cframe:PointToObjectSpace(point)
end
--Middle of update section
if currentNode then
--print("Go")
while IsAlive() do
task.wait(Rate)
local heading = GetHeadingToPoint(currentNode.Position)
if heading.Magnitude > GetMaxSpeed() / 2 then
local dirToMovePosition = (Vehicle.PrimaryPart.Position - currentNode.Position).Unit
local angleToDir = Math.SignedAngle(Vehicle.PrimaryPart.CFrame.LookVector.Unit, dirToMovePosition, Vector3.FromNormalId(Enum.NormalId.Top))
--print(angleToDir)
--[[if angleToDir > 0 then
DriveSeat.SteerFloat = 1
else
DriveSeat.SteerFloat = -1
end]]
--[[if angleToDir > 5 then
DriveSeat.SteerFloat = 1
elseif angleToDir < -5 then
DriveSeat.SteerFloat = -1
else
riveSeat.SteerFloat = 0
end]]
heading = GetHeadingToPoint(currentNode.Position)
if heading.Unit.Z < -0.25 then
if math.abs(math.deg(math.atan2(heading.X, -heading.Z))) > 5 then
DriveSeat.SteerFloat = -math.sign(heading.Z) * math.deg(math.atan2(heading.X, -heading.Z))
else
DriveSeat.SteerFloat = 0
end
else
if angleToDir > 0 then
DriveSeat.SteerFloat = 1
else
DriveSeat.SteerFloat = -1
end
end
else
break
end
end
end
--
(Kart script)
local Movement = Vector2.new()
Main.DriveSeat.Changed:Connect(function(property)
if property == "Steer" then
Movement = Vector2.new(Main.DriveSeat.Steer, Movement.Y)
elseif property == "Throttle" then
Movement = Vector2.new(Movement.X, Main.DriveSeat.Throttle)
end
end)
local Rotate = 0
local function Steer(direction, amount)
Rotate = (MaxSpeed.Turn.Value * direction) * amount
end
--Middle of update section
if Movement.X ~= 0 then
local dir = Movement.X > 0 and (Values.IsCursed.Value and 1 or -1) or (Values.IsCursed.Value and -1 or 1)
local amount = math.abs(Movement.X)
Steer(dir, amount)
end
--if not (Values.IsStunned.Value or Values.IsFlying.Value or Finished.Value) and IsGoing.Value then
BodyAngularVelocity.AngularVelocity = Vector3.new(0, CurrentSpeed.Turn, 0)
CurrentSpeed.Turn = Math.Lerp(CurrentSpeed.Turn, Rotate * (CurrentSpeed.Movement < 0 and -1 or 1) * (not hit and Stats.TurnSpeed.AerialTurnFactor.Value or 1), dt * Stats.TurnSpeed.TurnTorque.Value)
Rotate = 0
--end
--
To be summarized, comparing my NPC kart to the one from YouTube video, it has unnatural steering behavior. And if you guys understand what topic says, what alternate methods to improve NPC kart’s steering?
p/s: I used BodyAngularVelocity to make it steer, with these following properties:
- MaxTorque: Vector3.new(0, math.huge, 0)
- P: 3000