← 所有教程
第 4 篇教程

做出你的第一个 tower defense

敌人沿着路线走向你的基地,防御塔会射击离它最近的那一个。

免费60 分钟 · 新手 · Roblox Studio
1
第 1 / 8

设置场景

  1. 打开 Roblox Studio,点击 New Experience,选择 Baseplate 模板。
  2. 在 Explorer 里把鼠标移到 Workspace 上,点击 + 并添加一个 Folder。把它命名为 Path。
  3. 在 Workspace 里再添加第二个 Folder,命名为 Enemies。让它空着。游戏进行时,敌人会出现在里面。

更多细节

  • Baseplate 模板在开始页面的模板列表里。
  • 点 + 以后,输入 Folder 这个词可以很快找到它。用 F2 给文件夹改名。
  • 名字必须正好是 Path 和 Enemies,第一个字母要大写。脚本就是按这些名字去找的。
  • 在 Mac 上,每当教程说 Ctrl 的时候,都改用 Cmd 键。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

2
第 2 / 8

做出路线

  1. 添加一个 Part。把 Size 设为 6, 1, 6,打开 Anchored,并把它拖进 Path 文件夹。把它命名为 1。
  2. 用 Ctrl+D 复制它,把复制出来的那个移到大约 30 studs 远的地方。把它命名为 2。
  3. 重复这样做,直到你有 5 个 Part,名字是 1、2、3、4 和 5。摆放的时候让路线有几个拐弯。
  4. 敌人会从 1 走到 2,再走到 3,依此类推,每两个点之间走直线。

更多细节

  • 要把零件放进文件夹,就在 Explorer 里把它的名字拖到 Path 这个名字上。
  • 用 Ctrl+D 复制出来的零件已经在 Path 文件夹里了。你只需要移动它,再给它改名。
  • 名字就是数字:1、2、3、4、5。不要有字母,也不要有空格。
  • 让这些零件躺在地面上。敌人会飘在它们上面 2 studs 的地方。
常见错误. 漏掉了一个数字。如果少了 3 号 Part,敌人会停在 2 号,脚本还会报错。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

3
第 3 / 8

做出敌人

  1. 添加一个 Part。把 Shape 设为 Ball,把 Size 设为 3, 3, 3,并把它设成红色。打开 Anchored,关闭 CanCollide,并命名为 Enemy。
  2. 把鼠标移到 Enemy 上,点击 + 并添加一个 IntValue。把它命名为 Health,并把它的 Value 设为 3。
  3. 把 Enemy 拖进 ServerStorage。现在它是一个模板。游戏会复制出很多个它。

更多细节

  • Shape 是 Properties 里的一个列表。点开它,选择 Ball。
  • CanCollide 是 Properties 里的一个复选框。没有打勾的话,玩家和其他零件会直接穿过敌人。
  • 点 + 以后,输入 IntValue 就能找到它。点一下新的 IntValue,然后在 Properties 里把 Name 改成 Health,把 Value 改成 3。
  • 把 Enemy 拖进 ServerStorage 以后,它就从 Viewport 里消失了。这是对的。
小提示. 敌人要打开 Anchored,是因为由脚本来移动它。Anchored 的 Part 不受重力和推力的影响。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

4
第 4 / 8

做出基地

  1. 在路线的尽头、5 号 Part 的旁边添加一个大的 Part。打开 Anchored,并命名为 Base。
  2. 把鼠标移到 Base 上,点击 + 并添加一个 IntValue。把它命名为 Health,并把它的 Value 设为 10。
  3. 给 Base 添加一个 BillboardGui,Size 是 {0, 200}, {0, 50},StudsOffset 是 0, 8, 0。在里面添加一个 TextLabel,Size 是 {1, 0}, {1, 0},并打开 TextScaled。
  4. 给 Base 添加一个 Script,并粘贴下面的代码。
Base > Script
local base = script.Parent
local health = base.Health
local label = base.BillboardGui.TextLabel

local function update()
	if health.Value > 0 then
		label.Text = "Base: " .. health.Value
	else
		label.Text = "Game over"
	end
end

health.Changed:Connect(update)
update()

每一部分的作用

  • Changed 会在 Health 的值每次变化时运行。
  • update 函数会把新的数字写到基地上方的文字里。
  • 当 Health 变成 0 时,文字会显示 Game over,Waves 脚本也会停止派出敌人。

更多细节

  • 大小 10, 10, 10 的基地很合适。任何颜色都可以。
  • 基地的 Health 和敌人的 Health 是不同的物体。每一个都放在它自己的零件里面。
  • 对于 Size 和 StudsOffset,完全照着给出的样子输入数字,括号和逗号都要有,然后按 Enter。
  • 测试一下:按 F5。基地上方的标签显示 Base: 10。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

5
第 5 / 8

派出一波波敌人

  1. 把鼠标移到 ServerScriptService 上,点击 + 并添加一个 Script。把它命名为 Waves。
  2. 删掉里面已有的那一行,然后粘贴下面的代码。
  3. 按 Play。每隔 3 秒,1 号 Part 那里就会出现一个红色的球,并沿着路线移动。它走到终点时,基地会失去 1 点生命值。
ServerScriptService > Waves
local TweenService = game:GetService("TweenService")
local ServerStorage = game:GetService("ServerStorage")

local path = workspace:WaitForChild("Path")
local enemies = workspace:WaitForChild("Enemies")
local base = workspace:WaitForChild("Base")
local SPEED = 8

local function walk(enemy)
	for i = 2, #path:GetChildren() do
		local target = path[tostring(i)].Position + Vector3.new(0, 2, 0)
		local distance = (target - enemy.Position).Magnitude
		local info = TweenInfo.new(distance / SPEED, Enum.EasingStyle.Linear)
		local tween = TweenService:Create(enemy, info, {Position = target})
		tween:Play()
		tween.Completed:Wait()
		if not enemy.Parent then return end
	end

	base.Health.Value = math.max(0, base.Health.Value - 1)
	enemy:Destroy()
end

while base.Health.Value > 0 do
	task.wait(3)

	local enemy = ServerStorage.Enemy:Clone()
	enemy.Position = path["1"].Position + Vector3.new(0, 2, 0)
	enemy.Parent = enemies
	task.spawn(walk, enemy)
end

每一部分的作用

  • Clone 会从 ServerStorage 里复制一个 Enemy 模板。
  • walk 函数会让敌人按顺序走向路线上的每个 Part。distance / SPEED 让敌人在长短不同的路段上速度都一样。
  • task.spawn 让每个敌人各走各的,这样循环就可以继续派出新的敌人。

更多细节

  • 脚本会在新的标签页里打开。点一下代码里面,按 Ctrl+A,再按 Ctrl+V,替换掉所有内容。
  • 游戏运行时,敌人会出现在 Enemies 文件夹里。你可以在 Explorer 里看到它们。
  • 如果还没有防御塔,每个敌人都会到达基地。10 个敌人过后,标签会显示 Game over,不会再有敌人出现。
  • 如果 Output 里有红色的文字说找不到某个名字,就表示某个路径零件或某个文件夹的名字错了。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

6
第 6 / 8

做出防御塔

  1. 在路线拐弯的地方附近添加一个 Part。把 Size 设为 4, 8, 4,打开 Anchored,并命名为 Tower。
  2. 给 Tower 添加一个 Script,并粘贴下面的代码。
  3. 按 Play。防御塔每秒会打一次范围内离它最近的敌人。敌人会闪一下白光,被打中 3 次后就会消失。
Tower > Script
local tower = script.Parent
local enemies = workspace:WaitForChild("Enemies")
local RANGE = 25
local DAMAGE = 1

while true do
	task.wait(1)

	local target = nil
	local closest = RANGE
	for _, enemy in ipairs(enemies:GetChildren()) do
		local distance = (enemy.Position - tower.Position).Magnitude
		if distance < closest then
			target = enemy
			closest = distance
		end
	end

	if target then
		target.Health.Value -= DAMAGE
		if target.Health.Value <= 0 then
			target:Destroy()
		else
			target.Color = Color3.new(1, 1, 1)
			task.wait(0.1)
			target.Color = Color3.fromRGB(255, 60, 60)
		end
	end
end

每一部分的作用

  • 这个循环会量出防御塔到每个敌人的距离,并记住最近的那一个。
  • RANGE 是防御塔能打到多远。DAMAGE 是一次攻击会扣掉多少生命值。
  • 当 Health 变成 0 时,Destroy 会把敌人移除。

更多细节

  • 把防御塔放在离路径 8 到 12 studs 的地方。射程是向四面八方各 25 studs。
  • 一座防御塔要用 3 秒对付一个敌人,而每 3 秒就会来一个新敌人。所以,只有当敌人在射程内停留得足够久,一座防御塔才能守住这条路。
  • 白色的闪光只持续十分之一秒。要仔细看才能看到。
  • 要做第二座防御塔,就选中 Tower,按 Ctrl+D,然后移动复制品。脚本会跟着一起过来。
小提示. 防御塔放在拐弯处旁边效果最好,因为敌人在那里待在射程内的时间更长。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

7
第 7 / 8

测试并调整难度

  1. 按 F5,看几波敌人。
  2. 如果没有一个敌人能到达基地,说明游戏太简单了。如果基地很快就失去了所有生命值,说明太难了。
  3. 用三个数字来调整:Waves 里的等待时间、敌人的 Health 值,还有防御塔的 DAMAGE。
  4. 按 Shift+F5 停止。如果哪里出了问题,从 Window 菜单里打开 Output 窗口,看看红色的文字。

更多细节

  • 一次只改一个数字,然后再玩一遍。不然你就不知道是哪个改动起了作用。
  • 等待时间就是 Waves 脚本靠近末尾的 task.wait(3) 里的那个数字。数字越小,敌人出来得越快。
  • 敌人的 Health 在 ServerStorage 里的 Enemy 里面。防御塔的 DAMAGE 在 Tower 脚本的最上面。
  • 一个不错的第一个目标:用两座防御塔,让基地撑过两分钟。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

8
第 8 / 8

发布它

  1. 选择 File → Publish to Roblox。给游戏起一个名字,再写一段简短的介绍。
  2. 在 Creator Hub 网站上打开你的游戏,填写 Maturity 问卷。
  3. 把游戏设为 Public,然后把链接发给一位朋友。

更多细节

  • 第一次发布时,Studio 会问你要一个名字和一段介绍。点 Create。
  • Creator Hub 就是网站 create.roblox.com。用同一个账号登录,然后在列表里点你的游戏。
  • 游戏公开之前,Roblox 可能还会要求更多信息,比如对账号做年龄验证。页面会告诉你还缺什么。
  • 如果你不满 18 岁,请和家长一起完成这一步。
小提示. 把游戏给朋友看,只问一个问题:太简单还是太难?然后改一个数字,再测试一次。
这一步我做不出来

先检查这三件事

  • 每个零件和脚本的名字都要和教程里的完全一样,大小写也要一样。
  • 脚本要放在正确的物体里面。看一看代码框上面的标签。
  • 从 Window 菜单里打开 Output 窗口。红色的文字会告诉你哪个脚本、哪一行有问题。

还是不行?给我们写信 →

现在自己改一改

  • 再加一个第二个防御塔,射程短一点,DAMAGE 是 2。
  • 让敌人的波次随着时间变得越来越快。提示:把等待时间放进一个变量里,每派出一个敌人就让它小一点点。
  • 给基地 20 点生命值,让每个敌人扣掉 2 点。