i have a checkpoint script that spawns the player facing the part’s frame, it works fine but the camera is facing the other direction, the game is in first person so the character faces the camera too ;-; how would i fix it?
Use CFrame.lookAt()
on the camera’s CFrame.
workspace.CurrentCamera.CFrame = CFrame.lookAt(DesiredPosition, FramePosition)
hmm it dosn’t seem to work…heres some pictures
it faces the red arrow when I lockfirstperson
hmm i tried lock first person using script but it still faces where the red arrow faces
i have this checkpoint script, i tried dup the char line but didn’t work
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, 3, 0)) * CFrame.Angles(0, math.rad(TempCheckpoint.Orientation.Y) + TempCheckpoint.Orientation.Z, 0))
end
end
end
This function in the code below that I made will reset the camera direction to wherever the local player’s character is facing. It must be in a LocalScript
ran on the client. If a server script needs to be able to do it, you should use a RemoteEvent
to trigger the function on the client.
local function setCameraFacingPlayerDirection()
local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local camera = workspace.CurrentCamera
--Values used for the camera cframe calculations
local playerCf = character:WaitForChild("Head").CFrame
local lastDiff = playerCf.Position - camera.CFrame.Position
local lastDiffY = lastDiff.Y * Vector3.new(0, -1, 0)
if (lastDiff.Magnitude < 1) then
return --prevent setting it if they are already in first person
end
local lastType = camera.CameraType
local cameraPos = (playerCf + lastDiffY - (lastDiff.Magnitude * Vector3.new(1, 0, 1) * playerCf.LookVector)).Position
--Set camera cframe manually and then give control back to camera script
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.lookAt(cameraPos, playerCf.Position)
camera.CameraType = lastType
end
NOTE: The function above will not work correctly if they are already in first-person when they respawn! If your game has first person when the character spawns, you will need to first disable it for a moment as they are respawning via scripting because it will override the character’s direction and the code has no way of knowing where the player is supposed to be facing. An alternative solution to this is to instead directly make the camera face your part’s frame on spawn instead of the character (cutting out the middle man).
I hope this is somewhat helpful. I couldn’t test out the alternative solution I mentioned above right now since it’s late. If you are still having troubles and no one else gives a solution, I might be able to help more when I am back on and have more time.
starter pack or starterplayer?, i tried putting this every where but it don’t work for some reason
i tried put a wait in front of the check point new char but it still faces the red arrow in first person
I created a new script that I tested (works for me) and correctly makes the player face a target part upon respawning when in locked first person.
Put this in a LocalScript
that is inside StarterPlayer.StarterCharacterScripts
:
--CHANGE THE VARIABLE BELOW TO WHATEVER PART THE PLAYER WILL FACE
local partToFaceOnSpawn = workspace:WaitForChild("TargetPart")
local player = game:GetService("Players").LocalPlayer
local character = script.Parent
local camera = workspace.CurrentCamera
local function createModalButton()
local button = Instance.new("TextButton")
button.Text = ""
button.BackgroundTransparency = 1
button.Active = false
button.Visible = true
button.Modal = true
local gui = Instance.new("ScreenGui")
gui.Name = "CameraResetModal"
button.Parent = gui
gui.Parent = player:WaitForChild("PlayerGui")
return gui
end
if player.CameraMode == Enum.CameraMode.LockFirstPerson then
camera.Changed:Wait()
local lastType = camera.CameraType
local modal = createModalButton()
camera.CameraType = Enum.CameraType.Scriptable
local cameraPos = camera:GetRenderCFrame().Position
local partPos = partToFaceOnSpawn.CFrame.Position
local targetPos = partPos * Vector3.new(1, 0, 1) + Vector3.new(0, cameraPos.Y, 0)
local newCf = CFrame.lookAt(cameraPos, targetPos)
camera.CFrame = newCf
camera.CameraType = lastType
modal:Destroy()
end
i’m sorry i didn’t tell you this before but uh… there is some checkpoints facing another direction so facing one won’t really work ;-;
You should be able to change the partToFaceOnSpawn
variable in my code to reference whatever target part their current checkpoint is (dynamically), it doesn’t have to be the same part every time (that’s just what I put as an example).
I don’t know what the other code is in your game or how it works so I can’t supply a full working script. It depends on how your checkpoint system works for what that variable will be set to.
Here is a pseudocode example for how something dynamic like that could work:
--some code/function that gets the player's current checkpoint (would return a number value)
local currentLevel = getPlayerCheckpointLevel()
--find the part for this checkpoint the player is on
local partToFaceOnSpawn = workspace.Checkpoints:FindFirstChild(tostring(currentLevel))
hmm can i like just rotate the player again? like wait till the player spawns and rotate the cframe again
What do you mean by that? Can you give an example?
Are the checkpoints in your game just SpawnLocations, or are they a custom part (the part you are standing on in the screenshot)?
You could rotate the player instead to face the forward direction of the part they spawned on. I can supply code for this later today if you want.
the checkpoint is just a normal part, and the script is a server script, i tried rotate it after 0.1 second but it don’t work
Can you post a screenshot of how the checkpoints are set up in Workspace
, as well as the server script code for the checkpoint system?
the script:
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 = 1193721691 -- 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
wait(0.1)
char:SetPrimaryPartCFrame(CFrame.new(TempCheckpoint.Position + Vector3.new(0, 3, 0)) * CFrame.Angles(0, math.rad(TempCheckpoint.Orientation.Y) + TempCheckpoint.Orientation.Z, 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])
wait (1)
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] = 1
local TempLeaderstats = player:FindFirstChild("leaderstats")
if TempLeaderstats ~= nil then
local TempStage = TempLeaderstats:FindFirstChild("Stage")
if TempStage ~= nil then
TempStage.Value = 1
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])
wait(6)
end
wait(1)
end)
inGameStartupPlayers = {}
the checkpoints are just in a folder called checkpoints
Alright, try this, I believe it should work:
- First, create a
RemoteEvent
called SetCameraDirection and put it directly inReplicatedStorage
- Replace your
NewCharacter
function inside the server script with this code:
local SetCameraDirection: RemoteEvent = ReplicatedStorage.SetCameraDirection
local function NewCharacter(player: Player, char: Model)
local TempCurrentStage = CurrentStage[player.UserId]
local TempCheckpoint: BasePart = TempCurrentStage and Checkpoints:FindFirstChild(tostring(TempCurrentStage))
if TempCheckpoint then
task.wait()
char:MoveTo(TempCheckpoint.Position)
SetCameraDirection:FireClient(player, TempCheckpoint.Orientation)
end
end
- Create a new
LocalScript
insideStarterPlayer.StarterPlayerScripts
with the following code:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera
local function CreateModalButton()
local button = Instance.new("TextButton")
button.Text = ""
button.BackgroundTransparency = 1
button.Active = false
button.Visible = true
button.Modal = true
local gui = Instance.new("ScreenGui")
gui.Name = "CameraResetModal"
button.Parent = gui
gui.Parent = LocalPlayer:WaitForChild("PlayerGui")
return gui
end
local SetCameraDirection: RemoteEvent = ReplicatedStorage:WaitForChild("SetCameraDirection")
SetCameraDirection.OnClientEvent:Connect(function(dir: Vector3)
assert(LocalPlayer.CameraMode == Enum.CameraMode.LockFirstPerson, "Set Player.LockFirstPerson to true! (currently false)")
Camera.Changed:Wait()
local lastType = Camera.CameraType
local modal = CreateModalButton()
Camera.CameraType = Enum.CameraType.Scriptable
local cameraPos = Camera:GetRenderCFrame().Position
local newCf = CFrame.new(cameraPos) * CFrame.Angles(math.rad(dir.X), math.rad(dir.Y), math.rad(dir.Z))
Camera.CFrame = newCf
Camera.CameraType = lastType
modal:Destroy()
end)
- Make sure
LockFirstPerson
is set totrue
for the game.