Make two players face each other

I’m creating a 2D fighting game, and I’d like to achieve something similar to this (both players looking at each other in any situation) :
https://gyazo.com/fb27d74bd77d16082128c88aced80456
This is my progress so far (I’m only missing them turning to face each other):
https://gyazo.com/6e65b7d4931801de420c334ddfe55e00
I tried using CFrame.new() and the lookAt argument but it ends up being choppy since I still have to set the cframe of the rootpart to itself. I’m getting weird results using BodyGyro, and I doubt it’d give instant results like in the gif.

1 Like

I suggest using the following for the server:

local RunService = game:GetService("RunService")
local Plr1 = -- player 1
local Plr2 = -- player 2


RunService.RenderStepped:Connect(function(step)
	-- set the CFrame here
end)

RenderStepped can only be used in local scripts, though…

I used Heartbeat, which is similar to RenderStepped and made this script :

local RunService = game:GetService("RunService")
RunService.Heartbeat:connect(function()
	plr2.HumanoidRootPart.CFrame = CFrame.new(plr2.HumanoidRootPart.Position,Vector3.new(plr2.HumanoidRootPart.Position.X,plr2.HmanoidRootPart.Position.Y,plr1.HumanoidRootPart.Position.Z))
end)

But I end up with this : https://gyazo.com/fd2fa4bf1292e849df7d4c33ed203161

I only changed the Z Axis since they only move on the Z Axis

My bad, do it client-sided for them (use hearbeat instead server-sided) then or an even better idea I just had:
run the following server-sided, this would only work with 2 players:

local players = game:GetService("Players")
local plr1 
local plr2

players.PlayerAdded:Connect(function(plr)
	local function respawnFunc (character, plr)
		local humRP = character:WaitForChild("HumanoidRootPart")
		
		local BG = instance.new("BodyGyro", humRP)
		-- please read more about BodyGyro's properties I put a link under the script.
		BG.MaxTorque = Vector3.New(40000,40000,40000)
		
		while character.Humanoid.Health =< 0 do
			if plr1 ~= plr then
				if plr1.Character and plr1.Character:FindFirstChild("HumanoidRootPart") then
					local otherHumRP = plr1.Character:FindFirstChild("HumanoidRootPart")
					BG.CFrame = CFrame.new(humRP.Position,Vector3.new(humRP.Position.X,humRP.Position.Y,otherHumRP.Position.Z))
				end
			elseif plr2 ~= plr then
				if plr2.Character and plr2.Character:FindFirstChild("HumanoidRootPart") then
					local otherHumRP = plr2.Character:FindFirstChild("HumanoidRootPart")
					BG.CFrame = CFrame.new(humRP.Position,Vector3.new(humRP.Position.X,humRP.Position.Y,otherHumRP.Position.Z))
				end
			end
		end
		BG:Destroy()
	end

	if not plr1 then
		plr1 = plr
		plr.CharacterAdded:Connect(function(char) respawnFunc(char,plr) end)
	elseif not plr2 then
		plr2 = plr
		plr.CharacterAdded:Connect(function(char) respawnFunc(char,plr) end)
	end
end)

Note, read something about the BodyGyro and read over it’s properties.
wait sorry forgot something, don’t take this over. Editting it rn.

Plr1.HumanoidRootPart:GetPropertyChangedSignal("CFrame"):Connect(function()
-- Set CFrame
end)

The event only fires if the CFrame property is changed by a script, not the player walking.

Indeed, rokoblox’s script doesn’t work for this reason. I’m open for more ideas though

This should work, try the script I replied to.
I suggest messing around with the properties of BG the BodyGyro

“Attempt to connect failed: Passed value is not a function” line 27 because of the
plr.CharacterAdded:Connect()

I don’t exactly know how to fix this since I don’t really see what you had in mind here, mind handing me a hand on this ?

Just make your own movement script then, using Humanoid:Move()

Oops, I was too quick, hehe let me fix it.
Edit: Fixed it, you can copy the script now again.
Edit2: Edited the script again, it should have no failure now.

The script seems to unfortunately do virtually nothing. Also I had to fix the BG.MaxForce, which I supposed you meant to say MaxTorque ? Anyways, I believe the problem comes from the fact the BodyGyro isn’t parented to any part, but rather to the character. I’ll try to parent it to the root part and see how it goes.
Edit : Okay I’m confused, the BG should be parented to the root part, but ends up being a children of the character whenever I launch the server

you’re wrong at that;
image
I parented the BodyGyro to the HumanoidRootPart the second I made it.
Tho I suggest using .Parent instead of parenting it directly to the parent you want it to have, as it is bad for your performance; I suggest reading more about it here.
Edit: I found a small error in the script; I used End) instead of End which would have the script break.

Nevermind, it came from this :
while character.Humanoid.Health =< 0 do
which I fixed to this :
while character.Humanoid.Health >= 0 do

But now I’m getting another error : “attempt to index nil with ‘Character’” at this line for some reason ?
if plr2.Character and plr2.Character:FindFirstChild("HumanoidRootPart") then

Edit : It seems that the function is being fired (by plr1) before the plr2’s character has loaded

I found a few other issues, 1 second fixing them in studio so I can fix it easier and quicker; when I am done I will edit the script in here.
Edit:

local players = game:GetService("Players")
local plr1 
local plr2

players.PlayerAdded:Connect(function(plr)
	local function respawnFunc (char, plr)
		print("Respawn function active for: "..plr.Name)
		local humRP = char:WaitForChild("HumanoidRootPart")
		
		local BG = Instance.new("BodyGyro")
		-- please read more about BodyGyro's properties I put a link under the script.
		BG.MaxTorque = Vector3.new(0,400000000,0)
		-- BG.P = mess around with these 2 settings
		-- BG.D = 
		BG.Parent = humRP
		
		while char and char:FindFirstChild("Humanoid") and char.Humanoid.Health > 0 do
			if plr1 and plr1 ~= plr then
				if plr1.Character and plr1.Character:FindFirstChild("HumanoidRootPart") then
					local otherHumRP = plr1.Character:FindFirstChild("HumanoidRootPart")
					BG.CFrame = CFrame.new(humRP.Position,Vector3.new(humRP.Position.X,humRP.Position.Y,otherHumRP.Position.Z))
				end
			elseif plr2 and plr2 ~= plr then
				if plr2.Character and plr2.Character:FindFirstChild("HumanoidRootPart") then
					local otherHumRP = plr2.Character:FindFirstChild("HumanoidRootPart")
					BG.CFrame = CFrame.new(humRP.Position,Vector3.new(humRP.Position.X,humRP.Position.Y,otherHumRP.Position.Z))
				end
			end
			wait()
		end
		BG:Destroy()
	end

	if not plr1 then
		plr1 = plr
		plr.CharacterAdded:Connect(function(char) respawnFunc(char,plr) end)
		print(plr.Name.." set as plr1")
	elseif not plr2 then
		plr2 = plr
		plr.CharacterAdded:Connect(function(char) respawnFunc(char,plr) end)
		print(plr.Name.." set as plr2")
	end
end)

That should do it, I hope.
Edit 2:

  1. Sadly when I tried it, it did not work. I currently have no solution for fixing this; this is as far as I know how I could help you; maybe making the MaxTorque higher or editting with the BG.P or BG.D would work; tho I am not sure.
  2. If this all won’t work then instead of setting the BG.CFrame set the humRP.CFrame
1 Like

I believe you’re mixing “<=” and “>=” (which i fixed)

None the less, the same issue I explained before is still there. plr2’s character does not exist when respawnFunc is fired. I believe this comes from the fact that plr1 loads in first and fires the function directly before plr2’s character is loaded.

No, it’s supposed to be; when the humanoid is 0 or lower it should stop;
so “<=” is it supposed to be.
A.K.A when the player dies your HumanoidRootPart stops moving; tho it doesn’t really matter that much.
Edit: I am going to edit 2 things in the script real quick such as a spawn function so the script doesn’t have to wait and at the while check if the HumanoidRootPart ~= nil.
Edit 2: I found another issue;

BG.MaxTorque = Vector3.new(0,400000000,0)

I wrote .new with a capital N.

Unfortunately I have to go off right now. There is definitely still some things to tweak in the script but I won’t be able to test it further for the time being. I’ll be back tomorrow to work on it again, thanks for your help none the less.

I am quite confused,
the BodyGyro did not appear inside the HumanoidRootPart.
image