How to Spectate Players Outside of Render Distance?

I have a spectate system mostly made for my game, where once a player dies it sets them into a forced spectating mode where they can spectate anyone who is currently alive. I have recently found a bug however, where if the player being spectated is out of render distance from the player spectating (which is fairly common) then the camera will just get stuck in place until they come back into render distance. How do I fix this?

1 Like

You can detect when a player’s character gets streamed out using CollectionService and tags

Essentially, tag the player’s character in CharacterAdded, and use CollectionService’s GetInstanceAddedSignal and GetInstanceRemovedSignal to detect when they’re within or outside of the spectating player’s streamed-in radius


@Spooce I genuinely wasn’t aware of that property, so awesome suggestion dude! :grin:

2 Likes

Try setting the spectating player’s ReplicationFocus to the subject’s root part.

6 Likes

Another way would be to have a selection menu of who you want to spectate and have the camera follow them close up. I’ve seen other games with this mechanic using left and right GUI buttons to scroll through all the players.

This ALMOST works but the problem is that I can’t seem to set ReplicationFocus to the subject’s root part if they aren’t in render distance, which just kinda brings me back to the original problem. It’s a step close but now I need to be able to set it to objects outside of the already existing render distance.

You can only set ReplicationFocus on the server, so you shouldn’t have to worry about it being streamed in on the client. Hence, you can pass the target player through a remote event, allowing the server to find the root part and set the ReplicationFocus for the spectating player.

2 Likes

So, despite my best efforts, setting the player’s ReplicationFocus through the server still has the same result, being not able to set it if the Player that is being spectated is outside of render distance. Since that didn’t work server sided now I’m just confused :sob:

I would suggest you share your code as there is probably something wrong with your code

ReplicationFocus is the intended solution for managing where StreamingEnabled should stream in objects, in the case the camera isn’t around the character

2 Likes

Are you talking about with streaming enabled? you can use Player | Documentation - Roblox Creator Hub (RequestStreamAroundAsync) method on the player and then replication focus?

1 Like

Client side:

--PlayerToAttempt is a player in Players
ReplicatedStorage.Events.Spectate:FireServer(PlayerToAttempt)

Server Side:

ReplicatedStorage.Events.Spectate.OnServerEvent:Connect(function(Player, PlayerToSpectate)
	Player.ReplicationFocus = PlayerToSpectate.Character.PrimaryPart
end)

Your code seems good, I don’t see anything wrong with it

Could you go into more details about this? Were you getting an error, or what was preventing it from being set?

Here is the full code for spectating a new player on the client side. What was shown in the previous message for the server side was all that was all that there was on the server for this.

--CurrentSpectatingPlayer is just a number
for i=1, 10 do
		if CurrentSpectatingPlayer >= #Players:GetPlayers() then
			CurrentSpectatingPlayer = 1
		else
			CurrentSpecatingPlayer += 1
		end
		if Players:GetPlayers()[CurrentSpecatingPlayer] then
			local PlayerToAttempt = Players:GetPlayers()[CurrentSpecatingPlayer]
			if PlayerToAttempt.Character:WaitForChild("Humanoid").Health > 0 then
				ReplicatedStorage.Events.Spectate:FireServer(PlayerToAttempt)
				workspace.CurrentCamera.CameraSubject = PlayerToAttempt.Character:WaitForChild("Humanoid")
				Main.Dead.SpectatingPlayer.Text = PlayerToAttempt.Name
				break
			end
		end
	end

This is run every time a new player is to be spectated

on the serverside set the player character model streaming mode to persistent so that the rootpart never streams out

			if PlayerToAttempt.Character:WaitForChild("Humanoid").Health > 0 then
			end

This if statement here is your problem. Since the Character is not loaded in on the client, PlayerToAttempt.Character will be nil. Then you’ll be calling :WaitForChild() on nil, which will cause an error
Either way, you should always check if Player.Character isn’t nil. That property of Player is often nil, such as when a player is dead

what @happya_x suggested wont fix your full issue as, well you would be able to spectate the player, but everything around the player would be unloaded. It would however make your client sided code work, not sure if that was what Happya was suggesting, but I wanted to clarify that

There is also be a delay between the time ReplicationFocus is set on the server, and when the player will appear to the client (due to latency). So either use Player.CharacterAdded:Wait() if the Character is nil, or some collection service tag shenanigans, or Happya’s suggestion

Another solution would be storing in a different manner the state of the player, by possibly having a BoolValue under their Player object to tell if they are alive or not, or if you want to make something more complicated but cleaner, a system where the server sends information about players through remote events, and to a client sided module or something

But the thing is, it passes this part of the code perfectly fine. Once players die, they don’t insta respawn which is why the check is needed. The client is able to detect the player who is being spectated’s humanoid health perfectly fine, since it isn’t a physical object and hence is loaded anywhere. The game TRIES to spectate the player since it sets SpectatingPlayer.Text to the player’s name perfectly fine, meaning it DOES in fact pass that part of the code without issue.


Model#ModelStreamingMode

Even though humanoids are not physical objects, if it is a child of a model, it will get streamed out if the model itself is streamed out. Unless player characters are an exception, they will stream out if far enough

Could you send the error message you are getting or more details about what is not working. Because it’s quite hard to diagnose the issue if I don’t know what the error is, especially if it isn’t caused by what I thought was the culprit

There is no error message it legit just, doesn’t.

1 Like

Ah this seems to have fixed it! Thanks to everyone who helped here!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.