local A = "Hello"local B = " World!"print(A .. B)print(#A)
조건문
-- if 조건 then-- 실행할 내용-- else if then-- else-- endif a == 1 then print("hi")end
반복문
-- for 변수 = 초기값, 최종값, 증감값 do-- 반복할 내용-- endfor num = 1, 10, 1 do print(num)end
함수
function name(arg1, arg2, ...) -- some codeend
적용해보기
Kill block
-- kill blocklocal lava = script.Parent -- 이 스크립트의 부모 파트를 lava 변수에 저장한다local function killPlayer(otherPart) -- lava에 닿은 파트를 otherPart로 받아 실행되는 함수 local partParent = otherPart.Parent -- 닿은 파트의 부모 객체를 가져온다 local humanoid = partParent:FindFirstChild("Humanoid") -- 부모 객체 안에서 Humanoid를 찾는다 if humanoid then -- Humanoid가 존재한다면, 즉 플레이어 캐릭터라면 humanoid.Health = 0 -- 체력을 0으로 만들어 캐릭터를 죽인다 endendlava.Touched:Connect(killPlayer) -- lava에 무언가 닿으면 killPlayer 함수를 실행한다
Faded Block
-- fade blocklocal platform = script.Parentlocal function fade() for count = 1, 10 do platform.Transparency = count / 10 wait(0.1) end platform.CanCollide = false wait(5) platform.CanCollide = true platform.Transparency = 0endplatform.Touched:Connect(fade)
리더보드 설정
ServerScriptService/SetupPoints
-- server leader boardlocal Players = game:GetService("Players")local function onPlayerAdded(player) local leaderstats = Instance.new("Folder") leaderstats.Name = "leaderstats" leaderstats.Parent = player local points = Instance.new("IntValue") points.Name = "Points" points.Value = 0 points.Parent = leaderstatsendPlayers.PlayerAdded:Connect(onPlayerAdded)
점수 얻기
-- get pointlocal part = script.Parentlocal canGet = truelocal function onTouch(otherPart) local humanoid = otherPart.Parent:FindFirstChild('Humanoid') if humanoid then local player = game.Players:FindFirstChild(otherPart.Parent.Name) if player and canGet then print("Get Point") canGet = false player.leaderstats.Points.Value = player.leaderstats.Points.Value + 1 -- 만약 다시 점수를 얻어야하는 경우라면 -- wait(10) -- canGet = true end endendpart.Touched:Connect(onTouch)
BGM 추가
local music = game.Workspace.Script["Happy Song"]music:Play()-- attribute -> looped -> true
무빙 플랫폼
Structure
ServerScriptService├─ MovingPlatformService└─ Modules └─ MovingPlatform ← ModuleScriptWorkspace└─ Green ├─ Part ├─ Part └─ MovingPlatformConfig ← Script
MovingPlatformService
local CollectionService = game:GetService("CollectionService")local ServerScriptService = game:GetService("ServerScriptService")local MovingPlatform = require(ServerScriptService.Modules.MovingPlatform)local TAG_NAME = "MovingPlatform"local function applyToModel(instance: Instance) if not instance:IsA("Model") then warn("[MovingPlatform] 태그는 Model에 붙여야 합니다:", instance:GetFullName()) return end local direction = instance:GetAttribute("MoveDirection") or Vector3.new(1, 0, 0) local distance = instance:GetAttribute("MoveDistance") or 20 local speed = instance:GetAttribute("MoveSpeed") or 6 local friction = instance:GetAttribute("Friction") or 1 MovingPlatform.apply(instance, direction, distance, speed, friction)endlocal taggedModels = CollectionService:GetTagged(TAG_NAME)print("[MovingPlatform] 찾은 모델 개수:", #taggedModels)for _, instance in ipairs(taggedModels) do applyToModel(instance)endCollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(instance) applyToModel(instance)end)
MovingPlatform
local RunService = game:GetService("RunService")local MovingPlatform = {}local activeConnections = {}local function getParts(model: Model): { BasePart } local parts = {} for _, descendant in ipairs(model:GetDescendants()) do if descendant:IsA("BasePart") then table.insert(parts, descendant) end end return partsendfunction MovingPlatform.apply( model: Model, direction: Vector3, distance: number, speed: number, friction: number?) if activeConnections[model] then activeConnections[model]:Disconnect() activeConnections[model] = nil end local parts = getParts(model) if #parts == 0 then warn("[MovingPlatform] Model 안에 BasePart가 없습니다:", model:GetFullName()) return end if direction.Magnitude == 0 then warn("[MovingPlatform] direction이 Vector3.zero입니다:", model:GetFullName()) return end if distance <= 0 then warn("[MovingPlatform] distance는 0보다 커야 합니다:", model:GetFullName()) return end if speed <= 0 then warn("[MovingPlatform] speed는 0보다 커야 합니다:", model:GetFullName()) return end friction = friction or 1 for _, part in ipairs(parts) do part.Anchored = true part.CanCollide = true part.CanTouch = true part.CustomPhysicalProperties = PhysicalProperties.new( 1, -- Density friction, -- Friction 0, -- Elasticity 1, -- FrictionWeight 1 -- ElasticityWeight ) end local startPivot = model:GetPivot() local goalPivot = startPivot + direction.Unit * distance local travelTime = distance / speed local elapsed = 0 local lastPivot = startPivot local connection connection = RunService.Heartbeat:Connect(function(deltaTime) if not model.Parent then connection:Disconnect() activeConnections[model] = nil return end elapsed += deltaTime local cyclePosition = (elapsed / travelTime) % 2 local linearAlpha if cyclePosition <= 1 then linearAlpha = cyclePosition else linearAlpha = 2 - cyclePosition end local easedAlpha = 0.5 - math.cos(linearAlpha * math.pi) * 0.5 local nextPivot = startPivot:Lerp(goalPivot, easedAlpha) local deltaPosition = nextPivot.Position - lastPivot.Position if deltaTime > 0 then local velocity = deltaPosition / deltaTime for _, part in ipairs(parts) do part.AssemblyLinearVelocity = velocity end end model:PivotTo(nextPivot) lastPivot = nextPivot end) activeConnections[model] = connection print("[MovingPlatform] 적용됨:", model:GetFullName()) return connectionendreturn MovingPlatform
움직일 파트의 스크립트
local CollectionService = game:GetService("CollectionService")local model = script.ParentCollectionService:AddTag(model, "MovingPlatform")model:SetAttribute("MoveDirection", Vector3.new(1, 0, 0))model:SetAttribute("MoveDistance", 10)model:SetAttribute("MoveSpeed", 6)model:SetAttribute("Friction", 1)
local Players = game:GetService("Players")local ReplicatedStorage = game:GetService("ReplicatedStorage")local CharacterController = require(ReplicatedStorage.Modules.CharacterController)CharacterController.start(Players.LocalPlayer)
CharacterController
--!strict-- Client character actions: lower extra jump while airborne.local UserInputService = game:GetService("UserInputService")local Workspace = game:GetService("Workspace")local CharacterController = {}local DOUBLE_JUMP_FALLBACK_UP_VELOCITY = 50local DOUBLE_JUMP_HEIGHT_RATIO = 0.72local DOUBLE_JUMP_FORWARD_BOOST = 4local DOUBLE_JUMP_MIN_AIR_TIME = 0.12local function isJumpInput(input: InputObject) return input.KeyCode == Enum.KeyCode.Space or input.KeyCode == Enum.KeyCode.ButtonAendfunction CharacterController.start(player: Player) local currentHumanoid: Humanoid? = nil local currentRoot: BasePart? = nil local becameAirborneAt = 0 local canDoubleJump = false local usedDoubleJump = false local nextDoubleJumpAt = 0 -- 추가: 점프 입력을 계속 누르고 있는지 확인 local jumpInputHeld = false -- 추가: 첫 번째 점프 이후 점프 키를 뗐는지 확인 local releasedJumpAfterAirborne = false local function resetDoubleJump() becameAirborneAt = 0 canDoubleJump = false usedDoubleJump = false releasedJumpAfterAirborne = false end local function getNormalJumpVelocity(humanoid: Humanoid) local normalJumpVelocity = DOUBLE_JUMP_FALLBACK_UP_VELOCITY if humanoid.UseJumpPower then normalJumpVelocity = humanoid.JumpPower else normalJumpVelocity = math.sqrt(2 * Workspace.Gravity * humanoid.JumpHeight) end if normalJumpVelocity <= 0 then return DOUBLE_JUMP_FALLBACK_UP_VELOCITY end return normalJumpVelocity end local function doExtraJump() local humanoid = currentHumanoid local root = currentRoot if not humanoid or not root or humanoid.Health <= 0 then return end if usedDoubleJump or not canDoubleJump then return end if os.clock() < nextDoubleJumpAt then return end if os.clock() - becameAirborneAt < DOUBLE_JUMP_MIN_AIR_TIME then return end if humanoid.FloorMaterial ~= Enum.Material.Air then return end -- 핵심: -- 첫 번째 점프 후 스페이스바를 한 번 떼야만 더블 점프 허용 if not releasedJumpAfterAirborne then return end usedDoubleJump = true canDoubleJump = false nextDoubleJumpAt = os.clock() + 0.25 local currentVelocity = root.AssemblyLinearVelocity local forwardBoost = root.CFrame.LookVector * DOUBLE_JUMP_FORWARD_BOOST local upVelocity = getNormalJumpVelocity(humanoid) * DOUBLE_JUMP_HEIGHT_RATIO root.AssemblyLinearVelocity = Vector3.new( currentVelocity.X + forwardBoost.X, upVelocity, currentVelocity.Z + forwardBoost.Z ) humanoid:ChangeState(Enum.HumanoidStateType.Jumping) end local function bindCharacter(character: Model) currentHumanoid = character:WaitForChild("Humanoid") :: Humanoid currentRoot = character:WaitForChild("HumanoidRootPart") :: BasePart resetDoubleJump() currentHumanoid.StateChanged:Connect(function(_, newState: Enum.HumanoidStateType) if newState == Enum.HumanoidStateType.Jumping or newState == Enum.HumanoidStateType.Freefall then if becameAirborneAt == 0 then becameAirborneAt = os.clock() -- 공중에 진입했을 때 점프 키를 이미 누르고 있다면, -- 아직 더블 점프 불가 releasedJumpAfterAirborne = not jumpInputHeld end if not usedDoubleJump then canDoubleJump = true end elseif newState == Enum.HumanoidStateType.Landed or newState == Enum.HumanoidStateType.Running or newState == Enum.HumanoidStateType.RunningNoPhysics then resetDoubleJump() end end) end -- 점프 키를 누르고 있는지 추적 UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessed: boolean) if gameProcessed then return end if isJumpInput(input) then jumpInputHeld = true end end) -- 첫 번째 점프 이후 점프 키를 떼면 더블 점프 가능 상태로 전환 UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessed: boolean) if isJumpInput(input) then jumpInputHeld = false if becameAirborneAt ~= 0 and not usedDoubleJump then releasedJumpAfterAirborne = true end end end) UserInputService.JumpRequest:Connect(function() doExtraJump() end) if player.Character then bindCharacter(player.Character) end player.CharacterAdded:Connect(bindCharacter)endreturn CharacterController