Trying to make Target Lock-on work on players

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)

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!