§ How to · with Picoo

How to make a Roblox katana combat system (anime style)

By Sametcan Tasgiran, Founder & Developer·Published ·Updated

Anime combat games — Demon Slayer-style katana fighters especially — need two things working together: a katana that actually equips in the player's hand and glows, and a combo/block/parry/dash system that feels sharp. Picoo builds them with two recipes: ask for a fire katana and it applies sword_tool for the weapon; ask for a katana combat system with combos, block and parry and it applies combat_system for the mechanics.

sword_tool (glowing katana + trail) + combat_system (combo/block/parry/dash) · two recipes · server-authoritative.

Equipping katana (fixed grip)

The Tool ships with a configured Handle — CanCollide off, Anchored off, Massless on — and a GripPos that seats the hilt, so it actually sits in the hand. A colliding Handle is a common reason hand-built weapons fail to equip.

Glowing element blade

Pass element: fire / ice / void / lightning / shadow / holy for a Neon themed blade, a PointLight aura, streaming particles, and a swing trail — the trendy anime-blade look, all code, no uploaded assets.

Swing trail on M1

Two attachments down the blade drive a Trail that flicks on for 0.35 s during the swing and off after — the signature ribbon behind every katana slash.

Procedural cinematic swing

swing_style: procedural arcs the blade through a slash via Tool.Grip plus an arm follow-through — a code-driven swing for when you can't upload a keyframe animation.

Full combat mechanics

combat_system adds an M1 combo, heavy attack, block, parry window, dash and spin attack, with every hit decided on the server. It also gives each player its own neon StarterSword.

No uploaded assets required

Glow, particles and trail are generated in code, and the swing is Roblox's built-in slash or the procedural one. No mesh upload, no animation upload, no moderation wait.

Files Picoo ships for this prompt

8 files · 1356 lines · two recipe calls

StarterPack/Katana (Tool + Handle)

sword_tool: equipping Tool with a 5.5-stud Neon blade Handle, CanCollide off, Massless on, GripPos set

instance

StarterPack/Katana/KatanaLocal.lua

sword_tool: builds the aura, fire particles and swing trail at load; fires the swing and toggles the trail

73 lines

ServerScriptService/KatanaServer.lua

sword_tool: checks the Katana is held, 0.5 s cooldown, 25 damage to the nearest target within 8 studs, hit sound and burst

102 lines

ReplicatedStorage/Remotes/KatanaSwing

sword_tool: RemoteEvent the katana fires on each swing

instance

ServerScriptService/CombatSystem/HitboxModule.lua

combat_system: GetPartBoundsInBox hitbox in front of the attacker

60 lines

ServerScriptService/CombatSystem/CombatServer.lua

combat_system: combo, stamina, block, parry, stun, dash i-frames, spin attack and all damage

514 lines

StarterPlayer/StarterPlayerScripts/CombatClient.lua

combat_system: M1/E/F/Q/R/Shift input, arm swings, client dash, stamina and combo HUD

607 lines

ReplicatedStorage/CombatRemotes (CombatAction + CombatState)

combat_system: the intent RemoteEvent and the HUD state RemoteEvent

instance

Sample output: StarterPack/Katana/KatanaLocal.lua

--!strict
-- Generated by Picoo recipe: sword_tool (LocalScript inside Tool)
local Tool = script.Parent :: Tool
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local SwordSwing: RemoteEvent = Remotes:WaitForChild("KatanaSwing") :: RemoteEvent
local Handle = Tool:WaitForChild("Handle") :: BasePart

-- Element VFX (built once, parented to the Handle so they follow the blade)
local aura = Instance.new("PointLight")
aura.Color = Color3.fromRGB(255, 120, 40)
aura.Range = 11
aura.Brightness = 3
aura.Parent = Handle

local flame = Instance.new("ParticleEmitter")
flame.Texture = "rbxasset://textures/particles/fire_main.dds"
flame.Color = ColorSequence.new(Color3.fromRGB(255, 170, 40), Color3.fromRGB(200, 30, 10))
flame.Rate = 55
flame.Lifetime = NumberRange.new(0.4, 0.9)
flame.Speed = NumberRange.new(2, 6)
flame.Size = NumberSequence.new({ NumberSequenceKeypoint.new(0, 1.4), NumberSequenceKeypoint.new(1, 0) })
flame.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.2), NumberSequenceKeypoint.new(1, 1) })
flame.LightEmission = 1
flame.EmissionDirection = Enum.NormalId.Top
flame.Parent = Handle

-- Swing trail — two attachments down the blade's long (Z) axis, disabled at rest
local a0 = Instance.new("Attachment"); a0.Name = "TrailBottom"; a0.Position = Vector3.new(0, 0, -2.5); a0.Parent = Handle
local a1 = Instance.new("Attachment"); a1.Name = "TrailTop";    a1.Position = Vector3.new(0, 0, 2.5);  a1.Parent = Handle
local trail = Instance.new("Trail")
trail.Attachment0 = a0
trail.Attachment1 = a1
trail.Lifetime = 0.3
trail.Color = ColorSequence.new(Color3.fromRGB(255, 90, 20))
trail.Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0), NumberSequenceKeypoint.new(1, 1) })
trail.LightEmission = 1
trail.FaceCamera = true
trail.WidthScale = NumberSequence.new({ NumberSequenceKeypoint.new(0, 1), NumberSequenceKeypoint.new(1, 0) })
trail.Enabled = false
trail.Parent = Handle
local CLIENT_COOLDOWN = 0.5
local lastSwing = 0

Tool.Activated:Connect(function()
	local now = tick()
	if (now - lastSwing) < CLIENT_COOLDOWN then return end
	lastSwing = now

	SwordSwing:FireServer()

	local character = Tool.Parent
	local humanoid = character and character:FindFirstChildOfClass("Humanoid")
	-- The server's toolanim drives the default Animate script. Only when the game
	-- has removed or replaced Animate do we play the Roblox-owned slash ourselves,
	-- choosing the id that matches the rig (the R15 id cannot drive an R6 rig).
	if humanoid and character and not character:FindFirstChild("Animate") then
		local animator = humanoid:FindFirstChildOfClass("Animator")
		if animator then
			local anim = Instance.new("Animation")
			anim.AnimationId = if humanoid.RigType == Enum.HumanoidRigType.R6 then "rbxassetid://129967390" else "rbxassetid://522635514"
			local track = animator:LoadAnimation(anim)
			track.Priority = Enum.AnimationPriority.Action
			track:Play()
			anim:Destroy()
		end
	end

	if trail then
		trail.Enabled = true
		task.delay(0.35, function() trail.Enabled = false end)
	end
end)

Building a Roblox katana combat system (anime style)

Anime combat games are one of the biggest and fastest-growing genres on Roblox, and the katana is their signature weapon. Two problems stop most developers cold: the katana won't stay in the player's hand, and there's no way to get that glowing, trailing, "burning" blade look without a modeling pipeline. Picoo solves both in code.

The equip problem is almost always the Handle. A Roblox Tool equips by welding a child part named exactly "Handle" to the character's hand. If that Handle has CanCollide on, the physics fight the weld and the weapon flies off or never appears. Picoo's sword_tool recipe ships the Handle with CanCollide = false, Anchored = false, Massless = true, and a GripPos that seats the hilt, so the katana seats in the hand every single time — no manual weld debugging.

The look is pure code. Ask for a fire katana and sword_tool builds the Handle as a Neon blade in the fire colour; when the tool loads, its LocalScript parents a PointLight for the aura, adds a streaming ParticleEmitter, and builds a Trail from two attachments down the blade — enabled only during the swing so you get the ribbon behind each slash. Because it is all instance properties and Instance.new, there is no mesh upload and no animation upload, which means no moderation wait and nothing that can get flagged.

Real keyframe animation is the one thing code genuinely cannot produce — uploading a KeyframeSequence to Roblox is a moderated asset operation. By default the swing is Roblox's own slash: the server drops a toolanim value on the Tool and the default Animate script plays it on R6 and R15. Ask for a procedural swing and the LocalScript arcs the blade through the slash by tweening Tool.Grip and adds an arm follow-through on the shoulder's Motor6D. It is wrapped in pcall so it can never throw a runtime error, and it needs no upload.

For a complete anime fighter, add the combat_system recipe with a second prompt such as "katana combat system with combos, block and parry": an M1 combo chain, a heavy attack, a block, a parry window that stuns the attacker, a dash with invincibility frames, a spin attack and stamina — every damage calculation on the server. sword_tool makes the katana look and equip right; combat_system makes the fighting feel right.

See more on the Luau generator, the AI Luau script writer, the 3D model generator and the game builder, read how Picoo compares with ChatGPT, or browse the full blog.

Frequently asked

Why won't my katana appear in the player's hand?+

Almost always the Handle collides or sits wrong in the grip. A weapon Tool needs a BasePart child named exactly 'Handle' with CanCollide = false, Anchored = false and Massless = true, plus a grip offset that puts the hilt in the palm. Picoo's sword_tool recipe sets all of these on the Handle when it builds the Tool, along with RequiresHandle and GripPos, so the katana equips correctly every time.

Can Picoo make a real cinematic katana animation?+

A real uploaded keyframe animation needs a Roblox asset upload (moderated) that code cannot do. By default the katana plays Roblox's own tool slash, which the default Animate script picks up from a toolanim value the server sets. Ask for a procedural swing (swing_style: procedural) and the LocalScript instead arcs the blade by tweening Tool.Grip and adds an arm follow-through on the shoulder Motor6D, with no upload.

How do I get the glowing / flaming blade look?+

Ask for a fire katana (element: 'fire'), or ice, void, lightning, shadow or holy. sword_tool builds the Handle as a Neon blade in the element's colour, and the katana's LocalScript adds a PointLight aura, element particles and a swing trail at load, so it shows up instantly with no mesh or texture upload.

Does it come with combos and parry?+

Add the combat_system recipe: ask for a katana combat system with combos, block and parry. It adds a 4-hit M1 combo, heavy attack, block, a parry window that stuns the attacker, a dash with i-frames, a spin attack and stamina, all decided on the server, and gives each player a neon StarterSword on spawn.

Is this exploit-safe?+

Damage is decided on the server in both recipes. The katana's client only fires a swing event; KatanaServer checks that the player is holding the Katana, enforces the cooldown, finds the nearest target in range itself and applies the damage. combat_system works the same way through its CombatAction remote. Nothing a client sends becomes a damage number.

Related Picoo prompts