Part に触れている他のパーツを調べるには、GetTouchingParts というものを使えば良いのですが、なぜか単純に呼び出しただけでは正常に動作しないようです。以下のようなプログラムを組みことで正常に動作することが確認できました。この関数に調べたいPartを指定すれば、触れているすべてのパーツが返ります。

local function getTouchingParts(part)
    local connection = part.Touched:Connect(function() end)
    local results = part:GetTouchingParts()
    connection:Disconnect()
    return results
end

モデルのWeld化

アンカー設定されているモデルは、アセット内のバズーカ砲などでは破壊できないのがほとんどです。またアセット内のモデルはアンカー設定されているものが多いようです。そこで、上記関数の使用例として、アンカー設定されているパーツで作られたモデルを接着(Weld)し、アンカーを解除するプログラムを作成してみます。

local function weldParts(part,parts)
    for _,v in pairs(parts) do
        local weld = Instance.new("WeldConstraint")
        weld.Part0 = part
        weld.Part1 = v
        weld.Parent = v
    end
end

local function weldModel(model)
    local descendants = model:GetDescendants()
    for _, v in pairs(descendants) do
        if v:IsA("BasePart") and v.Anchored == true then
            local parts = getTouchingParts(part)
            weldParts(v,parts)
            v.Anchored = false
        end
    end
end

getAllParts(モデル)

少し離れていても接着させる方法

上記のプログラムでは、パーツ同士が完全に触れていないと接着されません。そこで、パーツ同士が少し離れていても接着できるようなプログラムを作成してみました。
パーツのサイズを少し大きくし、元も戻して接着させます。この方法ですと、GetTouchingParts は正しく動作するようです。

local distance = 0.1    -- 許容範囲

local function weldModel(model)
    local descendants = model:GetDescendants()
    for _, v in pairs(descendants) do
        if v:IsA("BasePart") and v.Anchored == true then
            v.Size = v.Size + Vector3.new(distance,distance,distance)
            wait()
            weldParts(v,v:GetTouchingParts())
            v.Size = v.Size + Vector3.new(-distance,-distance,-distance)
            v.Anchored = false
        end
    end
end

getAllParts(モデル)

特定の3次元空間内に存在するパーツを検出する方法

あるパーツが他のパーツと重なっているかどうか(触れていても重なっていると判断)を調べるには、GetPartBoundsInBox を使用します。

local newPartCFrame = CFrame.new(0, 10, 0) -- 新しいパーツの中心位置
local newPartSize = Vector3.new(4, 4, 4) -- 新しいパーツのサイズ

-- GetPartBoundsInBoxを使用してボックス内のパーツを検出
local partsInBox = workspace:GetPartBoundsInBox(newPartCFrame, newPartSize)

-- 重なっているパーツがあるか確認
if #partsInBox > 0 then
    print("新しいパーツは他のパーツと重なっています。")
else
    print("重なっているパーツはありません。")
end

ゾーン内にいるプレイヤーの確認

Part をゾーンとし、その中にいるプレイヤーを調べたい場合は、次のようなプログラムになるでしょう。

  1. ゾーンとしてPartを1つ設置します。
  2. Anchoredをtrueに、CanCollideをfalseに設定します。
  3. Partの下に以下のプログラムを追加します。
local Players = game:GetService("Players")
local zone = script.Parent

local playerList = {}  -- ゾーンに入っているプレイヤーのリスト

local function addPlayerList(player)
    for _,pl in ipairs(playerList) do
        if pl == player then
            return
        end
    end
    table.insert(playerList,player)
end

while wait(1) do
    playerList = {}
    local partsInBox = workspace:GetPartBoundsInBox(zone.CFrame, zone.Size)
    if #partsInBox > 0 then
        for i,p in ipairs(partsInBox) do
            local player = Players:GetPlayerFromCharacter(p.Parent)
            if player then
                addPlayerList(player)
            end
        end
    end
    print(playerList)
end

By schilverberch

ROBLOXでゲームを作ろう! 一緒にプログラミングを学びましょう。

コメントを残す