Yol Bulma

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Yol Bulma, bir karakterin veya nesnenin (ajan) bir hedefe ulaşmak için engeller etrafında mantıksal bir yol boyunca hareket etme sürecidir; isteğe bağlı olarak tehlikeli maddelerden veya tanımlı bölgelerden kaçınabilir.

Yol bulma düzeni ve hata ayıklama konusunda yardımcı olmak için, Studio bir navigasyon ağı ve modifikatör etiketleri oluşturabilir. Bunları etkinleştirmek için, 3D görünüm alanının sağ üst köşesindeki Görselleştirme Seçenekleri aracından Navigasyon ağı ve Yol Bulma modifikatörleri seçeneklerini açın.

Görselleştirme Seçenekleri butonunun sağ üst köşede belirtildiği 3D görünüm alanının yakın çekim görüntüsü.

Navigasyon ağı etkinleştirildiğinde, renkli alanlar bir karakterin yürüyebileceği veya yüzebileceği yerleri gösterir. Küçük oklar, bir karakterin zıplayarak ulaşmaya çalışacağı alanları gösterir.

Studio'da gösterilen navigasyon ağı

Uygulama

Yol bulma, PathfindingService ve CreatePath() gibi ilişkili yöntemler aracılığıyla çeşitli şekillerde uygulanabilir; bu bölüm, oyuncunun karakteri için aşağıdaki yol bulma betiğini kullanır.

Okurken test etmek için:

  1. ÖNEMLİ
    Explorer içinde StarterPlayer konteynerini seçin. Ardından, Özellikler penceresinde DevComputerMovementMode ve DevTouchMovementMode değerlerini Scriptable olarak ayarlayın.

  2. Aşağıdaki kodu LocalScript içine StarterCharacterScripts içinde kopyalayın veya bu paketi alın ve StarterCharacterScripts içine bırakın.

    PlayerPathFollow (StarterCharacterScripts içindeki LocalScript)
    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local DESTINATION = Vector3.new(20, 0.5, 20)
    local GROUND_WAIT = 0.01
    local VELOCITY_MULTIPLIER = 0.0625
    local path = PathfindingService:CreatePath({
    AgentCanClimb = true,
    Costs = {
    Water = 20
    }
    })
    local character = script.Parent
    local humanoid = character:WaitForChild("Humanoid")
    local waypoints
    local nextWaypointIndex
    local blockedConnection
    local currentWaypointReachedConnection
    local currentWaypointPlaneNormal = Vector3.zero
    local currentWaypointPlaneDistance = 0
    local pathfinderWorking = false
    local function disconnectCurrentWaypointReachedConnection()
    if not currentWaypointReachedConnection then return end
    currentWaypointReachedConnection:Disconnect()
    currentWaypointReachedConnection = nil
    end
    local function isCurrentWaypointReached()
    if humanoid.FloorMaterial == Enum.Material.Air then
    return false
    end
    local reached = false
    if currentWaypointPlaneNormal ~= Vector3.zero then
    -- Humanoid ile hedef düzlem arasındaki mesafeyi hesapla
    local dist = currentWaypointPlaneNormal:Dot(humanoid.RootPart.Position) - currentWaypointPlaneDistance
    -- Humanoid hızının düzleme doğru olan bileşenini hesapla
    local velocity = -currentWaypointPlaneNormal:Dot(humanoid.RootPart.Velocity)
    -- Humanoid hızına dayalı olarak hedef düzlemden hesaplanan eşik
    local threshold = math.max(1.0, VELOCITY_MULTIPLIER * velocity)
    -- Düzlemin önünde eşik değerinden daha azsa waypoint'in ulaşıldığını kabul et
    reached = dist < threshold
    else
    reached = true
    end
    if reached then
    currentWaypointPlaneNormal = Vector3.zero
    currentWaypointPlaneDistance = 0
    moveToNextWaypoint()
    end
    end
    local function calculateNextWaypointApproach()
    nextWaypointIndex += 1
    if nextWaypointIndex > #waypoints then
    return false
    end
    local currentWaypoint = waypoints[nextWaypointIndex - 1]
    local nextWaypoint = waypoints[nextWaypointIndex]
    -- Mevcut olanın yanına gelecek şekilde bir düzlem oluştur
    currentWaypointPlaneNormal = currentWaypoint.Position - nextWaypoint.Position
    -- Yukarı tırmanmıyorsanız Y düzlemine dik normal ayarlayın
    if nextWaypoint.Label ~= "Climb" then
    currentWaypointPlaneNormal = Vector3.new(currentWaypointPlaneNormal.X, 0, currentWaypointPlaneNormal.Z)
    end
    if currentWaypointPlaneNormal.Magnitude > 0.000001 then
    currentWaypointPlaneNormal = currentWaypointPlaneNormal.Unit
    currentWaypointPlaneDistance = currentWaypointPlaneNormal:Dot(nextWaypoint.Position)
    end
    return true
    end
    local function resetWaypointData()
    humanoid:Move(Vector3.zero)
    currentWaypointPlaneNormal = Vector3.zero
    currentWaypointPlaneDistance = 0
    disconnectCurrentWaypointReachedConnection()
    pathfinderWorking = false
    end
    local function waitForGround()
    while humanoid.FloorMaterial == Enum.Material.Air do
    task.wait(GROUND_WAIT)
    end
    end
    function moveToNextWaypoint()
    if calculateNextWaypointApproach() then
    disconnectCurrentWaypointReachedConnection()
    currentWaypointReachedConnection = RunService.Heartbeat:Connect(isCurrentWaypointReached)
    local nextWaypointPosition = waypoints[nextWaypointIndex].Position
    local nextWaypointAction = waypoints[nextWaypointIndex].Action
    humanoid:Move(nextWaypointPosition - humanoid.RootPart.Position)
    if waypoints[nextWaypointIndex + 1] and waypoints[nextWaypointIndex + 1].Label == "UseBoat" then
    nextWaypointIndex += 1
    -- Ajanın botu kullanmasını sağlamak için kendi özelleştirilmiş fonksiyonunuzu çağırın
    elseif nextWaypointAction == Enum.PathWaypointAction.Jump then
    humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
    while humanoid.FloorMaterial ~= Enum.Material.Air do
    task.wait(GROUND_WAIT)
    end
    humanoid:Move(nextWaypointPosition - humanoid.RootPart.Position)
    end
    else
    resetWaypointData()
    end
    end
    local function findStartingPoint(waypoints)
    nextWaypointIndex = 1
    while nextWaypointIndex + 1 <= #waypoints do
    local dist = waypoints[nextWaypointIndex + 1].Position - humanoid.RootPart.Position
    dist = Vector3.new(dist.X, 0, dist.Z)
    if dist.magnitude >= 2 then
    return
    end
    nextWaypointIndex += 1
    end
    end
    local function followPath()
    -- Yolu hesapla
    pathfinderWorking = true
    waitForGround()
    local success, errorMessage = pcall(function()
    path:ComputeAsync(character.PrimaryPart.Position, DESTINATION)
    end)
    if not success or path.Status ~= Enum.PathStatus.Success then
    warn("Yol hesaplanamadı!", errorMessage)
    return
    end
    -- Yol noktalarını al
    waypoints = path:GetWaypoints()
    -- Yolun engellendiğini tespit et
    blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
    -- Engel yolun daha ilerinde mi kontrol et
    if blockedWaypointIndex >= nextWaypointIndex then
    -- Yol yeniden hesaplanana kadar yol engelini tespit etmeyi durdur
    blockedConnection:Disconnect()
    resetWaypointData()
    -- Yeni yolu yeniden hesaplamak için fonksiyonu çağır
    followPath()
    end
    end)
    findStartingPoint(waypoints)
    moveToNextWaypoint()
    end
    followPath()
  3. DESTINATION değişkenini (

    SATIR 5
    ) oyuncu karakterinin ulaşabileceği bir Vector3 hedefi ile düzenleyin.

  4. Yol hesaplama ve karakter hareketi hakkında bilgi edinmek için aşağıdaki bölümlerden devam edin.

Yol oluşturma

Yol bulma, PathfindingService ve CreatePath() yöntemi aracılığıyla başlatılır (

SATIR 9–14
). Bu yöntem, karakterin (ajan) yol boyunca nasıl hareket edeceğini ince ayar yapmak için isteğe bağlı bir parametreler tablosu alır.

AnahtarAçıklamaTürVarsayılan
AgentRadiusAjan yarıçapı, stud cinsinden. Engellerden minimum ayrımı belirlemek için kullanışlıdır.tam sayı2
AgentHeightAjan yüksekliği, stud cinsinden. Bu değerden daha küçük boşluklar, merdivenlerin altındaki alan gibi, geçilemez olarak işaretlenecektir.tam sayı5
AgentCanJumpYol bulma sırasında zıplamanın izin verilip verilmediğini belirler.booleantrue
AgentCanClimbYol bulma sırasında TrussParts tırmanmanın izin verilip verilmediğini belirler. Tırmanılabilir bir yolun Label adı Climb olmalıdır ve tırmanılabilir bir yolun maliyeti varsayılan olarak 1'dir.booleanfalse
WaypointSpacingYol boyunca ara waypoint'ler arasındaki mesafe. math.huge olarak ayarlanırsa, ara waypoint'ler olmayacaktır.number4
CostsGeçiş için malzemelerin veya tanımlı PathfindingModifiers tablosu ve maliyetleri. Ajanın belirli malzemeleri/bölgeleri diğerlerine tercih etmesi için kullanışlıdır. Ayrıntılar için modifikatörlere bakın.tablenil

Yol hesaplama

Geçerli bir yolu CreatePath() ile oluşturduktan sonra, bu yol hesaplanmalıdır; bu, başlangıç noktası ve hedef için Vector3 ile Path:ComputeAsync() çağrılarak yapılır (

SATIR 133–139
).

İki köprü arasında işaretlenmiş yol başlangıcı/bitişi

Path hesaplandıktan sonra, başlangıçtan sona kadar olan yolu izleyen bir dizi waypoint içerecektir. Bu noktalar, Path:GetWaypoints() yöntemi ile toplanabilir (

SATIR 142
). Döndürülen dizi, yol başlangıcından yol sonuna kadar olan waypoint'ler sırasına göre düzenlenmiştir.

Hesaplanan yol boyunca gösterilen waypoint'ler
Hesaplanan yol boyunca gösterilen waypoint'ler

Yol hareketi

Her PathWaypoint, bir Position (Vector3) ve Action (PathWaypointAction) içerir. Tipik bir Roblox karakteri gibi bir Humanoid içeren bir karakteri hareket ettirmek için en iyi yol, waypoint'ten waypoint'e Humanoid:Move() çağrısı yapmak ve karakterin her waypoint'e ulaşıp ulaşmadığını tespit etmek için betiğin isCurrentWaypointReached() geri çağrısını kullanmaktır (

SATIR 32–56
).

Engellenmiş yollar

Birçok Roblox dünyası dinamik olup; parçalar hareket edebilir veya düşebilir ve zeminler çökebilir. Bu, hesaplanan bir yolu engelleyebilir ve karakterin hedefine ulaşmasını engelleyebilir. Bunu ele almak için, Path.Blocked olayına bağlanabilir ve engelleyen nesnenin etrafında yolu yeniden hesaplayabilirsiniz (

SATIR 145–154
).

Yol Bulma Modifikatörleri

Varsayılan olarak, Path:ComputeAsync() başlangıç noktası ile hedef arasındaki en kısa yolu döndürür; zıplamalardan kaçınmaya çalışır. Bu bazı durumlarda doğal görünmez; örneğin, bir yol, suyun etrafında değil, suyun içinden geçebilir çünkü su içindeki yol geometrik olarak daha kısadır.

İki yol gösteriliyor; daha kısa yol mantıklı olmayabilir

Yol bulmayı daha da optimize etmek için, çeşitli malzemeler üzerinden, tanımlı bölgelerin etrafında veya engelleri yok saymak için yol bulma modifikatörleri uygulayabilirsiniz.

Malzeme maliyetleri

Terrain ve BasePart malzemeleri ile çalışırken, belirli malzemelerin diğerlerinden daha geçilebilir olmasını sağlamak için CreatePath() içinde bir Costs tablosu ekleyebilirsiniz. Tüm malzemelerin varsayılan maliyeti 1'dir ve herhangi bir malzeme, değerini math.huge olarak ayarlayarak geçilemez olarak tanımlanabilir.

Costs tablosundaki anahtarlar, Enum.Material adlarını temsil eden string isimler olmalıdır; örneğin, Enum.Material.Water için Water veya Enum.Material.CrackedLava için CrackedLava.

PlayerPathFollow (LocalScript)
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local DESTINATION = Vector3.new(20, 0.5, 20)
local GROUND_WAIT = 0.01
local VELOCITY_MULTIPLIER = 0.0625
local path = PathfindingService:CreatePath({
AgentCanClimb = true,
Costs = {
Water = 20, CrackedLava = 100, Slate = 20
}
})

Bölgeleri yapılandırma

Bazı durumlarda, malzeme tercihi yeterli olmayabilir. Örneğin, karakterlerin altındaki malzemelerden bağımsız olarak tanımlı bir bölgeden kaçınmasını isteyebilirsiniz. Bu, bir parçaya bir PathfindingModifier nesnesi ekleyerek gerçekleştirilebilir.

  1. Bölgeyi tanımlamak için etrafında Anchored bir parça oluşturun ve CanCollide özelliğini false olarak ayarlayın.

    Yol bulma modifikatörünü uygulamak için bir bölge tanımlayan sabit parça.
  2. Parçaya bir PathfindingModifier örneği ekleyin, Label özelliğini bulun ve DangerZone gibi anlamlı bir isim atayın.

    Label özelliği DangerZone olarak ayarlanmış PathfindingModifier örneği.
  3. CreatePath() içindeki Costs tablosuna eşleşen bir DangerZone anahtarı ve ilişkili sayısal değer ekleyin. Bir modifikatör, değerini math.huge olarak ayarlayarak geçilemez olarak tanımlanabilir.

    PlayerPathFollow (LocalScript)
    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local DESTINATION = Vector3.new(20, 0.5, 20)
    local GROUND_WAIT = 0.01
    local VELOCITY_MULTIPLIER = 0.0625
    local path = PathfindingService:CreatePath({
    AgentCanClimb = true,
    Costs = {
    DangerZone = math.huge, Water = 20, CrackedLava = 20, Slate = 20
    }
    })

Engelleri yok sayma

Bazı durumlarda, katı engellerin içinden yol bulmak yararlı olabilir. Bu, belirli fiziksel engellerden geçerek bir yol hesaplamanızı sağlar; bu, hesaplamanın tamamen başarısız olmasını önler.

  1. Engelin etrafında Anchored bir parça oluşturun ve CanCollide özelliğini false olarak ayarlayın.

    Yol bulma modifikatörünü uygulamak için bir bölge tanımlayan sabit parça.
  2. Parçaya bir PathfindingModifier örneği ekleyin ve PassThrough özelliğini etkinleştirin.

    PassThrough özelliği etkinleştirilmiş PathfindingModifier örneği.

    Artık, bir yol, zombi NPC'den oyuncu karakterine hesaplandığında, yol kapının ötesine uzanır ve zombiyi geçmesini sağlayabilirsiniz. Zombi kapıyı açamasa bile, kapının arkasındaki karakteri "duyuyormuş" gibi tepki verir.

    Zombi NPC'nin daha önce engelleyen kapıdan geçiş yolu.

Yol Bulma Bağlantıları

Bazen, normalde geçilemeyen bir alan üzerinden bir yol bulmak ve bir sonraki waypoint'e ulaşmak için özel bir eylem gerçekleştirmek gerekebilir. Bu, PathfindingLink nesnesi aracılığıyla gerçekleştirilebilir.

Yukarıdaki örneği kullanarak, ajanı bir bot kullanmaya yönlendirebilirsiniz.

Bir ajanın bot kullanabileceğini gösteren PathfindingLink.

Bu örneği kullanarak bir PathfindingLink oluşturmak için:

  1. İSTEĞE BAĞLI
    3D görünüm alanının sağ üst köşesindeki Görselleştirme Seçenekleri aracından Yol Bulma bağlantılarını etkinleştirin. Bu, yol bulma bağlantılarını uygularken görselleştirme ve hata ayıklama konusunda yardımcı olur.

  2. Botun koltuğuna ve botun iniş noktasına yakın iki Attachments oluşturun.

    Yol bulma bağlantısının başlangıç ve bitişi için oluşturulan bağlantılar.
  3. Çalışma alanında bir PathfindingLink nesnesi oluşturun, ardından Attachment0 ve Attachment1 özelliklerini sırasıyla başlangıç ve bitiş bağlantılarına atayın.

    PathfindingLink'in Attachment0/Attachment1 özellikleri. 3D dünyada görselleştirilen PathfindingLink.
  4. Label özelliğine UseBoat gibi anlamlı bir isim atayın. Bu isim, ajanın başlangıç bağlantı noktasına ulaştığında özel bir eylemi tetiklemek için yol bulma betiğinde bir bayrak olarak kullanılır.

    PathfindingLink için belirtilen Label özelliği.
  5. CreatePath() içinde hem bir Water anahtarı hem de Label özellik adı ile eşleşen özel bir anahtar içeren bir Costs tablosu ekleyin. Özel anahtara, Water'ın değerinden daha düşük bir değer atayın.

    PlayerPathFollow (LocalScript)
    local PathfindingService = game:GetService("PathfindingService")
    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    local DESTINATION = Vector3.new(20, 0.5, 20)
    local GROUND_WAIT = 0.01
    local VELOCITY_MULTIPLIER = 0.0625
    local path = PathfindingService:CreatePath({
    AgentCanClimb = true,
    Costs = {
    UseBoat = 2, Water = 20
    }
    })
  6. moveToNextWaypoint() fonksiyonunda (

    SATIR 93–114
    ), Label modifikatör adı için özel bir kontrol kullanarak Humanoid:Move()'dan farklı bir eylem gerçekleştirebilirsiniz; bu durumda, ajanın botun içinde oturmasını sağlamak, botu suyun üzerinden hareket ettirmek, ajanın botun iniş noktasında inmesini sağlamak ve ardından ajanın yoluna devam etmesini sağlamak için bir fonksiyon çağırabilirsiniz.

Akış uyumluluğu

Oyun içi örnek akışı, bir oyuncunun karakteri dünyada hareket ettikçe 3D içeriği dinamik olarak yükleyen ve boşaltan güçlü bir özelliktir. 3D alanı keşfettikçe, alanın yeni alt kümeleri cihazlarına akarken, mevcut alt kümelerden bazıları akıştan çıkabilir.

PathfindingService'i akış destekli oyunlarda kullanırken aşağıdaki en iyi uygulamaları göz önünde bulundurun:

  • Akış, bir karakter bir yol boyunca hareket ederken belirli bir yolu engelleyebilir veya engeli kaldırabilir. Örneğin, bir karakter bir ormandan geçerken, bir ağaç önlerinde bir yere akabilir ve yolu engelleyebilir. Yol bulmanın akışla sorunsuz çalışmasını sağlamak için, engellenmiş yolları ele alma tekniğini kullanmanız ve gerektiğinde yolu yeniden hesaplamanız şiddetle önerilir.

  • Yol bulmada yaygın bir yaklaşım, mevcut nesnelerin koordinatlarını hesaplama için kullanmaktır; örneğin, bir yol hedefini dünyadaki mevcut bir TreasureChest modelinin konumuna ayarlamak. Bu yaklaşım, sunucunun her zaman dünyanın tam görünümüne sahip olduğu için sunucu tarafı Scripts ile tamamen uyumludur, ancak istemcide çalışan LocalScripts ve ModuleScripts, akışta olmayan bir nesneye yol hesaplamaya çalışırlarsa başarısız olabilir.

    Bu sorunu ele almak için, hedefi kalıcı bir model içindeki bir BasePart konumuna ayarlamayı düşünün. Kalıcı modeller, oyuncu katıldıktan kısa bir süre sonra yüklenir ve asla akıştan çıkmaz, bu nedenle istemci tarafı bir betik, PersistentLoaded olayına bağlanabilir ve olay tetiklendiğinde modelin erişimini güvenli bir şekilde sağlayabilir.

Sınırlamalar ve başarısızlık faktörleri

Yol bulma motoru, verimli işleme ve optimal performans sağlamak için belirli sınırlamalara sahiptir. Ayrıca, yol bulma hesaplamaları çeşitli nedenlerle başarısız olabilir; aşağıda belirtilmiştir.

©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.