Allowing Default Replication for Non-Humanoid Based Character Controllers

Project Overview:

For the past week, I’ve been working on a little project—a full character controller from scratch. It employs CFrame calculations and simple velocity and acceleration-based mechanics for smooth movement. Here’s a preview:

Replication Issue:

When I attempted to set this character as the starter character for the player, I realized it doesn’t replicate. I assumed any character models automatically replicate when assigned as a player’s character by the server.

Exploring Replication:

I read the documentation related to replication, and I know I can make my own replication system. But why doesn’t it replicate automatically? Am I missing something?

Custom Character Controller:

Some might ask, why make a character controller from scratch and reinvent the wheel? Especially when physics controllers have been released? The answer is simple. Physics controllers aren’t customizable enough. The controller I made allows for complex interactions between states, giving me 100% control for a more precise experience. This is particularly useful for combat games with abilities and complex movement. Physics-based controllers can be janky since they consider too many variables like mass and friction, which I don’t need.

So for me, I think reinventing the wheel sometimes is a good idea, specially when the existing wheel isn’t what I need.

Finally what do you guys think, I might be overlooking something here so feel free to correct me, I’d also love to hear your opinions on this too.

6 Likes

Should totally move this to scripting support.

I think what might help you is using the recently released unreliable remote events and buffers (optional but allows compressing data).

You will likely have to manually replicate player movement to the server using these.
If your movement system is CFrame based (with anchored root part) then it likely won’t replicate on it’s own.

Does your character have a humanoid inserted at all (perhaps with state disabled) or absolutely none?
Is the root part anchored? How do you currently move the player around?

Knowing those details could help identity the issue. :slight_smile:
Your movement system looks nice btw!

2 Likes

thanks, I really appreciate it :heart:

I use a disabled humanoid since I wanna allow custom player avatars, I’m not sure when are they planning on decoupling avatar functionality from it to separate components.

and yea all the parts are unanchored and set to CanCollide = false (for custom collision detection) except for the humanoid root part.

I really appreciate the buffer resource, I was looking for a way to compress data and researching remote event behavior and limitation just now lol.

also since reliable remote events don’t have a specific order (correct me if I’m wrong), I’d have to have some sort of buffer on the server to ensure the execution order is correct.

The easiest way I can think of solving this issue is storing the last 2 - 3 positions in an array and only accepting position data that has the longest distance from the last 2 - 3 positions.

Alternatively you can compare the direction between the last and most recent way the player was moving in.
If a player suddenly turns around 180 degrees randomly you can almost safely assume it’s older position data being received first.

If you receive the same direction multiple times you can be more confident that that direction is the direction the player actually wants to move into.

1 Like

Since I’m going to be remaking replication from scratch, I might as well make it server authoritative and as you suggested use a hybrid approach between unreliable remote events and normal remote events with the buffer to compact sent data.

for order issues, luckily Roblox has a synchronized clock between the server and client with micro second precision (which is incredible since making a synced clock is super hard), I can timestamp the client’s requests before sending it to the server.

the server would use these timestamps paired with the player’s half round trip time (half the ping) to know (with decent precision) when this action was performed and validate and update it’s own state accordingly.

I think using unreliable events would be good for movement and orientation updates, while actions like attacking or special abilities should be handled via normal remote events.

that’s my theory at least of how I’m gonna make this, but obviously talk is cheap and implementing this in the right way would take time and iteration which I’m 100% willing to do.

1 Like

If the movement is based on physics, constraints, or animation/animators (i.e. it’s not anchored parts), you can set the network ownership on the server to the player’s client. That’s how regular characters are replicated:

If it’s only based on CFrames with anchored parts, you’d probably want to create a custom replication system.

1 Like