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 をゾーンとし、その中にいるプレイヤーを調べたい場合は、次のようなプログラムになるでしょう。
- ゾーンとしてPartを1つ設置します。
- Anchoredをtrueに、CanCollideをfalseに設定します。
- 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