I’m working on an obby and when the player respawns, I want their camera to face forward to the next stage. When the player respawns, their character faces the right way, but my issue is that their camera faces the other direction.
I’ve tried to fix this using a RemoteEvent that fires to the client to manipulate the camera, but the code below causes the camera to position downwards.
local SetCamera = game.ReplicatedStorage:WaitForChild("SetCamera")
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
SetCamera.OnClientEvent:Connect(function()
camera.CFrame = CFrame.new(camera.CFrame.Position, player.Character.HumanoidRootPart.CFrame.lookVector)
end)
local Player = game:GetService("Players").LocalPlayer
local Camera = workspace.CurrentCamera
Camera.CFrame = Player.Character.HumanoidRootPart.CFrame
* CFrame.Angles(math.rad(-15),0,0)
You can use the Player.CharacterAppearanceLoaded event on the client instead of using a remote as well.
Thanks, it worked. Do you mind giving a brief explanation of your solution? I’m very new to CFrames and Roblox Studio in general so any information helps.
Well, its a little weird because of how the camera core scripts seem to work. The rotation of the camera is changeable, while the distance from the character to the camera is maintained.
The CFrame we set uses the rotation portion of the humanoid root part (the core scripts discard the positional part), which sets the camera’s rotation to be that of the root part. Then, using CFrame.Angles(), we are decreasing the X axis of rotation by 15 degrees, which pitches the cameras rotation downward a little bit (to see over your character). Then, the core scripts kick in, and set the distance offset based on our current rotation, that offset being the current offset of your camera relative to the character.
Hi, I’m wondering where this might go? does it depend whether or not I have checkpoint saving setup already? Could I adapt the camera orientation into this?
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local ObbyDataStore = DataStoreService:GetDataStore("ObbyDataStore")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SkipStage = ReplicatedStorage:WaitForChild("SkipStage")
local ResetStage = ReplicatedStorage:WaitForChild("ResetStage")
local Checkpoints = workspace:WaitForChild("Checkpoints")
local inGameStartupPlayers = {}
local CurrentStage = {}
local TouchDb = {}
local ProductId = 0000000000 -- Change to your developer product id
local function NewCharacter(player, char)
local TempCurrentStage = CurrentStage[player.UserId]
if TempCurrentStage ~= nil then
local TempCheckpoint = Checkpoints:FindFirstChild(TempCurrentStage)
if TempCheckpoint ~= nil then
repeat wait(0.1) until char.PrimaryPart ~= nil
char:SetPrimaryPartCFrame(CFrame.new(TempCheckpoint.Position + Vector3.new(0, 6, 0)) * CFrame.Angles(0, math.rad(TempCheckpoint.Orientation.Y) + math.rad(90), 0))
end
end
end
local function NewPlayer(player)
local success, stage = pcall(function()
return (ObbyDataStore:GetAsync(player.UserId)) or 1
end)
CurrentStage[player.UserId] = stage
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local Stage = Instance.new("IntValue", leaderstats)
Stage.Name = "Stage"
Stage.Value = stage
local TempChar = player.Character
if TempChar ~= nil then
NewCharacter(player, TempChar)
end
player.CharacterAdded:Connect(function(char)
NewCharacter(player, char)
end)
end
Players.PlayerAdded:Connect(function(player)
if inGameStartupPlayers[player] == nil then
NewPlayer(player)
end
end)
Players.PlayerRemoving:Connect(function(player)
local success = pcall(function()
ObbyDataStore:SetAsync(player.UserId, CurrentStage[player.UserId])
end)
CurrentStage[player.UserId] = nil
end)
SkipStage.OnServerInvoke = function(player)
local connection
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats ~= nil then
local Stage = leaderstats:FindFirstChild("Stage")
if Stage ~= nil then
if #Checkpoints:GetChildren() ~= Stage.Value then
local PurchaseResult = "Purchase Failed"
connection = MarketplaceService.PromptProductPurchaseFinished:Connect(function(userId, productId, purchased)
if player.UserId == userId and productId == ProductId then
if purchased == true then
PurchaseResult = "Success"
end
end
connection:Disconnect()
end)
MarketplaceService:PromptProductPurchase(player, ProductId)
repeat wait(0.1) until connection.Connected == false or Players:GetPlayerByUserId(player.UserId) == nil
return PurchaseResult
else
return "You have reached the highest stage!"
end
end
end
end
ResetStage.OnServerEvent:Connect(function(player)
CurrentStage[player.UserId] = 0
local TempLeaderstats = player:FindFirstChild("leaderstats")
if TempLeaderstats ~= nil then
local TempStage = TempLeaderstats:FindFirstChild("Stage")
if TempStage ~= nil then
TempStage.Value = 0
end
end
NewCharacter(player, player.Character)
end)
MarketplaceService.ProcessReceipt = function(recieptInfo)
if recieptInfo.ProductId == ProductId then
local player = Players:GetPlayerByUserId(recieptInfo.PlayerId)
if player ~= nil then
CurrentStage[player.UserId] = CurrentStage[player.UserId] + 1
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats ~= nil then
local Stage = leaderstats:FindFirstChild("Stage")
if Stage ~= nil then
Stage.Value = CurrentStage[player.UserId]
end
end
local TempChar = player.Character
if TempChar ~= nil then
NewCharacter(player, TempChar)
end
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
return Enum.ProductPurchaseDecision.NotProcessedYet
end
for i,v in pairs(Checkpoints:GetChildren()) do
local StageNum = tonumber(v.Name)
v.Touched:Connect(function(hit)
local char = hit.Parent
if char ~= nil then
local Humanoid = char:FindFirstChildOfClass("Humanoid")
if Humanoid ~= nil and Humanoid.Health > 0 then
local player = Players:GetPlayerFromCharacter(char)
if player ~= nil and (TouchDb[player.UserId] or 0) + 1 <= os.time() then
TouchDb[player.UserId] = os.time()
local TempCurrentStage = CurrentStage[player.UserId]
if TempCurrentStage == StageNum - 1 then
CurrentStage[player.UserId] = StageNum
local TempLeaderstats = player:FindFirstChild("leaderstats")
if TempLeaderstats ~= nil then
local TempStage = TempLeaderstats:FindFirstChild("Stage")
if TempStage ~= nil then
TempStage.Value = StageNum
end
end
end
end
end
end
end)
end
inGameStartupPlayers = Players:GetPlayers()
for i,v in pairs(inGameStartupPlayers) do
spawn(function()
NewPlayer(v)
end)
end
game:BindToClose(function()
for i,v in pairs(Players:GetPlayers()) do
ObbyDataStore:SetAsync(v.UserId, CurrentStage[v.UserId])
end
wait(1)
end)
inGameStartupPlayers = {}