Rückstoß
Lektion 11 von 25 im Kurs Roblox-Spiel: Kampfarenen von Coddy.
Ein Hieb sollte das, was er trifft, wegschleudern. ApplyImpulse auf einer Wurzel gibt dem gesamten Körper einen Schubs. Ein Impuls ist die Geschwindigkeitsänderung mal Masse. Wenn du also mit AssemblyMass multiplizierst, schleudert er leichte und schwere Rigs auf dieselbe Weise weg:
theirRoot:ApplyImpulse((away * 30 + Vector3.new(0, 20, 0)) * theirRoot.AssemblyMass)away zeigt von dir zu ihnen, flach über den Boden: ihre Position minus deine, wobei Y auf null gesetzt wird, dann .Unit für eine Länge von 1.
Aufgabe
MittelLass der Slam alle, die er trifft, wegschleudern.
- In
abilities.Slam, nachhurt:local away = (theirRoot.Position - root.Position) * Vector3.new(1, 0, 1), dannaway = away.Unit, wenn sein Magnitude größer als 0 ist. - Dann
theirRoot:ApplyImpulse((away * Settings.SlamKnockback + Vector3.new(0, 40, 0)) * theirRoot.AssemblyMass).
Drücke „Spielen“, gehe zwischen den beiden roten Rigs hindurch und drücke E: Sie fliegen auseinander. Dann „Prüfen“.
Probier es selbst
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> wann sie zuletzt zugeschlagen haben
-- Roblox' eigene Schwertanimationen
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- Jeder Treffer im Spiel läuft hierüber
local function hurt(humanoid, amount)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
humanoid:TakeDamage(amount)
end
-- Ein Schwerthieb: Erst kommt die Animation, dann werden alle in der Box vor dir getroffen
local function swing(player)
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = time()
if lastSwing[player] and now - lastSwing[player] < Settings.SwingCooldown then
return
end
lastSwing[player] = now
character.Humanoid.Animator:LoadAnimation(slash):Play()
-- die Box vor dir, niemals dein eigener Körper
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- jeder humanoid einmal pro Schwerthieb
for _, part in workspace:GetPartBoundsInBox(box, Settings.HitboxSize, params) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
if humanoid and not hit[humanoid] then
hit[humanoid] = true
hurt(humanoid, Settings.SwordDamage)
end
end
end
-- Die Fähigkeiten, nach Namen geordnet: was jede einzelne bewirkt
local abilities = {}
-- Das eigene Gerät eines Spielers bewegt seinen Charakter, deshalb findet der Dash dort statt
function abilities.Dash(player)
remotes.Ability:FireClient(player, "Dash")
end
-- Alle um dich herum werden getroffen
function abilities.Slam(player, character, root)
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local hit = {}
for _, part in workspace:GetPartBoundsInRadius(root.Position, Settings.SlamRadius, params) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
local theirRoot = part.Parent:FindFirstChild("HumanoidRootPart")
if humanoid and theirRoot and not hit[humanoid] then
hit[humanoid] = true
hurt(humanoid, Settings.SlamDamage)
-- Lektion 11: Hier kommt der Rückstoß hin
end
end
end
-- Der Client fordert eine Fähigkeit anhand ihres Namens an. Der Server prüft: Ist es eine echte
-- Fähigkeit, lebt der Spieler und ist ihre Abklingzeit abgelaufen? Wann sie wieder bereit ist,
-- ist ein Attribut des Spielers, damit es auf seinem Bildschirm angezeigt werden kann.
remotes.Ability.OnServerEvent:Connect(function(player, name)
if typeof(name) ~= "string" or not abilities[name] then
return
end
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = workspace:GetServerTimeNow()
if now < (player:GetAttribute(name .. "ReadyAt") or 0) then
return
end
player:SetAttribute(name .. "ReadyAt", now + Settings.Cooldowns[name])
abilities[name](player, character, root)
end)
-- Jeder Spieler bekommt bei jedem neuen Leben ein Schwert
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
local sword = ServerStorage.Sword:Clone()
sword.Parent = player.Backpack
sword.Activated:Connect(function()
swing(player)
end)
end)
end)
-- Die Trainingspuppe: Ihr Gesundheitsbalken zeigt ihre Gesundheit an, und eine besiegte
-- Puppe erscheint nach kurzer Zeit als neue Kopie an derselben Stelle wieder
local function setupDummy(dummy)
local humanoid = dummy.Humanoid
humanoid.HealthChanged:Connect(function(health)
dummy.HealthBar.Back.Fill.Size = UDim2.fromScale(health / humanoid.MaxHealth, 1)
end)
humanoid.Died:Connect(function()
local spot = dummy:GetPivot()
task.wait(0.5)
dummy:Destroy()
task.wait(Settings.DummyRespawn)
local fresh = ServerStorage.Dummy:Clone()
fresh:PivotTo(spot)
fresh.Parent = workspace
setupDummy(fresh)
end)
end
setupDummy(workspace.Dummy)
Alle Lektionen in Roblox-Spiel: Kampfarenen
Übe selbstständig: Roblox-Playground