Hello devs! I am currently creating a “dig out” type of action movement for my shovel tool, which creates a copy of the item that will be thrown and adds a parabolic movement with the shape of an upside down “U” to that item, in order to visualize the movement to the player.
The issue I am currently having is the existence of a weird scenario where the items which have this impulse applied to, fall down so hard, that they clip through the terrain of my game, while some don’t.
I am gonna show you an example through this video below:
Another weird behavior I noticed, most of the items that were cloned in that fashion, had some weird properties, such as acting like they are black hole-weighted or standing perfectly still mid-air even though they are un-anchored. Video:
The last item being dropped (Legendary Dirt, ), clips through the terrain.
I looked in both Dev hub and tried to minimize the total force
, but the unwanted behavior still insisted.
Some solutions I tried:
- Making my items larger, which in some cases worked but still is inconsistent.
- Setting the NetworkOwner property of the cloned item to nil, so there weren’t any problems regarding part ownership.
- Replacing ApplyImpulse with an AssemblyLinearVelocity method. Movement was fairly inconsistent, though, caused less item clipping or anomalous behavior (I may have implemented AssemblyLinearVelocity wrongly, in case that was the solution).
The way I tried to implement this action is, by adding a “SpawnPart” on my shovel which is a simple block part on top of the shovel’s handle (the pink cube on top of the branch) that can’t collide and plays the role of a placeholder position for the items that get cloned to be in, as a starter position.
Below is the Script I used to replicate the throwing action, using ApplyImpulse:
function HandleDigThrow(player: Player, toolName: string, drop)
-- Dropped item data
local dropTier = drop.Item.data.tier
local dropName = drop.Item.name
local dropSizeName = drop.Size.name
local dropSizeMultiplier = drop.Size.data.sizeMultiplier
local dropVariantName = drop.Variant.name
-- Tool that called the function
local tool = player.Character:FindFirstChild(toolName)
if not tool then
warn(`Tool not found: {toolName}`)
return
end
-- Part that Spawns the Item
local spawnPart = tool:FindFirstChild("SpawnPart")
if not spawnPart then
warn("Tool does not have a SpawnPart")
return
end
local spawnPos = spawnPart.Position + Vector3.new(0, 2, 0)
local humanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
if not humanoidRootPart then
warn("Player does not have a HumanoidRootPart")
return
end
-- Determine facing direction
local facingDirection = humanoidRootPart.CFrame.LookVector
-- Calculate behind-the-player destination
local offset = -facingDirection * 10 -- n studs behind the player
local throwDestination = spawnPos + offset
-- Add some height to the throw
throwDestination += Vector3.new(0, 2, 0) -- n studs upward
-- Calculate throw vector and force
local direction = throwDestination - spawnPos
local duration = math.log(1.001 + direction.Magnitude * 0.05)
local force = direction / duration + Vector3.new(0, Workspace.Gravity * duration * 0.5, 0)
-- Clone the item to be thrown
local itemToClone = ServerStorage.Items:FindFirstChild(dropName) -- Dynamic selection
if not itemToClone then
warn(`{dropName} to clone not found`)
return
end
local clone = itemToClone:Clone()
clone:ScaleTo(clone:GetScale() * dropSizeMultiplier)
-- Add trail from folder
AttachTrail(clone)
clone.PrimaryPart:FindFirstChild("Trail").Color = ColorSequence.new(Color3.fromHex(`{chatTags[dropTier].Color}`))
clone.PrimaryPart.Position = spawnPos
clone.Parent = Workspace
-- Model will use player's computer to replicate the throw
--clone.PrimaryPart:SetNetworkOwner(nil)
-- Apply impulse to simulate throw
clone.PrimaryPart:ApplyImpulse(force * clone.PrimaryPart.AssemblyMass)
-- Add rotation impulse
local rotation = Vector3.new(math.random(-1, 1), math.random(-2, 2), math.random(-1, 1))
clone.PrimaryPart:ApplyAngularImpulse(rotation * clone.PrimaryPart.AssemblyMass)
print(`{player.Name} successfully dug out an item!`)
Debris:AddItem(clone, 15)
task.delay(14, function() -- Remove the trail slightly before the clone is destroyed
if clone and clone.Parent then
RemoveTrail(clone)
end
end)
end
P.S: I don’t know if this is a welding issue, but the way I have glued the items together is by using weld constraints, so I don’t think there’s an issue there.
Any advice or guiding steps would be appreciated, thanks a lot!