Roblox塔防游戏击退脚本问题:敌人击退后跳过路径点
问题分析
- 核心矛盾:
- 修改PrimaryPart的CFrame会导致
Humanoid:MoveTo()的WalkToPoint改变,触发moveTo函数里的终止条件,中断当前移动 - 原脚本用
for循环静态遍历路径点,即使通过BindableEvent回退waypoints_hit,循环仍会按原顺序执行,导致敌人直接前往下一个路径点,出现"抄近路"现象
- 修改PrimaryPart的CFrame会导致
解决方案
1. 重构路径点移动逻辑:动态循环替代静态遍历
把固定顺序的for循环改成基于waypoints_hit的while循环,让敌人的移动目标始终跟随当前路径点进度,而非预先设定的遍历顺序。同时对路径点按名称排序,确保移动顺序正确。
2. 修复moveTo函数的终止条件
移除if humanoid.WalkToPoint ~= targetPoint then break end的判断,避免修改CFrame导致移动意外中断,改用手动标记的方式控制循环状态。
3. 调整击退逻辑与方向
修正击退方向为远离当前路径点(向后),同时确保先更新路径点进度再执行位置移动,让敌人的移动目标与新路径点同步。
修改后的代码
敌人移动脚本
-- In case the enemy dies before this script can run, pcall blocks errors. pcall(function(...) -- Constants local humanoid = script.Parent.Humanoid local info = script.Parent.EnemyInfo local waypoints = game:GetService("Workspace").Waypoints local waypoints_hit = 0 -- Not constant, waypoint counter local knockback = script.Parent.Knockback local isMoving = false -- 标记是否正在执行移动任务 -- 排序路径点,确保按编号顺序移动 local sortedWaypoints = waypoints:GetChildren() table.sort(sortedWaypoints, function(a, b) local numA = tonumber(a.Name) or math.huge local numB = tonumber(b.Name) or math.huge return numA < numB end) -- MoveTo() without timeout,移除WalkToPoint判断避免CFrame修改导致中断 local function moveTo(humanoid, targetPoint) isMoving = true local targetReached = false local connection connection = humanoid.MoveToFinished:Connect(function(reached) targetReached = true print("Reached target "..tostring(targetPoint)) connection:Disconnect() connection = nil end) humanoid:MoveTo(targetPoint) while not targetReached do if not (humanoid and humanoid.Parent) then break end humanoid:MoveTo(targetPoint) task.wait(0.1) end isMoving = false if connection then connection:Disconnect() connection = nil end end knockback.Event:Connect(function(...: any) print("Fired") -- 回退路径点,确保不小于0 waypoints_hit = math.max(0, waypoints_hit - 1) script.Parent.EnemyInfo.Waypoint.Value = tostring(waypoints_hit) -- 终止当前移动任务,重新设定目标 if isMoving then humanoid:MoveTo(humanoid.RootPart.Position) task.wait() end -- 获取新的移动目标 local targetPoint if waypoints_hit == 0 then targetPoint = game:GetService("Workspace").SpawnPoint.Position else targetPoint = sortedWaypoints[waypoints_hit].Position end moveTo(humanoid, targetPoint) end) -- Enemy configurations local damage: number = info.Damage.Value -- Damage to base local hp: number = info.HP.Value -- Hit points local speed: number = info.Speed.Value -- Speed -- Set HP and speed humanoid.MaxHealth = hp humanoid.Health = hp humanoid.WalkSpeed = speed -- 动态路径循环:根据waypoints_hit决定下一个目标 while waypoints_hit < #sortedWaypoints do local currentWaypointIndex = waypoints_hit + 1 local currentWaypoint = sortedWaypoints[currentWaypointIndex] if currentWaypoint then moveTo(humanoid, currentWaypoint.Position) waypoints_hit += 1 script.Parent.EnemyInfo.Waypoint.Value = tostring(waypoints_hit) end -- 检查是否到达终点 if waypoints_hit >= 8 then game:GetService("Workspace")["Match Config"].BaseHP.Value -= damage script.Parent:Destroy() break end task.wait() end end)
击退脚本(修正方向与执行顺序)
task.wait(10) local target = game:GetService("Workspace")["Live Enemies"]["Handcuff Arrest Officer"] local waypoint: Part = nil local currentWaypointValue = tonumber(target.EnemyInfo.Waypoint.Value) or 0 if currentWaypointValue == 0 then waypoint = game:GetService("Workspace").SpawnPoint else waypoint = game:GetService("Workspace").Waypoints[currentWaypointValue] end local studsToMove = 5 -- Make sure the model has a PrimaryPart set if target.PrimaryPart then -- 计算击退方向:远离当前路径点(向后) local direction = (target.PrimaryPart.Position - waypoint.Position).unit -- 计算新位置 local newPosition = target.PrimaryPart.Position + direction * studsToMove -- 先触发事件更新路径点,再执行位置移动 target.Knockback:Fire() target:SetPrimaryPartCFrame(target.PrimaryPart.CFrame + (direction * studsToMove)) end
关键修改说明
- 动态路径循环:用
while循环替代for,敌人每次完成移动后才更新路径点索引,中途路径点回退会直接影响下一次的移动目标 - 路径点排序:确保敌人按预设的路径顺序移动,避免因
GetChildren()返回顺序不稳定导致的路径错乱 - 移除WalkToPoint判断:避免修改CFrame导致moveTo函数意外终止,确保移动任务能正常完成
- 击退方向修正:原脚本方向为朝向路径点(向前),修正为反向(向后),符合击退逻辑
- 状态同步:击退时先更新路径点进度再移动位置,确保敌人的移动目标与新路径点一致
内容的提问来源于stack exchange,提问作者Rumi-SE Must Follow the CC-SA
相关产品推荐
相关产品推荐

