Menu
CoddyTech

Lướt nhanh bằng Q

Bài học 7 trên 25 trong khóa học Trò chơi Roblox: Đấu trường của Coddy.

Một cú lao là một lực đẩy: đặt AssemblyLinearVelocity của nhân vật gốc sẽ khiến nhân vật bật đi. Nhưng Roblox để thiết bị của mỗi người chơi xử lý vật lý của chính nhân vật đó, nên lực đẩy do máy chủ đặt hầu như không làm họ di chuyển. Máy chủ quyết định, còn LocalScript của người chơi thực hiện lực đẩy.

Máy chủ lưu các kỹ năng trong một bảng, theo tên, rồi gửi xác nhận cú lao về máy khách của người chơi đó bằng FireClient, nơi OnClientEvent nhận được xác nhận này:

remotes.Ability.OnClientEvent:Connect(function(name)
	if name == "Hop" then
		root.AssemblyLinearVelocity = Vector3.new(0, 50, 0)
	end
end)
challenge icon

Thử thách

Trung bình

Tạo cú lướt bằng phím Q: máy chủ xác nhận, thiết bị của bạn đẩy nhân vật đi.

  1. Trong BattleServer, thay lệnh in ra bằng bảng abilities: abilities.Dash(player) gọi remotes.Ability:FireClient(player, "Dash").
  2. Trình xử lý chạy abilities[name](player, character, root) khi hàm này tồn tại.
  3. Trong BattleClient, khi nhận remotes.Ability.OnClientEvent với "Dash", đặt vận tốc của root thành root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0).

Nhấn Chơi rồi nhấn Q: bạn sẽ lướt về phía trước. Sau đó nhấn Kiểm tra.

Tự làm thử

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)

local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> thời điểm vung kiếm gần nhất

-- Hoạt ảnh vung kiếm có sẵn của Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"

print("Swords deal " .. Settings.SwordDamage .. " damage")

-- Một lần vung kiếm: phát hoạt ảnh, rồi đánh trúng mọi người trong vùng phía trước bạn
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()
	-- Vùng phía trước bạn, không bao gồm cơ thể bạn
	local params = OverlapParams.new()
	params.FilterDescendantsInstances = { character }
	local box = root.CFrame * CFrame.new(0, 0, -3)
	local hit = {} -- Mỗi humanoid chỉ trúng đòn một lần cho mỗi lần vung kiếm
	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
			humanoid:TakeDamage(Settings.SwordDamage)
			print(humanoid.Parent.Name .. " is at " .. humanoid.Health)
		end
	end
end

-- Máy khách yêu cầu một kỹ năng theo tên
remotes.Ability.OnServerEvent:Connect(function(player, name)
	print(player.Name .. " asked for " .. name)
end)

-- Mỗi lần xuất hiện, người chơi đều nhận một thanh kiếm
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)

-- Hình nộm tập luyện: thanh máu thay đổi theo lượng máu; khi bị đánh gục,
-- hình nộm sẽ xuất hiện lại sau một lát dưới dạng bản sao mới ở cùng vị trí
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)

Tất cả bài học trong Trò chơi Roblox: Đấu trường

Tự luyện tập: Playground Roblox