Roblox · Анимации
Меч: клик — взмах, и урон наносится в тот момент анимации, когда клинок проходит перед персонажем (метка Hit). Сервер сам проверяет, кто перед мечом, — урон честный.
Синим — что нужно создать.
StarterPack └─ Sword (Tool) ├─ Handle (Part) — клинок; CanCollide выкл. │ └─ Swing (Sound) — свист ├─ Swing (Animation) — взмах; метка Hit — момент удара ├─ Hit (RemoteEvent) — клиент → сервер ├─ Configuration (Configuration) — Damage 25, Range 6, Cooldown 0.8, HitTime 0.25 ├─ SwordLocal (LocalScript) └─ SwordServer (Script)
Где: StarterPack → Sword · LocalScript
Зачем: Взмах и сигнал удара в нужный момент.
-- меч (Tool)
local tool = script.Parent
-- сигнал «удар» на сервер
local hitEvent = tool:WaitForChild("Hit")
-- анимация взмаха
local anim = tool:WaitForChild("Swing")
-- настройки
local config = tool:WaitForChild("Configuration")
-- загрузим, когда возьмём меч
local track = nil
-- идёт взмах
local busy = false
-- взяли меч
local function OnEquipped()
-- Humanoid
local humanoid = tool.Parent:FindFirstChildOfClass("Humanoid")
-- анимация задана
if humanoid and anim.AnimationId ~= "" then
-- загружаем
track = humanoid:WaitForChild("Animator"):LoadAnimation(anim)
-- главнее ходьбы
track.Priority = Enum.AnimationPriority.Action
-- конец проверки
end
-- конец функции
end
-- каждый раз, когда берут в руки
tool.Equipped:Connect(OnEquipped)
-- подобрали с земли: скрипт запустился уже в руках — Equipped был раньше
if tool.Parent and tool.Parent:FindFirstChildOfClass("Humanoid") then OnEquipped() end
-- клик с мечом в руках
tool.Activated:Connect(function()
-- ещё машем
if busy then return end
-- начали
busy = true
-- время взмаха
local start = os.clock()
-- удар уже отправлен?
local done = false
-- отправить удар
local function Hit()
-- только один раз за взмах
if done then return end
-- отправили
done = true
-- сервер проверит и нанесёт урон
hitEvent:FireServer()
-- конец функции
end
-- анимация есть
if track then
-- метка Hit в анимации — момент удара
local marker = track:GetMarkerReachedSignal("Hit"):Connect(Hit)
-- взмах
track:Play()
-- метки нет — удар через HitTime
task.delay(config.HitTime.Value, Hit)
-- ждём конец взмаха
track.Stopped:Wait()
-- метка больше не нужна
marker:Disconnect()
-- анимации нет
else
-- просто ждём
task.wait(config.HitTime.Value)
-- удар
Hit()
-- конец проверки
end
-- откат до следующего взмаха
task.wait(math.max(config.Cooldown.Value - (os.clock() - start), 0))
-- можно снова
busy = false
-- конец обработчика
end)Где: StarterPack → Sword · Script
Зачем: Проверка и урон тем, кто перед мечом.
-- меч (Tool)
local tool = script.Parent
-- сигнал от игрока
local hitEvent = tool:WaitForChild("Hit")
-- урон, дальность, откат
local config = tool:WaitForChild("Configuration")
-- звук взмаха
local swingSound = tool:WaitForChild("Handle"):WaitForChild("Swing")
-- время прошлого удара каждого игрока
local last = {}
-- игрок ударил
hitEvent.OnServerEvent:Connect(function(player)
-- его персонаж
local character = player.Character
-- меч должен быть у него в руках
if not character or tool.Parent ~= character then return end
-- слишком часто — не верим
if os.clock() - (last[player] or 0) < config.Cooldown.Value - 0.1 then return end
-- запоминаем
last[player] = os.clock()
-- центр персонажа
local root = character:FindFirstChild("HumanoidRootPart")
-- нет
if not root then return end
-- свист меча
swingSound:Play()
-- дальность удара
local range = config.Range.Value
-- коробка прямо перед персонажем
local box = root.CFrame * CFrame.new(0, 0, -range / 2)
-- настройки поиска
local params = OverlapParams.new()
-- не замечать список
params.FilterType = Enum.RaycastFilterType.Exclude
-- себя не бьём
params.FilterDescendantsInstances = {character}
-- кого уже ударили
local hit = {}
-- все детали в коробке
for _, part in ipairs(workspace:GetPartBoundsInBox(box, Vector3.new(4, 5, range), params)) do
-- модель детали
local model = part:FindFirstAncestorOfClass("Model")
-- живая?
local humanoid = model and model:FindFirstChildOfClass("Humanoid")
-- жива и ещё не ударена
if humanoid and humanoid.Health > 0 and not hit[humanoid] then
-- один удар — один урон
hit[humanoid] = true
-- урон
humanoid:TakeDamage(config.Damage.Value)
-- конец проверки
end
-- конец перебора
end
-- конец обработчика
end)Запусти Play (или Run) и убедись: