Hi there, Devforum. I’ve recently programmed a knife throwing system using attachments on the knife as raycasting points, but the problem is that when the knife lands, it won’t stay in a correct way.
How knifes from other games land:
How my knifes land:
Knife’s visuals code sample:
function throw(character,startPos,direction,maxRange,gravity,velocity)
local lastPos = startPos
local range = tonumber(maxRange)
local startTime = tick()
local spinTween = nil
local rayhit = false
local projectile = game:GetService("ReplicatedStorage").knifeProjectile:Clone()
projectile.Parent = gameSettings.ProjectilesFolder
projectile.Anchored = true
projectile.CanCollide = false
local blacklist = {character,workspace.ProjectilesFolder}
local rayFilter = RaycastParams.new()
rayFilter.FilterType = Enum.RaycastFilterType.Exclude
while range >0 do
if range <=0 then break end
local timeLength = (tick()-startTime)
local currentPos = startPos + (direction*timeLength)
currentPos = applyGravity(currentPos,gravity,timeLength)
local distance = (lastPos-currentPos).Magnitude
range -= distance
if projectile then
local projectileOffset = CFrame.new(0, 0, -(lastPos-currentPos).magnitude/2)
projectile.CFrame = (CFrame.new(lastPos,currentPos)*projectileOffset)
end
for _, point in pairs(projectile:GetChildren()) do
if point:IsA("Attachment") and point.Name == "hitPoint" then
local createdRay = workspace:Raycast(lastPos,point.WorldPosition-lastPos,rayFilter)
if createdRay == nil then
createdRay = workspace:Raycast(point.WorldPosition,lastPos-point.WorldPosition,rayFilter)
end
if createdRay and range >0 and rayhit == false then
local hit = createdRay.Instance
rayhit = true
if spinTween then
spinTween:Cancel()
spinTween = nil
print("cancelling tween")
end
local projectileOffset = CFrame.new(0, 0, -(currentPos-createdRay.Position).magnitude/2)
projectile.CFrame = (CFrame.new(currentPos,createdRay.Position)*projectileOffset)*CFrame.Angles(-90,0,0)
projectile.Anchored = false
projectile.CanCollide = false
local weld = Instance.new("WeldConstraint",projectile)
weld.Enabled = true
weld.Part0 = projectile
weld.Part1 = hit
task.wait(game:GetService("Players").RespawnTime/1.5)
break
end
end
lastPos = currentPos
local t = tick()
repeat task.wait() until tick()-t >= 1/60
end
local t = tick()
repeat task.wait() until tick()-t >= 1/60
if projectile then
projectile:Destroy()
end
end
end
oh boy, i sure do hope I dont see any beautiful projectile scripts in her-OH MY GOODNESS
It so good to look at! Its just missing that hidden beauty like, idk, using the hit’s CFRAME and adding it to the knife’s to modify the knife’s orientation
(it would probably look like
--Set the knife pos to current pos, and have it face the thrower/player
projectile.CFrame = CFrame.new(currentPos,Character.Position)
--Optional relative rotations
local SwaggyRotator = CFrame.Angles(
math.rad(math.random(LOWEST ADJUSTMENT AMOUNT,MAX ADJUSTMENT AMOUNT)),--X offset
0,--Y offset
0)--Z offset
--[[Disclaimer; this wont work because im GUESSING that X is the
orientation the will cause the knife to tilt back or forth towards the player.
It could be Y or Z! Definitely try both out and see which one causes the
knife to tile forwards and backwards!]]--
projectile.CFrame:ToWorldSpace(SwaggyRotator)
)
(PS. you have CFrame.Angles(90,0,0) in your script. THIS WILL NOT WORK. CFrame.Angles ONLY accepts RADIANS! IT IS VERY WHINEY LIKE THAT!!!)
I used the code sample you’ve posted, and it probably did something, but not enough. Any ideas/tips on how to make sure that the knife ALWAYS has the right rotation and position?
my code sample:
local projectileOffset = CFrame.new(0, 0, -(lastPos-createdRay.Position).magnitude/2)
local rotateScale = CFrame.Angles(
-math.random(90,105),--x offset
0,--y offset
0)--z offset
projectile.CFrame = (CFrame.new(lastPos,createdRay.Position)*projectileOffset)
projectile.CFrame:ToWorldSpace(rotateScale)
projectile.Anchored = false
projectile.CanCollide = false
local weld = Instance.new("WeldConstraint",projectile)
weld.Enabled = true
weld.Part0 = projectile
weld.Part1 = hit
Hm. its way to random for the very small offsets youve given it.
What id do is print the orientation before and after the modification
And make the angle at which it can rotate be an easy 30 or 60 degrees. Because you have it either completely straight up, to a LITTLE bit towards the player. so it shouldnt be noticeable.
The script detects the last position (lastpos) and makes a new position (currentpos), so sometimes the knife goes trough the wall or ground, so it doesn’t matter about the orientation, its about how to make sure that the knife lands as it should be.
The only idea in my head is using another raycast when the knife lands in order to check if the knife is in a object, and if so, then the script will make sure that the knife is ontop of the part and correct the orientation.