RobeeSeth

Roblox Snow Deformation

Jul 27th, 2025 (edited)
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.54 KB | None | 0 0
  1. -- made by @RobeeSeth
  2.  
  3. local basepart = script.Parent
  4. local resetpart = workspace:WaitForChild("reset")
  5.  
  6. local gridsize = 1 -- 1 = 1 stud part, higher means it'd be more optimized, but less precise, since there'd be less parts to step on, I haven't messed with the larger ones since I added foot prints, so it might not work.
  7. local ogheight = 1.2 -- edit this if you want lower or higher snow.
  8. local minheight = 0
  9. local shrinkstep = 0.8 -- this is the tiny foot steps you leave behind.
  10. local neighborshrinkstep = 0.6 -- this is the rest of the snow that you step on.
  11. local cooldowntime = 0.35 -- cooldown before you can step on the same snow part again.
  12. local maxpushheight = ogheight + 0.3 -- so, when you step on snow, the snow around that part will get higher.
  13. local maxpushvary = 0.15
  14.  
  15. local sizex = basepart.Size.X
  16. local sizez = basepart.Size.Z
  17. local basepos = basepart.Position
  18. local partsx = math.floor(sizex / gridsize)
  19. local partsz = math.floor(sizez / gridsize)
  20.  
  21. local snowmodel = Instance.new("Model")
  22. snowmodel.Name = "snowgrid"
  23. snowmodel.Parent = workspace
  24.  
  25. local snowgrid = {}
  26.  
  27. local function setheight(part, newheight)
  28. part.Size = Vector3.new(part.Size.X, newheight, part.Size.Z)
  29. part.Position = Vector3.new(
  30. part.Position.X,
  31. basepart.Position.Y + basepart.Size.Y / 2 + newheight / 2,
  32. part.Position.Z
  33. )
  34. end
  35.  
  36. local function shrinkbit(part, amount)
  37. local oldheight = part.Size.Y
  38. local newheight = math.max(oldheight - amount, minheight)
  39. if newheight ~= oldheight then
  40. setheight(part, newheight)
  41. end
  42. return oldheight - newheight
  43. end
  44.  
  45. local function pushtop(part, amount)
  46. local newheight = math.min(part.Size.Y + amount, maxpushheight)
  47. if newheight ~= part.Size.Y then
  48. setheight(part, newheight)
  49. end
  50. end
  51.  
  52. local function pushfullnbs(originx, originz, lostvolume)
  53. local nearby = {}
  54. for dx = -1, 1 do
  55. for dz = -1, 1 do
  56. if dx ~= 0 or dz ~= 0 then
  57. local nx, nz = originx + dx, originz + dz
  58. local neighbor = snowgrid[nx] and snowgrid[nx][nz]
  59. if neighbor and math.abs(neighbor.part.Size.Y - ogheight) < 0.01 then
  60. table.insert(nearby, neighbor.part)
  61. end
  62. end
  63. end
  64. end
  65. if #nearby > 0 then
  66. local pushper = lostvolume / #nearby
  67. for _, p in ipairs(nearby) do
  68. local randpush = math.random() * maxpushvary
  69. pushtop(p, pushper + randpush)
  70. end
  71. end
  72. end
  73.  
  74. local function shrinknbs(originx, originz, shrinkamt)
  75. for dx = -1, 1 do
  76. for dz = -1, 1 do
  77. if dx ~= 0 or dz ~= 0 then
  78. local nx, nz = originx + dx, originz + dz
  79. local neighbor = snowgrid[nx] and snowgrid[nx][nz]
  80. if neighbor and tick() - neighbor.lastshrink > cooldowntime then
  81. local lost = shrinkbit(neighbor.part, shrinkamt)
  82. neighbor.lastshrink = tick()
  83. pushfullnbs(nx, nz, lost)
  84. end
  85. end
  86. end
  87. end
  88. end
  89.  
  90. local function onstepped(part, x, z)
  91. return function(hit)
  92. if not hit:IsA("BasePart") then return end
  93. local data = snowgrid[x][z]
  94. if tick() - data.lastshrink < cooldowntime then return end
  95. local char = hit.Parent
  96. local isplayer = char and char:FindFirstChild("HumanoidRootPart")
  97. if isplayer then
  98. local lost = shrinkbit(part, shrinkstep)
  99. data.lastshrink = tick()
  100. shrinknbs(x, z, neighborshrinkstep)
  101. pushfullnbs(x, z, lost)
  102. else
  103. if hit.Anchored then return end
  104. local lost = shrinkbit(part, neighborshrinkstep)
  105. data.lastshrink = tick()
  106. shrinknbs(x, z, neighborshrinkstep)
  107. pushfullnbs(x, z, lost)
  108. end
  109. end
  110. end
  111.  
  112. for x = 0, partsx - 1 do
  113. snowgrid[x] = {}
  114. for z = 0, partsz - 1 do
  115. local partsize = Vector3.new(gridsize, ogheight, gridsize)
  116. local partpos = Vector3.new(
  117. basepos.X - sizex / 2 + x * gridsize + gridsize / 2,
  118. basepos.Y + basepart.Size.Y / 2 + ogheight / 2,
  119. basepos.Z - sizez / 2 + z * gridsize + gridsize / 2
  120. )
  121.  
  122. local regioncf = CFrame.new(partpos)
  123. local regionsize = partsize
  124.  
  125. local overlap = OverlapParams.new()
  126. overlap.FilterType = Enum.RaycastFilterType.Exclude
  127. overlap.FilterDescendantsInstances = {basepart, snowmodel}
  128. overlap.CollisionGroup = "Default"
  129.  
  130. local blocked = false
  131. local touching = workspace:GetPartBoundsInBox(regioncf, regionsize, overlap)
  132.  
  133. for _, other in ipairs(touching) do
  134. if other:IsA("BasePart") and other.Anchored and other.Transparency < 1 and other.CanCollide then
  135. local pos, size = other.Position, other.Size
  136. if pos and size then
  137. local min = pos - size / 2
  138. local max = pos + size / 2
  139. if partpos.X >= min.X and partpos.X <= max.X and
  140. partpos.Y >= min.Y and partpos.Y <= max.Y and
  141. partpos.Z >= min.Z and partpos.Z <= max.Z then
  142. blocked = true
  143. break
  144. end
  145. end
  146. end
  147. end
  148.  
  149. if not blocked then
  150. local part = Instance.new("Part")
  151. part.Size = partsize
  152. part.Position = partpos
  153. part.Anchored = true
  154. part.TopSurface = Enum.SurfaceType.Studs
  155. part.BottomSurface = Enum.SurfaceType.Smooth
  156. part.Color = Color3.fromRGB(255, 255, 255)
  157. part.Material = Enum.Material.Plastic
  158. part.CanCollide = false -- edit this if you want to collide with the snow, wouldn't recommend but go ahead.
  159. part.Parent = snowmodel
  160. snowgrid[x][z] = {
  161. part = part,
  162. lastshrink = 0
  163. }
  164. part.Touched:Connect(onstepped(part, x, z))
  165. end
  166. end
  167. end
  168.  
  169. local function resetall()
  170. for x = 0, partsx - 1 do
  171. for z = 0, partsz - 1 do
  172. local pd = snowgrid[x][z]
  173. if pd then
  174. setheight(pd.part, ogheight)
  175. end
  176. end
  177. end
  178. end
  179.  
  180. local click = resetpart:FindFirstChild("ClickDetector")
  181. if click then
  182. click.MouseClick:Connect(function()
  183. resetall()
  184. end)
  185. end
  186.  
Advertisement
Add Comment
Please, Sign In to add comment