How to make retro Like Movement?

Hello Devforum! I’ve recently been hit with a good idea, and want to see it in action. But sadly, I’m stumped on how to do it, and I’m lost on what the best method would be, as I’m still learning. Any help is appreciated, Thanks!

What I’m trying to recreate is in this video.

What I’d expect it to look like in studio from a scripting/game dev standpoint.


[ pink = 2 way move point. | Green = 4 way move point. | red = 3 way move point ]
[ Yellow = MovementPart ]
(yes, I know it looks like Pacman. )

{ EXAMPLE BELOW }

  1. I press [ W ], I’ll Walk forward until I hit a wall, or I can turn.
  2. Let’s say I’ve ran into a wall, I’d press [ A ] to look Left. If I let go of [ A ], it’d return me to facing forward. if I wanted to go left, I’d hold [ A ] so I keep looking left, then I’d press [ W ] to move forward.

{ QUESTIONS }

  1. There will be a monster chasing you in my game, Would it be better to move the player to these points, or Move the camera to these parts?
  2. If we’re moving the player to these points, how would we do so? Does it work like moving an NPC?
  3. If we’re turning the player. Would the best possible way to turn the player be something along the lines of shiftlock?
  4. If we use the camera method, how would a monster chasing the player work?
  5. Is this even possible?

Thanks for reading! I hope this makes sense, and I really hope someone can help me with this.

4 Likes

Hey! If you are doing a first person game with a custom movement and camera system, there would be no need to rely off of the default Roblox character and camera. You could use TweenService to tween the camera’s CFrame to the next point, as well as for rotating it to look in the desired direction. As for the monster chasing the player, you could check the distance between the monster and the camera. You would need to do that in a local script, but with Roblox’s new security updates it won’t be too much of an issue. One other question, are you planning on making this game multiplayer? If players need to see other characters, the system would need to be a little different.

2 Likes

thank you for responding! I’ve never even heard of someone checking the monster distance between the camera. I’d have no idea how to do such, and how would that even work gameplay wise?

But quick question, would this be more effective then simply making the player walk to the point? and having them turn using some sort of shift-lock like mechanic?

And to answer! I’m planning to make this game singleplayer. Thanks for responding again!

You can calculate the distance easily by getting the positions of both the camera and the monster, then substracting them from each other and get the magnitude of the result.

It would be much more effective to just use the camera instead of classic player characters. Normal roblox characters and scripts are unnecesarrily heavy and may bring more trouble than usefulness. Trust me, using humanoids is always a bad idea unless necesarry.

2 Likes

I fully second everything Sarlex has said. That is why I would recommend exclusively using the Camera and disabling Players.CharacterAutoLoads. As for the distance, you could use something like this:

local RunService = game:GetService("RunService")

local hitDist = 3

local camera = workspace.Camera
local monster = workspace.Monster.PrimaryPart

RunService.RenderStepped:Connect(function()
    local dist = (camera.CFrame.Position - monster.Position).Magnitude

    if dist <= hitDist then
        print("Monster got the player!")
    end
end)
4 Likes

Side note, please dont use renderStepped for such thing. Running too many unnecesarry renderStepped events will cause severe lags, always use heartbeat or stepped (if physics is involved) for any calculations or such. Only camera related processes like visual effects (eg. camera shake) should be bound to renderStepped

3 Likes

This is very helpful from you, and from Sarlex. But this is new for me as I’ve never really done anything like this before so it may be difficult. I’m so used to working with the character spawning in and then setting the camera at the very least. I hope I’ll be able to get somewhere doing this method instead of the traditional.

Side note, Thank you for giving an idea of what to do with the script. And sarlex for as well for giving a Side note and giving even more help with scripting,

Quick question, Are there any differences in scripting when using just the camera instead of spawning in the Character and using the camera?

2 Likes

Not at all, as long as you have camera behavior set to “scriptable”, which is “required” to do any changes to it via script, there are absolutely no differences in camera handling.

2 Likes

So I mentioned disabling CharacterAutoLoads for Players, you will just need to set the camera behavior. If you know how to use TweenService, this should be fairly straight forward. You can use ContextActionService for movement(instead of trying to use Humanoid.MoveDirection or something) and tween the camera’s CFrame.

2 Likes

thank you! what about the rest of the script as well? Since we don’t have a humanoid, how much of a traditional script would be changed?

1 Like

Not much, just throw away everything you know about humanoids. When you’re working with camera, all you need to know is how to set its rotation/position, and how to tween/lerp it, which tweenService as @RoloTheDevBunny mentioned does very well

2 Likes

Well all events run every frame, the only concern is that if your code takes too long to run, you can be disrupting other important Roblox processes and delaying the rendering of the frame. Stepped would be better because it’s after network replication, but it’s still before physics so we might want to wait for the monster to be moved for this frame. But yes, it could increase the frame rendering speed by switching to Heartbeat.

2 Likes

okay, thank you! I was just making sure before I dived into any coding

quick question, how do you set the camera to a part if we’re disabling Players.CharacterAutoLoads? Anytime I try to, it just kinda has me floating in space

There’s a chance your local script runs before the game is properly loaded, basically reseting the camera in place. A simple but dirty solution would be writing

repeat task.wait(0.2) until game.IsLoaded()

At the beginning of your script

Side note, if you’re going big, the best approach would be to do it from replicatedFirst after you close a loading screen.

1 Like

thanks for the response! I tried putting it into the code, and it seems it doesn’t want to work sadly

Do you mind showing me your script snippet so I can see what you’re doing?

1 Like

I don’t mind at all! I can’t say I’m original, I’m still on the wonderful stage of needing reference from scripts to get something done. So Please bare with me

repeat task.wait(0.2) until game.IsLoaded()
local Camera = workspace.CurrentCamera
local runservice = game:GetService(“RunService”)

runservice.RenderStepped:Connect(function()
repeat wait()
Camera.CameraType = Enum.CameraType.Scriptable
until Camera.CameraType == Enum.CameraType.Scriptable
Camera.CFrame = game.Workspace.RoamCameras.CamPart.CFrame
game.Workspace.Camera.FieldOfView = 40
wait(1)
script.Disabled = true
end)

So firstly, take the

repeat wait()
Camera.CameraType = Enum.CameraType.Scriptable
until Camera.CameraType == Enum.CameraType.Scriptable

Out of the renderStepped function, you don’t need this to run on every frame, just spawn it on another thread with task.spawn() right before you start connecting the run service event

Your problem lies in the repeat function, it will never run due to its condition never being met, as or right now, you’re instructing it to set the camera type to scriptable as long as the camera is set to scriptable, which is neve true cuz the default setting for it is “custom” a simple fix is to change the == to ~=, making it run instead only when the camera is not set scriptable.

1 Like

so something like this? side note, thank you for explaining and helping so far, it means a lot

repeat task.wait(0.2) until game.IsLoaded()

local Camera = workspace.CurrentCamera
repeat wait()
Camera.CameraType = Enum.CameraType.Scriptable
until Camera.CameraType ~= Enum.CameraType.Scriptable
Camera.CFrame = game.Workspace.RoamCameras.CamPart.CFrame
game.Workspace.Camera.FieldOfView = 40
wait(1)
script.Disabled = true