寻找最近的玩家

huangapple go评论66阅读模式
英文:

PathFinding closest Player

问题

路径规划为什么不起作用,我是新手脚本编写者,对我来说这根本没有意义,我明白我的其他代码,我已经阅读了文档,但当涉及到集成路径规划时,只有在他找到最近的玩家并跟随路径时才能找到/创建路径,这让我感到困惑。说实话,阅读文档后,我本以为我可以在if语句内声明路径,以判断玩家是否足够接近,然后他会跟随路径,但我查找了教程,他使用了GetWayPoints(),但我认为这对我没有用,到目前为止,这是我最新的尝试:

local runService = game:GetService("RunService") -- 运行服务类似于Unity的逐帧更新,参见文档保存的文件夹
local players = game:GetService("Players") -- Players将帮助“获取”游戏中的玩家

local humanoid = script.Parent -- 获取脚本的父物体,即人形角色
local root = humanoid.Parent.PrimaryPart -- root是人形角色的父物体,通常是人形角色的根部

local PathfindingService = game:GetService("PathfindingService"); -- 路径规划服务

local wantedDistance = 30 -- 他可以搜索或应该尝试搜索的最大距离,当前值较小,需要进行测试
local stopDistance = 5 -- 以防我们希望使用它使他停止(例如,如果有一个杀伤范围而不是触碰)

local damage = 50
local attackDistance = 8
local attackWait = 1
local lastAttack = tick()
function findNearestPlayer()
    local playerList = players:GetPlayers()
    
    local playerNearest = nil
    local dist = nil
    local direction = nil
    
    for _, player in pairs(playerList) do
        local character = player.Character 
        if character then
            local distanceV = player.Character.HumanoidRootPart.Position - root.Position
            
            if not playerNearest then
                playerNearest = player
                dist = distanceV.Magnitude
                direction = distanceV.Unit
            elseif distanceV.Magnitude < dist then
                playerNearest = player
                dist = distanceV.Magnitude
                direction = distanceV.Unit
            end
        end
    end
    
    return playerNearest, dist, direction
end

runService.Heartbeat:Connect(function()
    local path = PathfindingService:CreatePath()
    local playerNearest, distance, direction = findNearestPlayer()
    
    if playerNearest then
        if distance <= wantedDistance and distance >= stopDistance then
            path:ComputeAsync(humanoid.PrimaryPart.Position, playerNearest.PrimaryPart.Position)
            local waypoints = path:GetWaypoints()
            for _, waypoint in pairs(waypoints)  do
                humanoid:MoveTo(waypoint.Position)
            end
        else 
            humanoid:Move(Vector3.new())
        end

        if distance <= attackDistance and tick() - lastAttack >= attackWait then
            lastAttack = tick()
            playerNearest.Character.Humanoid.Health -= damage
        end
    end
end)

我期望他计算到最近玩家的路径,根据我的代码玩家最近。我真的不明白为什么这样做,或者仅仅告诉他在计算路径后移动到路径位置不起作用。

英文:

Why Isn't Pathfinding working I'm new to scripting and This just doesn't make sense to me I Understan my other code, and I've read the documentation but when it comes to integrating the pathfinding so he will only find/create a path when he had located the nearest player and follow that path has me stumped. To be honest after reading the documentation I would have figured I could just declare the path inside the if statement gauging if the player is close enough and he would follow the path but I looked up a tutorial and he used the GetWayPoints() but I figured that was to be to no avail so far this is my latest attempt

local runService = game:GetService(&quot;RunService&quot;) -- Run Service sort of like unitys Update frame by frame, SEE DOCUMENTATION SAVED FOLDER
local players = game:GetService(&quot;Players&quot;) -- Players will help &quot;get&quot; the players in the game
local humanoid = script.Parent -- grabs the parent of the script which is humanoid
local root = humanoid.Parent.PrimaryPart --root is the humanoids parent i.e models primary part which is typically the humanoid root part
local PathfindingService = game:GetService(&quot;PathfindingService&quot;); -- A path finding service
local wantedDistance = 30 --  How far he can search or should be trying to search, The value now is small testing needed
local stopDistance = 5 -- In caase we want to use this to make him stop (like if he had a kill radius instead of touching)
local damage = 50
local attackDistance = 8
local attackWait = 1
local lastAttack = tick()
function findNearestPlaya()
local playerList = players:GetPlayers()
local playerNearest = nil
local dist = nil
local direction = nil
for _, player in pairs(playerList) do -- basically a for each loop that says for each player in the list of players
local character = player.Character 
if character  then -- will only eggsacute if a player/character exists
local distanceV = player.Character.HumanoidRootPart.Position - root.Position -- Distance  &#39;&#39;Vector&#39;&#39; equals the distance from the player torso/Root position minus the distance of the models primary part which we have as root
if not playerNearest then
playerNearest = player
dist = distanceV.Magnitude -- distance vector magnitude gives us the actual distance
direction = distanceV.Unit -- direction of the nearest player, SEE DOCUMENTATIOIN FOR UNIT AND MAGNITUDE
elseif distanceV.Magnitude &lt; dist then -- If the player is closer than the set nearest player then &#39;&#39;replace&#39;&#39; the player
playerNearest = player -- resets to new player
dist = distanceV.Magnitude
direction = distanceV.Unit
end
end
end
return playerNearest, dist, direction -- function so return which playa and his distance and direction
end
-- Another call from the runService class that runs every &quot;physics frame&quot;, Which I think is like the updateBefore in unity
runService.Heartbeat:Connect(function() -- lua thing essentially this odd function call thing is just an anonymous function meaning it will execute every heartbeat
local path = PathfindingService:CreatePath()
local playerNearest, distance, direction = findNearestPlaya()
if the distance is within range of the wanted distance
if playerNearest  then
if distance &lt;=wantedDistance and distance &gt;= stopDistance then
path:ComputeAsync(humanoid.PrimaryPart.Position, playerNearest.PrimaryPart.Position)
local waypoints = path:GetWaypoints()
for _, waypoint in pairs(waypoints)  do
humanoid.MoveTo(waypoint.Position)
end
else 
humanoid:Move(Vector3.new()) -- 
end
if distance &lt;= attackDistance and tick() - lastAttack &gt;= attackWait then
lastAttack = tick();
playerNearest.Character.Humanoid.Health -= damage
end
end
end)

I was expecting him to calculate the path to the nearest player hints my code player nearest. I really dont understand why that or just telling him to move to path after calculating it wouldnt work

答案1

得分: 0

以下是代码的翻译部分:

local runService = game:GetService("RunService") -- 运行服务,类似于Unity的逐帧更新
local players = game:GetService("Players") -- 玩家服务,用于获取游戏中的玩家

local humanoid = script.Parent -- 获取脚本的父对象,即角色模型
local root = humanoid.Parent.PrimaryPart -- root是角色模型的主要部分,通常是人型角色的根部

local PathfindingService = game:GetService("PathfindingService") -- 寻路服务

local wantedDistance = 30 -- 搜索范围的最大距离
local stopDistance = 5 -- 停止距离(如果要使用此值来使NPC停止移动)

local damage = 50 -- 攻击造成的伤害值
local attackDistance = 8 -- 攻击距离
local attackWait = 1 -- 攻击等待时间
local lastAttack = tick() -- 上次攻击的时间戳

function findNearestPlaya()
	local playerList = players:GetPlayers() -- 获取所有玩家的列表

	local playerNearest = nil
	local dist = nil
	local direction = nil	
	for _, player in pairs(playerList) do
		local character = player.Character
		if character then
			local distanceV = player.Character.HumanoidRootPart.Position - root.Position -- 计算玩家与NPC之间的距离向量

			if not playerNearest then
				playerNearest = player
				dist = distanceV.Magnitude -- 计算距离的大小
				direction = distanceV.Unit -- 计算距离的单位方向向量
			elseif distanceV.Magnitude < dist then
				playerNearest = player
				dist = distanceV.Magnitude
				direction = distanceV.Unit
			end
		end
	end

	return playerNearest, dist, direction
end

runService.Heartbeat:Connect(function()
	local playerNearest, distance, direction = findNearestPlaya()

	if playerNearest and distance <= wantedDistance then
		local path = PathfindingService:CreatePath() -- 创建新的寻路路径
		path:ComputeAsync(root.Position, playerNearest.Character.HumanoidRootPart.Position) -- 计算路径,从NPC位置到最近玩家的位置
		local waypoints = path:GetWaypoints() -- 获取路径上的路标点

		for _, waypoint in pairs(waypoints) do
			humanoid:MoveTo(waypoint.Position) -- 沿着路径移动NPC
			humanoid.MoveToFinished:Wait() -- 等待移动完成
		end
	end

	if distance <= attackDistance and tick() - lastAttack >= attackWait then
		lastAttack = tick()
		playerNearest.Character.Humanoid.Health -= damage -- 攻击最近的玩家
	end
end)

希望这有助于理解代码的功能。

英文:

Here is the solved version comments should do a good job of explaining but essentially I was just being dumb I was harping to much on the direction as long as you ommit that you can essentially guide the NPC as long as he is in range instead of updating every player playerNearest path, the heartbeat function is already handling that all that's required is to create a new path for each player that is nearest then guide him along that path. The script isn't perfect but this will find the nearest player and create a path for the NPC to follow each time for a different nearest player (I'm bad at explanations and I've dragged this on for too long just read the comments)

local runService = game:GetService(&quot;RunService&quot;) -- Run Service sort of like unitys Update frame by frame, SEE DOCUMENTATION SAVED FOLDER
local players = game:GetService(&quot;Players&quot;) -- Players will help &quot;get&quot; the players in the game
local humanoid = script.Parent -- grabs the parent of the script which is humanoid
local root = humanoid.Parent.PrimaryPart --root is the humanoids parent i.e models primary part which is typically the humanoid root part
local PathfindingService = game:GetService(&quot;PathfindingService&quot;); -- A path finding service
local wantedDistance = 30 --  How far he can search or should be trying to search, The value now is small testing needed
local stopDistance = 5 -- In caase we want to use this to make him stop (like if he had a kill radius instead of touching)
local damage = 50
local attackDistance = 8
local attackWait = 1
local lastAttack = tick()
function findNearestPlaya()
local playerList = players:GetPlayers()
local playerNearest = nil
local dist = nil
local direction = nil	
for _, player in pairs(playerList) do -- basically a for each loop that says for each player in the list of players
local character = player.Character 
if character  then -- will only eggsacute if a player/character exists
local distanceV = player.Character.HumanoidRootPart.Position - root.Position -- Distance  &#39;&#39;Vector&#39;&#39; equals the distance from the player torso/Root position minus the distance of the models primary part which we have as root
if not playerNearest then
playerNearest = player
dist = distanceV.Magnitude -- distance vector magnitude gives us the actual distance
direction = distanceV.Unit -- direction of the nearest player, SEE DOCUMENTATIOIN FOR UNIT AND MAGNITUDE
elseif distanceV.Magnitude &lt; dist then -- If the player is closer than the set nearest player then &#39;&#39;replace&#39;&#39; the player
playerNearest = player -- resets to new player
dist = distanceV.Magnitude
direction = distanceV.Unit
end
end
end
return playerNearest, dist, direction -- function so return which playa and his distance and direction
end
-- Another call from the runService class that runs every &quot;physics frame&quot;, Which I think is like the updateBefore in unity
runService.Heartbeat:Connect(function() -- lua thing essentially this odd function call thing is just an anonymous function meaning it will execute every heartbeat
local playerNearest, distance, direction = findNearestPlaya()	
-- if the distance is within range of the wanted distance
if playerNearest and distance &lt;= wantedDistance  then
local path = PathfindingService:CreatePath(); -- Now if hes in range of the player create a new path
path:ComputeAsync(root.Position, playerNearest.Character.HumanoidRootPart.Position) -- compute the path with the positions of the player and Dr. Sturgeon
local waypoints = path:GetWaypoints()  -- Assign a new waypoint and and gathers the paths 
-- standard for each loop for the nodes SEE DOCUMENTATION/TUTORIALS TO UNDERSTAND &#39;&#39;NODES&#39;&#39;
for _, waypoint in pairs(waypoints)  do 
humanoid:MoveTo(waypoint.Position) -- For each waypoint/node move Dr. sturgeon to it until it reaches the computed path i.e the distance from the player to the robot vice a versa
humanoid.MoveToFinished:Wait()
end
end
if distance &lt;= attackDistance and tick() - lastAttack &gt;= attackWait then
lastAttack = tick();
playerNearest.Character.Humanoid.Health -= damage
end
end)

huangapple
  • 本文由 发表于 2023年6月2日 02:50:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384865.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定