Trying to make Target Lock-on work on players

I am trying to make a target lock-on in which it will lock on a player’s movement once a certain key bind is pressed. I also want to make so that there could be a certain distance for the lock to be on and that the lock-on doesn’t go through collisions

The issue is, I can’t use it on players, if I try to make Target.Position it would not be a valid member of CurrentCamera

I’ve tried using i v pairs and adding “.Position”.

local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")

local Players = game:GetService("Players")
local Player = Players.LocalPlayer

local Character = Player.Character or Player.CharacterAdded:Wait()
local Mouse = Player:GetMouse()

local Camera = game.Workspace.CurrentCamera
local Focus = false

UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt and not Focus and not Processed then
		Camera.CameraType = Enum.CameraType.Scriptable
		Focus = true
		wait()
		spawn(function(Position)
			for _,Target in pairs(game.Workspace:GetChildren()) do
				if Target:FindFirstChild("Humanoid") and Target:FindFirstChild("HumanoidRootPart") and Target ~= script.Parent or Player.Name then
					local HumanoidRootPartPosition = Character.HumanoidRootPart.Position
					local OffSet = Vector3.new(10,4,0)
					local ViewTarget = Target + ((HumanoidRootPartPosition + OffSet) - Target).Unit * ((HumanoidRootPartPosition - Target).Magnitude + 12)
					Camera.CFrame = CFrame.new(ViewTarget, Target)
				end
			end
		end)
	end
end)
1 Like

What are you trying to do? You want when the player holds down a key it locks the players camera to the nearest other player? I’m confused.

1 Like

Something like that, for a better example here is a video:

(Sorry for the late response)

So you want it to lock on the closest target to players camera? You could use the camera’s LookVector and find the closest player in that direction.

Anyway to make the code I would firstly use ContextActionService and bind the action to a key, then use BindToRenderStepped to find and update the players camera cframe.

I used UserInputService instead is there any difference if I used ContextActionService? I also used RunService (Forgot to put RenderStepped) but the main problem I have is trying to identity a player’s HumanoidRootPart so I could lock the player’s camera to that certain player’s HumanoidRootPart (if that makes sense) as I got an error with my script.

ContextActionService allows you to bind functions to “actions” like key presses. In this scenario I would use it.

take out the “wait()” and take out the spawn()

Use Renderstepped and do

for _,player in ipairs (game.Players:GetPlayers()) do
   local HumanoidRootPart = player.Character.HumanoidRootPart -- assuming the player has a character

   -- the "camera cframe setting" needs to go in a RenderStepped
   -- so that it updates every frame
end

local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")

local Players = game:GetService("Players")
local Player = Players.LocalPlayer

local Character = Player.Character or Player.CharacterAdded:Wait()
local Mouse = Player:GetMouse()

local Camera = game.Workspace.CurrentCamera
local Focus = false

UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt and not Focus and not Processed then
		Camera.CameraType = Enum.CameraType.Scriptable
		Focus = true
			while Focus do
			for _,Player in ipairs(game.Players:GetPlayers()) do
						if Player:FindFirstChild("Humanoid") and Player:FindFirstChild("HumanoidRootPart") and Player ~= script.Parent or Player.Name then
						local HumanoidRootPart = Player.Character.HumanoidRootPart
						local HumanoidRootPartPosition = Character.HumanoidRootPart.Position
						local OffSet = Vector3.new(10,4,0)
						local ViewTarget = Player + ((HumanoidRootPartPosition + OffSet) - Player).Unit * ((HumanoidRootPartPosition - Player).Magnitude + 12)
						Camera.CFrame = CFrame.new(ViewTarget, Player)
						RS.RenderStepped:Wait()
				end
			end
		end
	elseif Input.KeyCode == Enum.KeyCode.LeftAlt and not Processed and Focus then
		Focus = false
		Camera.CameraType = Enum.CameraType.Custom
	end
end)

Something doesn’t work. Is there anything I’m doing wrong?

You are trying to do math on an instance (player) plus there is no player.Unit or player.Magnitude and the braces are in the wrong place.

Anyway you have to figure out who you want to lock on to, right now you looping through each player and setting the cframe for one frame.

What you need to do is pass or bind a function to render stepped, within the function you need to do 2 things.

  • Calculate which player you will lock onto (assuming you want it to be based on the location of the player otherwise calculate it outside of renderstepped)
  • Set the camera cframe to lock onto the selected player

I’m not at my PC rn and I have to go for the night, good luck

Update: I’ve made a RenderStepped function for the camera lock. I watched some tutorials on how to make a lock-on and used one as a guide on how to adjust the camera CFrame onto a player. I’m still new to scripting so I have a vague understanding of camera manipulation and CFrame.

UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt and not Focus and not Processed then
		Camera.CameraType = Enum.CameraType.Scriptable
		Focus = true
		while Focus do
				for _,Target in ipairs(game.Players:GetPlayers()) do
					if Target:FindFirstChild("Humanoid") and Target:FindFirstChild("HumanoidRootPart") and Target ~= script.Parent or Player.Name then
					local TargetRootPart = Target.Character.HumanoidRootPart
					local LocalPlayerHumanoidRootPart = Player.Character.HumanoidRootPart
					RS.RenderStepped:Connect(function() -- Added RenderStepped function
						local TargetDistance = (LocalPlayerHumanoidRootPart - TargetRootPart).Magnitude
						if 45 > TargetDistance then -- To detect if a player is close enough to lock on
							local CameraViewPosition = CFrame.new(LocalPlayerHumanoidRootPart.Position, Target.Position)*CFrame.new(1,1,1).p -- Found a tutorial and used script as guide
							Camera.CFrame = CFrame.new(CameraViewPosition, Target.Position)
						end
					end)
				end
			end
		end
	elseif Input.KeyCode == Enum.KeyCode.LeftAlt and not Processed and Focus then
		Focus = false
		Camera.CameraType = Enum.CameraType.Custom
	end
end)						

Since I used a tutorial’s script for the camera’s CFrame setting, I don’t get how it works. Also, when playing the RunService my game crashes even when I add a wait()

okay I’ll make an entire script for you, this make take some time.

Oh ok, Meanwhile I’m gonna try to study CFrame and Camera manipulation. (Sorry for the bother)

Just to be very clear what you want:

  • when the client presses (or holds?) left alt, the clients camera automatically locks-on to the nearest player even if the player is behind the client.
  • The clients camera stays locked onto the player until the player dies or left alt is pressed again? regardless if another player comes closer?

The client presses the key and automatically locks-on the nearest player. It stays locked on when a player until the client is out of range (Moves away) or dies. The lock-on has a range for players from the closest being the first to lock-on onto to but if it is in view of the client, if it is close to the client but either behind or out of view it won’t play. Also the lock-on should not clip through collisions like walls and floors. It will also have a BUI but I’ll take care of that. Also the lock-on should not work on a dead player’s HumanoidRootPart. The client should have his or her’s torso facing the player when locked on. Sort of like shift lock movement.

Okay I’ll see what I can do thanks for the clarification

Take a look at this

Sorry for the late response. I was busy maybe we could continue this tomorrow later in the afternoon? I have school so in 5:00 or 6:00 PM CDT I might be on.

Ok, so I made a lock-on script from a tutorial but modified it.

Here is the script:

local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")

local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local Camera = game.Workspace.CurrentCamera
local Target = nil

UIS.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.LeftAlt then
		for _,v in pairs(game.Players:GetChildren()) do
			if v:IsA("Humanoid") then
				Target = v
			else
				Target = nil
			end
		end
	end
end)

RS.RenderStepped:Connect(function()
	if Target then
		local CameraPosition = CFrame.new(Character.HumanoidRootPart.Position, Target.PrimaryPart.Position)*CFrame(10,10,10).p
		Camera.CameraType = Enum.CameraType.Scriptable
		Camera.CFrame = CFrame.new(CameraPosition, Target.PrimaryPart.Position)
	else
		Camera.CameraType = Enum.CameraType.Custom
	end
end)

I still have to add magnitude to add distance and much more other things.

Here is the video:

I’ve tested the script I made and when playing, it doesn’t show any errors but doesn’t lock-on to anything. I’ve tried altering the script, doesn’t work.

2 Likes

You are looping through players and checking whether its a Humanoid, when its a player.

Is there any way I could get the HumanoidRootPart of the player (Not client) so that the camera can focus on the player? Do I still have to use I, v pairs or something else?

(I’ll have to go now so I’ll be on tomorrow.)

Changed the script, though I got a CFrame error I don’t know how to fix.

local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")

local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local Camera = game.Workspace.CurrentCamera
local Focus = false

UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt and not Focus and not Processed then
		Focus = true
		Camera.CameraType = Enum.CameraType.Scriptable
	elseif Input.KeyCode == Enum.KeyCode.LeftAlt and Focus and not Processed then
		Focus = false
		Camera.CameraType = Enum.CameraType.Custom
	end
end)

RS.RenderStepped:Connect(function()
	while Focus do
		local CameraTarget = game.Workspace:GetChildren(Character:WaitForChild("HumanoidRootPart"))
		local CameraPosition = CFrame.new(Player.Character.HumanoidRootPart.Position, CameraTarget.Position)*CFrame(10,10,10).p
		Camera.CFrame = CFrame.new(CameraPosition, CameraTarget.Position)
		RS.RenderStepped:Wait()
	end
end)