Making a tank game, problem with moving the tanks with player inputs

As the title says, I’m trying to make a tank game. I’ve got the movement made with player inputs already, it’s just that, when I test it with 2 players, when the first player joins, movement is fine, when the second player joins, they can control their tank perfectly fine, but when the first player tries to control their tank, they instead control the second player’s tank. I’ve been trying to fix this for a while now, but I just can’t think of a way to do it, so I’m resorting to the dev forum yet again. Help :sweat_smile:
Here’s my code:
Server side:

local runService = game:GetService("RunService")
local fastCast = require(game.ReplicatedStorage.Modules.FastCastRedux)

local turningLeft
local turningRight
local movingForward
local movingBackward
local headTurningLeft
local headTurningRight

local turningSpeed = 0.02
local speed = 0.05
local turretTurningSpeed = 0.02

-- Movement
local events = game.ReplicatedStorage.Events.Movement
events.turnRight.OnServerEvent:Connect(function()
	turningRight = true
end)

events.turnLeft.OnServerEvent:Connect(function()
	turningLeft = true
end)

events.moveForward.OnServerEvent:Connect(function()
	movingForward = true
end)

events.moveBackward.OnServerEvent:Connect(function()
	movingBackward = true
end)

events.headTurnRight.OnServerEvent:Connect(function()
	headTurningRight = true
end)

events.headTurnLeft.OnServerEvent:Connect(function()
	headTurningLeft = true
end)

events.stopTurningRight.OnServerEvent:Connect(function()
	turningRight = false
end)

events.stopTurningLeft.OnServerEvent:Connect(function()
	turningLeft = false
end)

events.stopMovingForward.OnServerEvent:Connect(function()
	movingForward = false
end)

events.stopMovingBackward.OnServerEvent:Connect(function()
	movingBackward = false
end)

events.stopHeadTurningRight.OnServerEvent:Connect(function()
	headTurningRight = false
end)

events.stopHeadTurningLeft.OnServerEvent:Connect(function()
	headTurningLeft = false
end)

runService.Heartbeat:Connect(function(dt)
	if turningRight == true then
		playerTank.CFrame = playerTank.CFrame * CFrame.fromEulerAnglesXYZ(0,-turningSpeed,0 * dt)
	end
		
	if turningLeft == true then
		playerTank.CFrame = playerTank.CFrame * CFrame.fromEulerAnglesXYZ(0,turningSpeed,0 * dt)
	end
		
	if movingForward == true then
		playerTank.CFrame = playerTank.CFrame * CFrame.new(0,0,-1 * speed)
	end
	
	if movingBackward == true then
		playerTank.CFrame = playerTank.CFrame * CFrame.new(0,0,1 * speed)
	end
	
	if headTurningRight == true then
		local weld = playerTank.turretWeld
		weld.C0 *= CFrame.Angles(0,-turretTurningSpeed, 0)
	end
	
	if headTurningLeft == true then
		local weld = playerTank.turretWeld
		weld.C0 *= CFrame.Angles(0,turretTurningSpeed, 0)
	end
end)

Client side:

local userInputService = game:GetService("UserInputService")
local tankController = require(game.ReplicatedStorage.Modules.tankController)
userInputService.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Keyboard then
	if input.KeyCode == Enum.KeyCode.A then
		game.ReplicatedStorage.Events.Movement.turnLeft:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.D then
		game.ReplicatedStorage.Events.Movement.turnRight:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.W then
		game.ReplicatedStorage.Events.Movement.moveForward:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.S then
		game.ReplicatedStorage.Events.Movement.moveBackward:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.G then
		game.ReplicatedStorage.Events.Movement.headTurnRight:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.F then
		game.ReplicatedStorage.Events.Movement.headTurnLeft:FireServer()
	end
	
end
end)

userInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Keyboard then
	if input.KeyCode == Enum.KeyCode.A then
		game.ReplicatedStorage.Events.Movement.stopTurningLeft:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.D then
		game.ReplicatedStorage.Events.Movement.stopTurningRight:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.W then
		game.ReplicatedStorage.Events.Movement.stopMovingForward:FireServer()
	end
	
	if input.KeyCode == Enum.KeyCode.S then
		game.ReplicatedStorage.Events.Movement.stopMovingBackward:FireServer()
	end	
	
	if input.KeyCode == Enum.KeyCode.G then
		game.ReplicatedStorage.Events.Movement.stopHeadTurningRight:FireServer()
	end	
	
	if input.KeyCode == Enum.KeyCode.F then
		game.ReplicatedStorage.Events.Movement.stopHeadTurningLeft:FireServer()
	end
end
end)

I get “playerTank” (Server script) by firing an event on the client, passing the player’s name, and the server script picks it up:

game.ReplicatedStorage.Events.tankDeployed.OnServerEvent:Connect(function(player)
    playerTank = game.ReplicatedStorage.Tanks.testTank:Clone()
    playerTank.Name = tostring(player.Name.."Tank")
    playerTank.Parent = game.Workspace
    game.ReplicatedStorage.Events.tankDeployed:FireClient(player,playerTank)
end)

Instead of firing an event everytime you press a key, press the key, set the values into the local script, and then every Heartbeat, fire an event sending all the values. I know that my explanation was a :poop:, so take this code has an example:

LocalScript:

local ContextActionService = game:GetService("ContextActionService")
local RunService = game:GetService("RunService")

local Tank --Player's tank
local MovementEvent --Event to be fired

local Movements = {
	Forward  = false,
	Backward = false,
	Right    = false,
	Left     = false
};

local function MovementBind(ActionName, InputState, InputObject)
	if (InputState == Enum.UserInputState.Begin) then
		Movements[ActionName] = true
	elseif (InputState == Enum.UserInputState.End) then
		Movements[ActionName] = false
	end
end

RunService.Heartbeat:Connect(function()
	MovementEvent:FireServer(Tank, Movements)
end)

ContextActionService:BindAction("Forward", MovementBind, false, Enum.KeyCode.W)

Script:

local Speed = 0.05

local Event --The event to be fired

Event.OnServerEvent:Connect(function(Player, Tank, Movement)
	-- Player = The player who moved
	-- Tank = The model to be moved
	-- Movement = A table with all the moving values
	
	if Movement.Forward then --If Movement's "Forward" value is true
		Tank.CFrame = Tank.CFrame * CFrame.new(0,0,-1 * Speed)
	end
end)

These codes are much more clean and probably won’t give any problem.

2 Likes

This looks good, but I think I’m way too tired to get it to work right now :sweat_smile: Thanks for your response anyway

1 Like

After a break and some ideas popping up, I finally got it working (I spent like 3+ hours trying to solve this problem before making this post on the dev forum), so big thanks to you :sweat_smile:

2 Likes