i have a modified rocket launcher gear that clones a custom explosion effect when the rocket… explodes! i’d like for the white circle in the video to always be perpendicular to whatever surface it hits (similar to how it looks when rockets hit the floor)
unfortunately, i have no way of figuring out the angle of whatever part i hit!! i’ve seen no mention of any problem similar to this online, and i’ve struggled finding a way to get it by myself
i’ve already tried setting the rotation of the explosion effect to the same as the rocket object, but that didn’t provide favorable results
script i have so far relating to the effect:
--Create the explosion.
local Explosion = Instance.new("Explosion")
Explosion.BlastPressure = 0
Explosion.BlastRadius = BLAST_RADIUS
Explosion.Position = Position
Explosion.Hit:Connect(OnExplosionHit)
Explosion.Visible = false
-- MY! ugly effect
local vfx = ReplicatedStorage.vfx:FindFirstChild("explode")
local clonevfx = vfx:Clone()
-- clonevfx:PivotTo(CFrame.new(Position) * CFrame.fromEulerAngles(math.rad(45), 0, 0))
clonevfx:PivotTo(CFrame.new(Position))
-- print(CFrame.lookAt(Position, touchedpart.Position))
-- i love commenting out stuff i've tried that doesn't work <3
clonevfx.Parent = workspace
Explosion.Parent = game.Workspace
--Reparent the script to the explosion and destroy the rocket.
FiredByValue.Parent = script
script.Parent = Explosion
Rocket:Destroy()
wait(1)
clonevfx:Destroy()
You need the surface normal direction of the part/wall/floor that got hit, which is only easy to get by doing a raycast at the impact position, from the direction the projectile came from. You can whitelist just the hit part to be sure the ray doesn’t consider anything else along the projectile path.
Once you have the normal from the RaycastResult, you can construct a CFrame where that surface normal is the UpVector. Since your circle graphic is radially symmetric, you can use the CFrame constructor Cframe.new( hitPos, hitPos + normal ) or you can use CFrame.lookAt, but because that constructs a CFrame where the supplied direction is the LookVector, not UpVector, you’ll have to either multiply the result by something like CFrame.fromOrientation( -0.5*math.pi,0,0), or use CFrame.fromMatrix to construct the full CFrame manually if you know how (requires solid understanding of cross product and dot product to cover all cases correctly). Or you can bake the 90 degree rotation into the model you’re orienting, using a weld or motor to a part that’s oriented how you want.
thank you for pointing me in the right direction! i’ve got something resembling what i’d like down… but i’m having trouble with walls still. slopes and floors are working great though! !
updated code snippet
local Explosion = Instance.new("Explosion")
Explosion.BlastPressure = 0
Explosion.BlastRadius = BLAST_RADIUS
Explosion.Position = Position
Explosion.Hit:Connect(OnExplosionHit)
Explosion.Visible = false
-- MY! ugly effect
local vfx = ReplicatedStorage.vfx:FindFirstChild("explode")
local clonevfx = vfx:Clone()
--
clonevfx:PivotTo(CFrame.new(Position))
-- print(CFrame.lookAt(Position, touchedpart.Position))
-- i love commenting out stuff i've tried that doesn't work <3
clonevfx.Parent = workspace
Explosion.Parent = game.Workspace
--Reparent the script to the explosion and destroy the rocket.
FiredByValue.Parent = script
script.Parent = Explosion
local tovector = Rocket.CFrame.LookVector * 100
local rayDirection = tovector
local raycastResult = workspace:Raycast(Rocket.Position, rayDirection)
-- this saved me >>> https://devforum.roblox.com/t/how-do-you-visualize-a-raycast-as-a-part/657972/12
--[[local function visualizeRaycast(origin, direction)
local Raycast = Instance.new("Part")
Raycast.CFrame = CFrame.new(origin + direction/2, origin + direction)
Raycast.Anchored = true
Raycast.CanCollide = false
Raycast.Name = "Raycast"
Raycast.Size = Vector3.new(1, 1, direction.Magnitude)
Raycast.Parent = workspace
end
visualizeRaycast(Rocket.Position, rayDirection)]]
if raycastResult then
print(raycastResult.Normal)
local normal90 = (raycastResult.Normal * 90)
clonevfx:PivotTo(CFrame.new(Position) * CFrame.fromEulerAngles(math.rad(normal90.X), math.rad(normal90.Y), math.rad(normal90.Z)))
else
print("no raycast hit... :(")
end
Rocket:Destroy()
wait(1)
clonevfx:Destroy()