공부/Roblox Studio

[로블록스 스튜디오] Pet Simulation 강좌 따라하기

굴러다니다니 2023. 10. 5. 17:16
728x90

https://www.youtube.com/watch?v=BVPt0ClPvYE&list=PLH1di03gos6ZuOcenzr5QSvkaKbdBIWcC&index=1 

새로 배운점

  • Billboard Gui (약간 유니티로 따지면 World Space로 만드는 Canvas)
  • Surface Gui (물건의 표면에만 보이게 하는 Canvas)
  • Click Detector (추가하면 클릭이 가능해짐)

 

Pet_Follower 코드

local runService = game:GetService("RunService")

local playerPets = workspace:WaitForChild("MainFolder_Workspace"):WaitForChild("PlayerPets")
//waitforchild: 개체가 생성될 때까지 기다리고 찾음, 로딩 속도 때문에+ , 3하면 3초내에 못찾으면 관둠
local circle = math.pi * 2

local function getPosition(angle, radius)
	local x = math.cos(angle) * radius
	local z = math.sin(angle) * radius
	return x, z
end

local function positionPets(character, folder, dt)
	for i, pet in pairs(folder:GetChildren()) do //folder의 자식들을 하나하나 탐색
		local radius = 4+#folder:GetChildren() //#: 길이를 의미 
		local angle = i * (circle / #folder:GetChildren())
		local x, z = getPosition(angle, radius)
		local _, characterSize = character:GetBoundingBox()
		local _, petSize = pet:GetBoundingBox()

		local offsetY = - characterSize.Y/2 + petSize.Y/2
		local sin = (math.sin(15 * time() + 1.6)/.5)+1
		local cos = math.cos(7 * time() + 1)/4

		if pet:FindFirstChild("Attack").Value ~= nil then //attack이 있으면
			if pet:FindFirstChild("Walks") then //걷는애면
				local position = (pet:FindFirstChild("Attack").Value.PrimaryPart.CFrame * CFrame.new(x, 0, z)).p
				local lookAt = pet:FindFirstChild("Attack").Value.PrimaryPart.Position
				pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(CFrame.new(position, lookAt) * CFrame.new(0, 1 +sin, 0) * CFrame.fromEulerAnglesXYZ(0,0,cos),0.1))
			else
				local position = (pet:FindFirstChild("Attack").Value.PrimaryPart.CFrame * CFrame.new(x, 0, z)).p
				local lookAt = pet:FindFirstChild("Attack").Value.PrimaryPart.Position
				pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(CFrame.new(position, lookAt) * CFrame.new(0, 3+math.sin(time()*7)/2, 0) * CFrame.fromEulerAnglesXYZ(cos,0,0) ,0.1))
			end 
		else
			if character.Humanoid.MoveDirection.Magnitude > 0 then
				if pet:FindFirstChild("Walks") then
					pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame * CFrame.new(x, offsetY+sin, z) * CFrame.fromEulerAnglesXYZ(0,0,cos),0.1))
				else
					pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame * CFrame.new(x, offsetY/2+math.sin(time()*3)+1, z),0.1))
				end 
			else
				if pet:FindFirstChild("Walks") then 
					pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame * CFrame.new(x, offsetY, z) ,0.1))
				else
					pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame * CFrame.new(x, offsetY/2+math.sin(time()*3)+1, z) ,0.1))
				end
			end
		end

	end
end

runService.RenderStepped:Connect(function(dt)
	for _, PlrFolder in pairs(playerPets:GetChildren()) do
		local Player = game.Players:FindFirstChild(PlrFolder.Name) or nil
		if Player ~= nil then
			local character = Player.Character or nil
			if character ~= nil then
				positionPets(character, PlrFolder, dt)
			end
		end
	end
end)

 

MainServer 코드

local Players = game:GetService("Players")

local mainFolder_Workspace = workspace.MainFolder_Workspace
local playerPets = mainFolder_Workspace.PlayerPets
local drops = mainFolder_Workspace.Drops

Players.PlayerAdded:Connect(function(player) //플레이어가 추가되면 함수 실행
	local folder = Instance.new("Folder") //폴더 생성
	folder.Name = player.Name //닉네임으로
	folder.Parent = playerPets //playerPets의 자식객체로 폴더 나옴
	
	for _, v in pairs(script.PlayerData:GetChildren()) do //playerData의 자식들 하나하나
		v:Clone().Parent = player	 //playerData의 자식의 부모를 player로 바꿈
	end
end)

Players.PlayerRemoving:Connect(function(player)	if playerPets:FindFirstChild(player.Name) then
		playerPets:FindFirstChild(player.Name):Destroy() //player 떠나면 playerPets 폴더 삭제
	end
end)

for _, drop in pairs(drops:GetDescendants()) do //drops의 자식들의 객체까지 접근가능
	if drop:IsA("Model") then //타입이 모델
		drop.Health.Value = drop.MaxHealth.Value //만땅
		drop.ClickDetector.MouseClick:Connect(function(player) //만약 클릭하면
			local currentPlayerPets = playerPets[player.Name] //현재 playerPet 이름으로 찾기
			if #currentPlayerPets:GetChildren() > 0 then //지금 펫의 자식이 0보다 크면
				local pet = currentPlayerPets:FindFirstChildOfClass("Model")
				if player.Values.SentTo.Value == nil then
					player.Values.SentTo.Value = drop 
					pet.Attack.Value = player.Values.SentTo.Value
				elseif player.Values.SentTo.Value == drop then
					player.Values.SentTo.Value = nil
					pet.Attack.Value = player.Values.SentTo.Value
				elseif player.Values.SentTo.Value ~= nil and player.Values.SentTo.Value ~= drop then
					player.Values.SentTo.Value = drop
					pet.Attack.Value = player.Values.SentTo.Value
				end
			end
		end)
	end
end
728x90