Hello, I'm currently making my own gun system for my zombie game. I'm having issues making the bullet holes for extra effects. When they're spawned in they don't face the right way I wanted them to face. I think its about how I raycasted but I'm not really sure.
How I wanted the bullet hole to look/face: https://prnt.sc/t585i5
How it actually looks/faces like: https://prnt.sc/t586qh
Extra Info: The line of code is in a localscript; I'm using a remote event to fire the bullet.
The code below is possibly incredibly unorganized on your screen, so I recommend using the "View Source" window to observe it.
local NewRay local ProjectileHitPosition if not Aiming then local SpreadCalculator = Vector3.new(FirePoint.WorldCFrame.Position.X + math.random(-Configuration.Spread, Configuration.Spread)/1000, FirePoint.WorldCFrame.Position.Y + math.random(-Configuration.Spread, Configuration.Spread)/1000, FirePoint.WorldCFrame.Position.Z + math.random(-Configuration.Spread, Configuration.Spread)/1000) local NewRay2 = Ray.new(FirePoint.WorldCFrame.Position, (Mouse.Hit.Position - SpreadCalculator).Unit * Configuration.Range) ProjectileHitPosition = (Mouse.Hit.Position - SpreadCalculator).Unit * Configuration.Range NewRay = Ray.new(NewRay2.Origin, CFrame.Angles(math.rad(math.random(-Configuration.Spread, Configuration.Spread)), math.rad(math.random(-Configuration.Spread, Configuration.Spread)), math.rad(math.random(-Configuration.Spread, Configuration.Spread))) * NewRay2.Direction) elseif Aiming and Configuration.Sniper then local SpreadCalculator = Vector3.new(FirePoint.WorldCFrame.Position.X + math.random(-Configuration.SniperSpread, Configuration.SniperSpread)/1000, FirePoint.WorldCFrame.Position.Y + math.random(-Configuration.SniperSpread, Configuration.SniperSpread)/1000, FirePoint.WorldCFrame.Position.Z + math.random(-Configuration.SniperSpread, Configuration.SniperSpread)/1000) local NewRay2 = Ray.new(FirePoint.WorldCFrame.Position, (Mouse.Hit.Position - SpreadCalculator).Unit * Configuration.Range) ProjectileHitPosition = (Mouse.Hit.Position - SpreadCalculator).Unit * Configuration.Range NewRay = Ray.new(NewRay2.Origin, CFrame.Angles(math.rad(math.random(-Configuration.SniperSpread, Configuration.SniperSpread)), math.rad(math.random(-Configuration.SniperSpread, Configuration.SniperSpread)), math.rad(math.random(-Configuration.SniperSpread, Configuration.SniperSpread))) * NewRay2.Direction) elseif Aiming and not Configuration.Sniper then local SpreadCalculator = Vector3.new(FirePoint.WorldCFrame.Position.X + math.random(-Configuration.IronsightSpread, Configuration.IronsightSpread)/1000, FirePoint.WorldCFrame.Position.Y + math.random(-Configuration.IronsightSpread, Configuration.IronsightSpread)/1000, FirePoint.WorldCFrame.Position.Z + math.random(-Configuration.IronsightSpread, Configuration.IronsightSpread)/1000) local NewRay2 = Ray.new(FirePoint.WorldCFrame.Position, (Mouse.Hit.Position - SpreadCalculator).Unit * Configuration.Range) ProjectileHitPosition = (Mouse.Hit.Position - SpreadCalculator).Unit * Configuration.Range NewRay = Ray.new(NewRay2.Origin, CFrame.Angles(math.rad(math.random(-Configuration.IronsightSpread, Configuration.IronsightSpread)), math.rad(math.random(-Configuration.IronsightSpread, Configuration.IronsightSpread)), math.rad(math.random(-Configuration.IronsightSpread, Configuration.IronsightSpread))) * NewRay2.Direction) end local MouseHit, HitPosition, Normal = Workspace:FindPartOnRayWithIgnoreList(NewRay, IgnoreList, true, true) if Configuration.BulletHoles and MouseHit and MouseHit:IsA("BasePart") and MouseHit.Parent:FindFirstChildOfClass("Humanoid") == nil then local BulletHoleBasePart = Instance.new("Part") BulletHoleBasePart.Material = Enum.Material.Air BulletHoleBasePart.Transparency = 1 BulletHoleBasePart.CanCollide = false BulletHoleBasePart.Anchored = true BulletHoleBasePart.Massless = true BulletHoleBasePart.Name = "BulletHit" BulletHoleBasePart.Size = Vector3.new(3.6, 0.05, 3.6) BulletHoleBasePart.CFrame = CFrame.new(HitPosition, HitPosition + Normal) BulletHoleBasePart.Parent = Workspace local Weld = Instance.new("Weld") Weld.Part0 = MouseHit Weld.Part1 = BulletHoleBasePart Weld.C0 = MouseHit.CFrame:Inverse() Weld.C1 = BulletHoleBasePart.CFrame:Inverse() Weld.Parent = BulletHoleBasePart local BulletHoleDecal = Instance.new("Decal", BulletHoleBasePart) BulletHoleDecal.Face = "Top" BulletHoleDecal.Texture = "rbxassetid://"..Configuration.BulletHoleDecals[math.random(#Configuration.BulletHoleDecals)] BulletHoleDecal.Name = "BulletHole" BulletHoleDecal.Color3 = MouseHit.Color table.insert(IgnoreList, BulletHoleBasePart) Debris:AddItem(BulletHoleBasePart, 10) end
There is a lot going on there, but thankfully, all you need is the CFrame to place the part that the decal is on, and by using the normal you got from the FindPartOnRay, you can get the exact position and rotation that the decal part needs to be.
CFrame.new(HitPosition)*CFrame.Angles(math.rad(Normal.X),math.rad(Normal.Y),math.rad(Normal.Z))
Also, if for whatever reason, the decal is facing the wrong way, all you would need to do is rotate it again by multiplying by another CFrame.Angles:
CFrame.new(HitPosition)*CFrame.Angles(math.rad(Normal.X),math.rad(Normal.Y),math.rad(Normal.Z))*CFrame.Angles(0,math.rad(180),0)
The reason yours didn't work is because CFrame.new(HitPosition, HitPosition + Normal)
means that it is positioned at HitPosition, but it is facing the point at HitPosition + the normal, when all you want it to do is face in the direction of the normal alone.