Hi! I want to make a script that makes my model’s rock’s material change to the material of the part that they touched when spawning. (default material is set to slate)
The script runs perfectly fine, but the model’s rocks doesnt change material.
local rs = game:GetService("ReplicatedStorage")
local RemoteEvent = rs:WaitForChild("RockFolder"):WaitForChild("RemoteEvent")
RemoteEvent.OnServerEvent:Connect(function(player)
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local humrp = character:WaitForChild("HumanoidRootPart")
local rocksFolder = Instance.new("Folder", workspace)
rocksFolder.Name = player.Name.."'s rocks"
local rocks = rs:WaitForChild("RockFolder"):WaitForChild("rocks"):Clone()
rocks.Parent = rocksFolder
rocks:PivotTo(CFrame.new(humrp.Position) * CFrame.new(0,-15,0))
local tweenService = game:GetService("TweenService")
local goal = {
Position = rocks:WaitForChild("Part").Position + Vector3.new(0,15,0)
}
local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local tweenPos = tweenService:Create(rocks:WaitForChild("Part"), tweenInfo, goal)
tweenPos:Play()
-- changing the model's rocks material
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {workspace.Ignore}
rayParams.FilterType = Enum.RaycastFilterType.Blacklist
for i, v in pairs(rocks:GetChildren()) do
local ray = workspace:Raycast(v.CFrame.Position, v.CFrame.UpVector, rayParams)
if ray then
v.Material = ray.Instance.Material
end
end
for i, v in pairs(rocks:GetChildren()) do
if v.Name == "Rock" then
local goal2 = {
Transparency = 0
}
local tweenT = tweenService:Create(v, tweenInfo, goal2)
tweenT:Play()
end
end
wait(2)
for i, v in pairs(rocks:GetChildren()) do
for i, Attachment in pairs(v:GetChildren()) do
for i, Attachment in pairs(Attachment:GetChildren()) do
if Attachment.Name == "particle" then
Attachment.Enabled = true
end
end
end
end
wait(5)
rocksFolder:Destroy()
RemoteEvent:FireClient(player)
end)
I think the problem is that you need to raycast downwards, and that your raycast should be longer than one.
You probably want to sample directly downwards, so for the direction use something like Vector3.down or Vector3.new(0, -1, 0) (both are the same) multiplied by how long you want the raycast to be. I’d recommend something like 10-100 studs.
These changes result in this:
local ray = workspace:Raycast(v.CFrame.Position, Vector3.down*100, rayParams)
Here is some code that can (probably) debug the problem:
local rs = game:GetService("ReplicatedStorage")
local RemoteEvent = rs:WaitForChild("RockFolder"):WaitForChild("RemoteEvent")
RemoteEvent.OnServerEvent:Connect(function(player)
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local humrp = character:WaitForChild("HumanoidRootPart")
local rocksFolder = Instance.new("Folder", workspace)
rocksFolder.Name = player.Name.."'s rocks"
local rocks = rs:WaitForChild("RockFolder"):WaitForChild("rocks"):Clone()
rocks.Parent = rocksFolder
rocks:PivotTo(CFrame.new(humrp.Position) * CFrame.new(0,-15,0))
local tweenService = game:GetService("TweenService")
local goal = {
Position = rocks:WaitForChild("Part").Position + Vector3.new(0,15,0)
}
local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local tweenPos = tweenService:Create(rocks:WaitForChild("Part"), tweenInfo, goal)
tweenPos:Play()
-- changing the model's rocks material
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {workspace.Ignore}
rayParams.FilterType = Enum.RaycastFilterType.Blacklist
for i, v in pairs(rocks:GetChildren()) do
local ray = workspace:Raycast(v.CFrame.Position, Vector3.new(0, -100, 0), rayParams)
if ray then
if (ray.Instance == v) then print("Ray hit the rock instead of the ground! Parent the rocksFolder to Workspace.Ignore.")
else if (ray.Instance:IsDescendantOf(rocksFolder)) then print("Ray hit another rock! Parent the rocksFolder to Workspace.Ignore.") end end
print("The raycast had a valid hit! Material was: "..ray.Instance.Material.Name)
v.Material = ray.Instance.Material
else
print("The raycast didn't hit anything! Check direction and ignore list!")
end
end
for i, v in pairs(rocks:GetChildren()) do
if v.Name == "Rock" then
local goal2 = {
Transparency = 0
}
local tweenT = tweenService:Create(v, tweenInfo, goal2)
tweenT:Play()
end
end
wait(2)
for i, v in pairs(rocks:GetChildren()) do
for i, Attachment in pairs(v:GetChildren()) do
for i, Attachment in pairs(Attachment:GetChildren()) do
if Attachment.Name == "particle" then
Attachment.Enabled = true
end
end
end
end
wait(5)
rocksFolder:Destroy()
RemoteEvent:FireClient(player)
end)
The first message means it hit something. The second means it didn’t hit something.
That’s weird, it should set the material of the rock if it’s giving that error message. Are you sure the material of the rocks can be set? It’s not a mesh with a texture?
Edit:
I fixed the debug code (I needed EnumItem.Name) in the original reply.
Oh, it looks like the raycasts are hitting the rocks instead of the ground. To fix this, set the rocksFolder parent to Workspace.Ignore instead of just workspace.
local rocksFolder = Instance.new("Folder", workspace:WaitForChild("Ignore"))
So before it was hitting a rock, now it isn’t hitting anything.
I assume the ground isn’t in the Ignore folder.
I think the problem is that the rocks are inside the ground, so when it raycasts it checks below the ground instead checking below where the rocks will be.
This code starts the raycast from where the tween ends, and raycasts 100 studs downwards:
local ray = workspace:Raycast(v.CFrame.Position + Vector3.new(0, 15, 0), Vector3.new(0, -100, 0), rayParams)