Menu
CoddyTech

조준하기

Coddy의 Roblox 게임: 타워 디펜스 코스 레슨. 18개 중 7번째.

타워는 Range 안의 지면을 지킵니다. 각 타워는 별도의 스레드에서 자체 루프를 실행합니다. 범위 내에서 가장 가까운 살아 있는 적을 찾고, Head가 적을 향하도록 회전시킵니다.

가장 가까운 적을 찾는 것은 전형적인 루프입니다. 아무것도 찾지 못한 상태에서 시작하고, 범위를 최적 거리로 설정한 다음, 지금까지의 최적 거리보다 가까운 적이 있으면 그 적을 선택합니다.

local best, bestDistance = nil, range
for _, enemy in enemies:GetChildren() do
	-- 지금까지 가장 가까운 대상보다 더 가까운가? 그렇다면 그 대상을 유지한다
end
return best

CFrame.lookAt(from, at)은 from 위치에 서서 at을 바라보는 CFrame이므로, 헤드를 움직이지 않고 회전시킵니다.

tower.Head.CFrame = CFrame.lookAt(tower.Head.Position, target.HumanoidRootPart.Position)

무한히 실행되는 루프는 매번 반복할 때마다 기다려야 합니다. 그렇지 않으면 게임이 멈춥니다. 대상을 찾았는지 여부와 관계없이 0.1초를 기다립니다.

challenge icon

챌린지

중급
  1. nearestEnemy(position, range)를 작성합니다. HumanoidRootPart가 있고 Health > 0인 살아 있는 적 중에서 position에 가장 가까우며 range 이내에 있는 적을 찾고, 없으면 nil을 반환합니다.
  2. runTower(tower)를 작성합니다. 타워가 게임에 있는 동안, 타워의 머리에서 Settings.Towers[tower.Name].Range 이내에 있는 가장 가까운 적을 찾고, 머리가 적을 향하도록 돌린 다음 task.wait(0.1)을 실행합니다.
  3. placeTower의 끝에서 task.spawn(runTower, tower)로 실행합니다.

Play를 눌러 시작 지점 옆에 Archer를 짓고, 타워가 적을 추적하는 모습을 확인합니다. 그런 다음 Check를 누릅니다.

직접 해보기

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

local remotes = game.ReplicatedStorage.Remotes
local enemies = workspace.Enemies
local towers = workspace.Towers

print("The base can take " .. Settings.BaseHealth .. " hits")

-- 순서대로 정렬된 경유지들(이름은 1, 2, 3...)
local waypoints = workspace.Path.Waypoints:GetChildren()
table.sort(waypoints, function(a, b)
	return tonumber(a.Name) < tonumber(b.Name)
end)

-- workspace의 속성으로 저장된 기지의 체력: 모든 클라이언트가 읽을 수 있음
workspace:SetAttribute("BaseHealth", Settings.BaseHealth)

-- 모든 플레이어는 리더보드에 Money를 받음
Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Value = Settings.StartMoney
	money.Parent = leaderstats
end)

-- 적이 기지에 도착함
local function damageBase(amount)
	local health = math.max(0, workspace:GetAttribute("BaseHealth") - amount)
	workspace:SetAttribute("BaseHealth", health)
end

-- 적을 경로를 따라 이동시킴. MoveTo는 8초가 지나면 포기하고 이를 알림
-- (MoveToFinished가 false를 반환함). 따라서 느린 적은 도착할 때까지 다시 이동 명령을 받음.
local function walkPath(enemy)
	local humanoid = enemy.Humanoid
	for i = 2, #waypoints do
		repeat
			humanoid:MoveTo(waypoints[i].Position)
		until humanoid.MoveToFinished:Wait() or not enemy.Parent
		if not enemy.Parent then
			return
		end
	end
	-- 적이 기지에 도착함
	damageBase(Settings.Enemies[enemy.Name].Damage)
	enemy:Destroy()
end

-- 입구에서 생성되어 경로를 따라 이동하는 새로운 적
local function spawnEnemy(kind)
	local enemy = ServerStorage.Enemies[kind]:Clone()
	-- 첫 번째 경유지 바로 위에 배치됨
	enemy:PivotTo(waypoints[1].CFrame + Vector3.new(0, 5, 0))
	local info = Settings.Enemies[kind]
	enemy.Humanoid.MaxHealth = info.Health
	enemy.Humanoid.Health = info.Health
	enemy.Humanoid.WalkSpeed = info.Speed
	enemy.Parent = enemies
	task.spawn(walkPath, enemy)
	return enemy
end

-- 발판 위에 타워를 건설함
local function placeTower(pad, kind)
	local tower = ServerStorage.Towers[kind]:Clone()
	tower:PivotTo(pad.CFrame + Vector3.new(0, pad.Size.Y / 2 + 1, 0))
	tower.Parent = towers
end

-- 클라이언트가 발판 위에 타워를 건설해 달라고 요청함
remotes.Place.OnServerEvent:Connect(function(player, pad, kind)
	placeTower(pad, kind)
end)

-- 한 웨이브: 적을 하나씩 생성한 뒤 모두 사라질 때까지 기다림
local function runWave(list)
	for _, kind in list do
		spawnEnemy(kind)
		task.wait(Settings.SpawnGap)
	end
	while #enemies:GetChildren() > 0 do
		task.wait(0.2)
	end
end

-- 각 웨이브는 휴식 시간이 지난 뒤 시작
for i, list in Settings.Waves do
	task.wait(Settings.WaveBreak)
	runWave(list)
end
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Roblox 게임: 타워 디펜스의 모든 레슨