ClientSide projectile on all clients without having Server to render it

robloxapp-20201003-1526425.wmv (286,6 KB)
^ To show that my magic move works on client and collides with a shield.
I want it to show on all clients without having to do it on the client.
So i used this method:

  1. Make the main projectile on the client and animate it with tweens.
  2. The server receives the client and the end position of the projectile.and fires all clients.
  3. Once the event happens - Clients (except the main client) create a fake projectile that also collides with the shield and removes it on their client if the collision happens.

My issue is the projectile doesnt appear on other clients just the main one.
Server script:

local RepStorage = game:GetService("ReplicatedStorage")
local particles = RepStorage.Magic
local Remote = RepStorage.MoveRemotes:WaitForChild("MagicBolt")
local ClientRemote = RepStorage.MoveRemotes:WaitForChild("ClientMagicBolt")

Remote.OnServerEvent:Connect(function(player, InputPos)
        local char = player.Character or player.CharacterAdded:wait()
        local StartPos = Vector3.new(char.HumanoidRootPart.Position + Vector3.new(0, 2, 0))
	    local OwnerValue = player.Name
        ClientRemote:FireAllClients(StartPos, InputPos, OwnerValue)
        local hum = char.Humanoid
        local CloneP1, CloneP2 = particles:Clone(), particles:Clone()
        CloneP1.Parent = player.Character.RightHand
        CloneP1.Enabled = true
        CloneP2.Parent = player.Character.LeftHand
        CloneP2.Enabled = true
        game.Debris:AddItem(CloneP1, 3)
        game.Debris:AddItem(CloneP2, 3)
        wait(0.3)
        CloneP1.Enabled = false
        CloneP2.Enabled = false
        player.leaderstats.exp.Value = player.leaderstats.exp.Value + 15
    end
)

Client script for all other clients except main one:

local tweenservice = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local RepStorage = game:GetService("ReplicatedStorage")
local ClientRemote = RepStorage.MoveRemotes:WaitForChild("ClientMagicBolt")
local Player = game.Players.LocalPlayer

ClientRemote.OnClientEvent:Connect(function(StartPos, EndPos, OwnerValue)
        if Player.Name == OwnerValue then
            return
        end
        local IgnoreList = {workspace.Map, workspace.ShopNPC, workspace.Spawn, workspace.ShopTouch}
        local dmgpart = game.ReplicatedStorage.Missiles.MagicBolt:Clone()
        dmgpart.Parent = workspace
        dmgpart.Position = Vector3.new(StartPos)
        game.Debris:AddItem(dmgpart, 3)
        local createTween =
            tweenservice:Create(
            dmgpart,
            tweenInfo,
            {
                Position = Vector3.new(EndPos)
            }
        )
        createTween:Play()
        local effect = Instance.new("Sound", dmgpart)
        effect.SoundId = "rbxassetid://4953173408"
        effect.MaxDistance = 300
        effect.PlaybackSpeed = 1
        effect.Volume = 0.5
        effect:Play()
        game.Debris:AddItem(effect, 2)
        local connection
        connection =
            game:GetService "RunService".Heartbeat:Connect(
            function()
                if dmgpart then
                    local ray = Ray.new(dmgpart.Position, dmgpart.CFrame.LookVector * 3)
                    local hit, hitPos = workspace:FindPartOnRayWithIgnoreList(ray, IgnoreList)
                    if hit and hit.Name == "Shield" then
                        connection:Disconnect()
                        dmgpart:Destroy()
                        local ShieldPart = game.ReplicatedStorage.Missiles.ShieldHit:Clone()
                        ShieldPart.Parent = workspace
                        ShieldPart.Position = hit.Position
                        local effect = Instance.new("Sound", ShieldPart)
                        effect.SoundId = "rbxassetid://192358310"
                        effect.MaxDistance = 300
                        effect.PlaybackSpeed = 2.5
                        effect.Volume = 0.5
                        effect:Play()
                        game.Debris:AddItem(ShieldPart, 2)
                        ShieldPart.Attachment.BlueMain.Enabled = true
                        ShieldPart.Attachment.BlueSparks.Enabled = true
                        hit.HitLight.Enabled = true
                        wait(0.15)
                        ShieldPart.Attachment.BlueMain.Enabled = false
                        ShieldPart.Attachment.BlueSparks.Enabled = false
                        hit.HitLight.Enabled = false
                    elseif hit and hit.Name == "SphereShield" then
                        connection:Disconnect()
                        dmgpart.Anchored = true
                        local ShieldPart = game.ReplicatedStorage.Missiles.ShieldHit:Clone()
                        ShieldPart.Parent = workspace
                        ShieldPart.Position = dmgpart.Position
                        dmgpart:Destroy()
                        local effect = Instance.new("Sound", ShieldPart)
                        effect.SoundId = "rbxassetid://192358310"
                        effect.MaxDistance = 300
                        effect.PlaybackSpeed = 2.5
                        effect.Volume = 0.5
                        effect:Play()
                        game.Debris:AddItem(ShieldPart, 2)
                        ShieldPart.Attachment.BlueMain.Enabled = true
                        ShieldPart.Attachment.BlueSparks.Enabled = true
                        hit.HitLight.Enabled = true
                        wait(0.15)
                        ShieldPart.Attachment.BlueMain.Enabled = false
                        ShieldPart.Attachment.BlueSparks.Enabled = false
                        hit.HitLight.Enabled = false
                    elseif dmgpart == nil then
                        connection:Disconnect()
                    end
                end
            end
        )
    end
)

A small downside of rendering everything client-sided is that exploiters would be able to destroy the projectile so they wouldn’t get hit.

I know but im trying to do this so the projectile collides with the shield instantly. I was so annoyed that it went through before.

Ok so i found out that the actual projectile shows on other clients but it just stays under the map and doesnt tween to the position.

What I typically do, is make my projectile on the server and assign it a vector3value. I then move it on the client by firing a remote to all clients before the loop in my projectile movement function. The remote once fired will place the part to the new position once the value inside it is changed from the server. This leads little exposed code on the client and hides the important stuff on the server.