Need help fixing projectile height being messed up when shot facing the Z axis!

Hello, i’ve been trying to create a projectile pattern on my game and have been struggling with making my projectiles consistently shoot on the proper pattern, they are supposed to fire in a + pattern, but the top and bottom projectiles simply shoot on the same height as the middle one, the shortened code for the shooting bit is:

function shoot(angleX, angleY, angleZ)
 local Vel = Instance.new("BodyVelocity",Bullet)
 Vel.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
 Vel.Velocity = CFrame.Angles(math.rad(angleX), math.rad(angleY), math.rad(angleZ)) *  direction.LookVector * speed
end

shoot(0, 30, 0)
shoot(0, 0, 0)
shoot(0, -30, 0)
shoot(0, 0, -30)
shoot(0, 0, 30)

If it helps in any way, the full code is shown below, first script being the local one and the second is the server script.

Local Script:

local Player = game.Players.LocalPlayer

local Mouse = Player:GetMouse()
local Locking = false
local rp = game:GetService("ReplicatedStorage")
local Danmaku = rp:WaitForChild("Basic Danmaku")
local RS = game:GetService("RunService")

local UIS = game:GetService("UserInputService")
local debounce = false

local function beginFocusing(input)
if input.KeyCode == Enum.KeyCode.Tab then
focus = true
else
focus = false
end
end


UIS.InputBegan:Connect (function(input, isTyping)
if isTyping then
return
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
if UIS.MouseBehavior == Enum.MouseBehavior.LockCenter then
if UIS:IsKeyDown(Enum.KeyCode.Tab) then
focus = true
else
focus = false
end

if debounce == false then
debounce = true
Danmaku:FireServer(Mouse.Hit, focus)
end
end
end
end)

Danmaku.OnClientEvent:Connect(function()
debounce = false
end)

Server Script:

rp = game:GetService("ReplicatedStorage")

speed = 60
damage = 100
DSS = game:GetService("DataStoreService")
Debris = game:GetService("Debris")
sound = Instance.new("Sound", game.Workspace)
sound.SoundId = "rbxassetid://3727467952"
debounce = false
Animations = script:WaitForChild("Animations")
Meshes = script:WaitForChild("Meshes")
DanmakuColor = DSS:GetDataStore("DanmakuColor")
DanmakuShape = DSS:GetDataStore("DanmakuShape")


Danmaku = rp:WaitForChild("Basic Danmaku")
cd = rp:WaitForChild("m1_cd")


Danmaku.OnServerEvent:Connect(function(Player, direction, focusEvent)
if focusEvent == true then
focus = true
else
focus = false
end

if not Player.Character:FindFirstChildOfClass("ForceField") then
local id = Player.UserId
local color = DanmakuColor:GetAsync(id.. "c")
local shape = DanmakuShape:GetAsync(id.. "s")
local Character = Player.Character
local Humanoid = Character:WaitForChild("Humanoid")
local Humrp = Character:WaitForChild("HumanoidRootPart")
local effectsFolder = Instance.new("Folder",workspace)

function shoot(angleX, angleY, angleZ)
effectsFolder.Name = Player.Name.." Effects"
Debris:AddItem(effectsFolder,2)
sound:Play()
local InnerDanmaku = Meshes:WaitForChild("InnerDanmaku"):Clone()
InnerDanmaku.CFrame = CFrame.new((Humrp.CFrame * CFrame.new(0 ,0,-1)).p,direction.p)
InnerDanmaku.Orientation = InnerDanmaku.Orientation + Vector3.new(90, 0, 0)
InnerDanmaku.BrickColor = BrickColor.new(color)
InnerDanmaku.Parent = effectsFolder

InnerDanmaku.Touched:Connect(function(Hit)

if Hit:isA("BasePart") then
if not Hit:IsDescendantOf (Character) then
local Humanoid = Hit.Parent:FindFirstChild("Humanoid")

--if you hit a humanoid then...
if Humanoid and Humanoid.Parent ~= Character then
if Humanoid.Health > 0 then
effectsFolder:Destroy()
Humanoid:TakeDamage(damage)
end
end
end
end
end)
local OuterDanmaku = Meshes:WaitForChild(shape):Clone()
OuterDanmaku.CFrame = Humrp.CFrame * CFrame.new(0,0,-1)
OuterDanmaku.Parent = effectsFolder
OuterDanmaku.BrickColor = BrickColor.new(color)
OuterDanmaku.CFrame = CFrame.new(OuterDanmaku.Position,direction.Position)

local weld = Instance.new("ManualWeld")
weld.Part1 = InnerDanmaku
weld.Part0 = OuterDanmaku
weld.C0 = weld.Part0.CFrame:toObjectSpace(weld.Part1.CFrame)
weld.Parent = weld.Part0

local Vel = Instance.new("BodyVelocity",InnerDanmaku)
Vel.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
Vel.Velocity = CFrame.Angles(math.rad(angleX), math.rad(angleY), math.rad(angleZ)) * direction.LookVector * speed

end


if debounce == false then
if focus == false then
shoot(0, 0, 0)
wait(0.2)
shoot(0, 0, 0)
wait(0.2)
shoot(0, 0, 0)
wait(0.2)
cd:FireClient(Player, 1)
wait(1)
Danmaku:FireClient(Player)
debounce = true
end
end

if debounce == false then
if focus == true then
shoot(0, 30, 0)
shoot(0, 0, 0)
shoot(0, -30, 0)
shoot(0, 0, -30)
shoot(0, 0, 30)
cd:FireClient(Player, 2)
wait(2)
Danmaku:FireClient(Player)
debounce = true
end
end
debounce = false
else
Danmaku:FireClient(Player)
end

end)

The problem can be seen happening on the video below, with the X and Z axis marked with decals:

Well, the problem with your way was that you rotated the velocity on world axis instead of the mesh’s. I just solved it by rotating the mesh by the angle on it’s local axis and then velocity is just look vector * speed. You can test the difference in your and mine version by using something with apparent front face (like a 4*1*2 part) instead of the balls - in yours the part should drift kinda sideways whereas in mine it will just face it’s direction.

Changed:
InnerDanmaku.CFrame = CFrame.new((Humrp.CFrame * CFrame.new(0 ,0,-1)).p,direction.p):ToWorldSpace(CFrame.Angles(math.rad(angleX), math.rad(angleY), math.rad(angleZ)))
And:
Vel.Velocity = InnerDanmaku.CFrame.LookVector * speed

And then:

shoot(0, 30, 0)
shoot(0, 0, 0)
shoot(0, -30, 0)
shoot(-30, 0, 0)
shoot(30, 0, 0)

This might need an adjustment because your mesh might need to rotate on different axis. I was testing with basic part. So I even deleted this:
InnerDanmaku.Orientation = InnerDanmaku.Orientation + Vector3.new(90, 0, 0)

1 Like

Thank you! Worked perfectly and fixed the orientation thing as well, i thought the rotation bit was based on the player orientation.