Hey, I'm making a 2D shared camera script (think street fighter), and I've already found a way to keep the camera in the middle of two players, by finding the midpoint of both players. The problem is that the camera wont stay at a side view. I figured that if I rotate the part in the center of both players, the camera would also rotate, however I'm not too sure. Could someone point me in the right direction?
repeat wait() until _G.arbDistance and _G.torsoDir _G.side = "left" local plr = game:GetService("Players").LocalPlayer local RunService = game:GetService('RunService') _G.camera = game.Workspace.CurrentCamera _G.camera.CameraType = "Scriptable" _G.mpPart = Instance.new("Part", workspace) _G.mpPart.Name = plr.Name .. "'s Camera" _G.mpPart.Size = Vector3.new(0.2, 0.2, 0.2) _G.mpPart.Shape = "Ball" _G.mpPart.Transparency = 1 _G.mpPart.CanCollide = false _G.mpPart.Anchored = true -- Physics shouldn't be acting on this part local zoom = 30 local height = 2 local angle = 0 local lv = _G.mpPart.CFrame.lookVector local rv = _G.mpPart.CFrame.rightVector function update() if plr.Character and plr.Character:FindFirstChild('Torso') then _G.mp = CFrame.new(_G.c1:Lerp(_G.c2, .5)) _G.mpPart.CFrame = CFrame.new(0, 2, 0) * _G.mp _G.camera.CameraSubject = _G.mpPart _G.camera.CoordinateFrame = CFrame.new(_G.mpPart.Position) * CFrame.new(0, height, zoom) * CFrame.Angles(0, 0, 0) end end RunService:BindToRenderStep('Camera', Enum.RenderPriority.Camera.Value, update)
Hi crome60!
Much as I hate to say it, your approach to scripting this camera behavior is devoid of encapsulation and just plain cryptic. However, I'm not going to state something like that without providing a solution. Observe:
-- A server script: -- Assuming that Player1 and Player2 are variables containing references to each player, let's say the following: local GetMidpoint = Instance.new("RemoteFunction", game.ReplicatedStorage); -- Let's make a default position for the camera, in case the character does not exist. Put a part in workspace and place it where you want the camera to be by default. Obviously, name it DefaultCameraPosition. local DefaultPos = game.Workspace:WaitForChild("DefaultCameraPosition").CFrame; GetMidpoint.Name = "GetMidpoint"; -- Return a point between the two players, if they both exist. Return a default position, if not. function GetMidpoint.OnServerInvoke() local conditions = ( Player1.Character and Player2.Character and Player1.Character:FindFirstChild("Torso") and Player2.Character:FindFirstChild("Torso") ); if (conditions) then local torso1Pos = Player1.Character.Torso.CFrame; local torso2Pos = Player2.Character.Torso.CFrame; return torso1Pos:lerp(torso2Pos, .5); end; return DefaultPos; end;
Okay, we now have a RemoteFunction that will return the midpoint between two characters when invoked. Let's make a client script to position the player's camera accordingly.
-- The local script: local Player = game.Players.LocalPlayer; local Camera = game.Workspace.CurrentCamera; local GetMidpoint = game.ReplicatedStorage:WaitForChild("GetMidpoint"); -- Offset of the camera applied AFTER the zoom offset is applied. Change as needed. local Offset = Vector3.new(-10, 2, 0); Camera.CameraType = Enum.CameraType.Scriptable; local function Update() local midPoint = GetMidpoint:InvokeServer(); local conditions = ( Player.Character and Player.Character:FindFirstChild("Torso") ); if (midPoint and conditions) then -- Set the camera position to the midPoint + Offset, and face it toward the character. Camera.CFrame = CFrame.new(midPoint + Offset, Player.Character.Torso.CFrame); end; end; RunService:BindToRenderStep('Camera', Enum.RenderPriority.Camera.Value, Update)
Okay, so we've got the basics down. We have a local script that moves the camera to the midpoint of the players plus an offset that we desire, then faces the character. I'm going to assume that you want to zoom out based on the distance between the players, so let's do that. Back to the server script:
-- Return a point between the two players, if they both exist. Return a default position, if not. function GetMidpoint.OnServerInvoke() local conditions = ( Player1.Character and Player2.Character and Player1.Character:FindFirstChild("Torso") and Player2.Character:FindFirstChild("Torso") ); if (conditions) then local torso1Pos = Player1.Character.Torso.CFrame; local torso2Pos = Player2.Character.Torso.CFrame; -- A scalar representing the distance between the two players in studs. local distance = (torso1Pos.p - torso2Pos.p).magnitude; -- The midpoint and the offset that will be applied to achieve the correct 'zoom.' X *might* not be the desired axis. Change if needed. local result = torso1Pos:lerp(torso2Pos, .5); local offset = Vector3.new(distance, 0, 0); -- return result + offset, or the midpoint translated by the offset. return result + offset; end; return DefaultPos; end;
I cannot guarantee that it will work 100% as advertised. You may need to tweak it a bit to get the desired result. I may have made a mistake or two with the vector arithmetic along the way (something I often do quite too easily,) but you will surely be able to iron any problems of that type. As for any other problems that may have been overlooked in my scripts -- which are very likely given I wrote this answer overnight, -- let me know. I'll try to help you get a reliable camera rig as quickly as possible.
Have a nice day, crome60, and best of luck with your game!
Yours truly, tkcmdr
Edit: Removed unnecessary semicolon