Trying to make Target Lock-on work on players

Never ever put a while loop in a renderstepped (or vise versa), your game will crash very quickly.

image

RenderStepped is fired every frame, if you connect a loop every frame it will quickly be running many thousands of instances of that loop and it will keep piling up.


This line does not make any sense, :GetChildren() returns an array of instance’s children and takes 0 parameters.


You have to have some code that decides which player to “lock on” to, you’ll probably want to do that on User Input or something

I’ve been trying to get a player’s HumanoidRootPart. Should I just resort to using a different part of the player instead? Also I’ll use “If Focus then” instead of the loop. I also get Vector3 errors for my CFrame.

I suggest to put all the players in a folder within the workspace when they spawn. Then you could easily loop through the folder, then search for the nearest target.

For the collision you could use rays to check if there is an object in the way.

To make it not target players that are already dead, you could use the CollectionService to tag players that are dead, then untag them when they respawn.

*Edit

Try making separate functions like this.

1 : A function that returns a target to lock on to
Example:



local function identifytarget()
-- Loop folder, find nearest target, return target
    
    maybetarget = torso.Parent
    return target
end
--then u can refer the target somewhere in the script
   Target = identifytarget()


2: A function that does the camera lock on thing

local function lockon()
      --lock camera to target
end

3: A function that runs the above functions after getting the input

local Target = nil
-- left alt pressed event 
Target = identifytarget() -- returns the target (refer to the function above)
if Target then -- check if there is a target
   RunService:BindToRenderStep("lockontarget"),203,lockon)
end

This is just an idea for the script
Not an actual how to do

Should I use a local script or a server script?

You should use local scrip
and
You could, if u want, do two local scripts, one for listening to the input, and one for doing the camera lock on. Then bind them using bindable events or something

Oh, I was planning on using a remote event or moduleScript to “re-parent” the player

For the putting players character in one folder thing should be in a server script. You can put in the script in the server script service or something. If this is what you mean for “re-parent” the player.

Made the script today, using your template. Also I couldn’t move the player to a folder so I just made a local script and put it in the StarterPlayer. Everything is fine except that I have an error with TargetHRP

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

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

local Character = Player.Character or Player.CharacterAdded:Wait()
local HRP = Character:WaitForChild("HumanoidRootPart")

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

local Distance = 50

local function DetectingTarget()
	for _,v in pairs(game.Players:GetChildren()) do
		local TargetHRP = v:FindFirstChild("HumanoidRootPart")
		local TargetHumanoid = v:FindFirstChild("Humanoid")
		if TargetHRP and TargetHumanoid ~= script.Parent and Player.Name then
			if (HRP.Position - TargetHRP.Position).Magnitude < 50 then
				Distance = (HRP.Position - TargetHRP.Position).Magnitude
			end
		end
		return v
	end
end

Target = DetectingTarget()

local function CameraTarget()
	Camera.CameraType = Enum.CameraType.Scriptable
	local TargetHRPPos = Target.TargetHRP.Position
	local HRPPos = HRP.Position
	local Offset = Vector3.new(10,10,10)
	local CamPos = TargetHRPPos + ((HRPPos + Offset) - TargetHRPPos).Unit * ((HRPPos - TargetHRPPos).Magnitude + 12)
	Camera.CFrame = CFrame.new(CamPos, TargetHRPPos)
	RS.RenderStepped:Wait()
end

UIS.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.LeftAlt then
		if Target then
			RS:BindToRenderStep("CameraLockOn", 203, CameraTarget)
		elseif Input.KeyCode == Enum.KeyCode.LeftAlt and Target then
			Camera.CameraType = Enum.CameraType.Scriptable
			Target = nil
			RS:UnbindFromRenderStep("CameraLockOn")
		end
	end
end)

Sorry for the late reply,

I think the issue is that, you are currently looping the player not the character.
What makes the character different is because it is a model, when u test the game, you could see your character in the workspace. Also, if u have trouble putting all the characters in a folder here you go:

Make a folder in workspace.
Add a script in serverscriptservice
Then copy this.

local function onPlayerAdded(p)
	p.CharacterAdded:Connect(function(character)
         task.wait(0.1)
		 character.Parent = game.Workspace.AllCharacters -- this is your folder that u added
		end)
	end

game.Players.PlayerAdded:Connect(onPlayerAdded)

However, in the future, you need to add a safety measure so that a hacker cannot put their character out of the folder.

Tried to call the character, got an error though.

local function DetectingTarget()
	for _,v in pairs(game.Workspace.AllCharacters:GetChildren()) do
		local TargetHumanoid = v.Character:FindFirstChild("Humanoid")
	end
end

Screen Shot 2021-09-26 at 11.07.29 AM

I’m a terrible scripter but you could try finding all humanoids in an area, locating its parent, and making a GUI that tracks the model’s location.

Solved the small problem, I just couldn’t use the Character for some reason since it isn’t part of the folder I hold all the players in. Thanks for the help though!

No need to put Character.
when you are looping the folder, the v is automatically the character(model) so you would just need to do

local targetHumanoid = v:FindFirstChild(“Humanoid”)

I have a problem with an “else if” statement I made for the key bind whenever the player presses on the key bind again. It shows no errors though, but doesn’t go back to custom.

UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt then
		Target = FindTarget()
		Camera.CameraType = Enum.CameraType.Scriptable
	elseif Input.KeyCode == Enum.KeyCode.LeftAlt and Target ~= nil then
		Target = nil
		Camera.CameraType = Enum.CameraType.Custom
	end
end)
UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt then
		Target = FindTarget()
		workspace.CurrentCamera.CameraType = "Scriptable"
	elseif Input.KeyCode == Enum.KeyCode.LeftAlt and Target ~= nil then
		Target = nil
		workspace.CurrentCamera.CameraType = "Custom"
	end
end)

try this

Tried it, still the same though.

Edit: Forgot to say, that I can’t get the position of TargetHRP as it is not a member of players.

local alreadyPressed = false

UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt then
              if alreadyPressed == true then
                    Target = nil
                    workspace.CurrentCamera.CameraType = "Custom"
                     alreadyPressed = false
              else
                    Target = FindTarget()
                     workspace.CurrentCameraType = "Scriptable"
                     alreadyPressed = true
               end
         end
end)

Make sure you are searching the player’s character not players

Btw show me the script where you tried to find the TargetHRP

I prefer not using a folder to store players in so that when an exploiter gets his character out of the folder, it doesn’t remove the target lock-on.

Here is the script:

local function FindTarget()
	for _,v in pairs(game.Players:GetChildren()) do
		if v ~= Player.Name then
		local TargetHum = v:FindFirstChild("Humanoid")
		local TargetHRP = v:FindFirstChild("HumanoidRootPart")
		return v
		end
	end
end


UIS.InputBegan:Connect(function(Input, Processed)
	if Input.KeyCode == Enum.KeyCode.LeftAlt then
		Target = FindTarget()
		if Target then
			Camera.CameraType = Enum.CameraType.Scriptable
			local TargetHRPPos = Target.TargetHRP.Position
			local HRPPos = HRP.Position
			print(TargetHRPPos)
		end
	end
end)

I’ve tried removing the local from function and it seems like its not a scoping problem.

1 Like

try to copy this code in a server script:

task.wait(5)
for i , v in pairs (game.Players:GetChildren())do
	print(i,v) 
	local children= v:GetChildren()
	print(children) 
end

And look at the output.
The second print function prints =
{
[1] = StarterGear,
[2] = Backpack,
[3] = PlayerGui
}

If you don’t want to use a folder, you would have to find a way to get all the players’s character.
I don’t seem to know the alternate way right now, but I am going to try to search for it. Once I have an alternate that I found for you I will inform u

1 Like