Would you suggest I just put the constants in their own module script and separate it out from the simulation object?
How would I implement some sort of timer for a knockback system? I tried using command.serverTime but the value seems to be stuck at 0 for bots
I just have it send the initial state through a reliable remote, it only took me adding 5 lines. Is there a reason I shouldn’t be doing this? I don’t understand why this wasn’t already a thing.
I have rewritten the collision module to use block casting; after lots of tweaking, I’ve gotten it to a state where I can no longer clip into objects, and there are no mispredicts! It is pretty simple, but it took me forever to think of it. Now, we can use variable-sized hitboxes!
This would probably get better results with capsule colliders, but its been working fine for me with the block ones.
It is a drop in replacement, the only bit of code that needs changing is the ProjectVelocity function in the Simulation module.
if planes[result.normal] == nil then
planes[result.normal] = true
--Deflect the velocity and keep going
moveVel = MathUtils:ClipVelocity(moveVel, result.normal, 1.0)
else
--We hit the same plane twice, push off it a bit
movePos += result.normal * 0.01
moveVel += result.normal
break
end
I changed it to use the results normal instead of its plane number.
local RunService = game:GetService("RunService")
local CollectionService = game:GetService("CollectionService")
local Debris = game:GetService("Debris")
local PhysicsService = game:GetService("PhysicsService")
if RunService:IsServer() then -- probably just create these in studio beforehand or the server module instead of here
PhysicsService:RegisterCollisionGroup("GameArea")
PhysicsService:CollisionGroupSetCollidable("GameArea","GameArea",true)
PhysicsService:CollisionGroupSetCollidable("GameArea","Default",false)
end
local module = {}
-- Constants
local DEFAULT_SIZE = Vector3.new(3, 5, 3)
local SHIFTBACK = 1 -- shift start position of the cast back by a constant offset, in opposite direction of movement. this will avoid the cast ever starting too close to a wall and us phasing through. There are some quirks when going over small terrain or features.
-- under 1 there are some rare cases when at extreme angles that you can get close enough to a wall to phase through it
function module:Sweep(startPos, endPos) -- not sure how to properly impelement all solid and start solid, possibly do a getpartBoundsInBox check at the starting position, but that will pick up meshparts incorrectly
local data = {
startPos = startPos,
endPos = endPos,
fraction = 1,
startSolid = false,
allSolid = false,
normal = Vector3.new(0, 1, 0),
}
local offset = endPos-startPos
local distance = offset.Magnitude
if distance <= 0 or distance >= 1024 then
return data
end
local direction = offset.Unit
local params = RaycastParams.new()
params.CollisionGroup = "GameArea"
--params.FilterType = Enum.RaycastFilterType.Exclude
--params.FilterDescendantsInstances = {}
local castOrigin = startPos-(direction*SHIFTBACK)
local result = workspace:Blockcast(
CFrame.new(castOrigin),
DEFAULT_SIZE,
direction*(distance+SHIFTBACK),
params
)
if result then
data.fraction = (result.Distance-SHIFTBACK) / direction.Magnitude
data.normal = result.Normal
data.endPos = castOrigin + direction.Unit * result.Distance
--data.allSolid = data.startSolid and data.fraction < 0.001
else
data.endPos = endPos
end
return data
end
function module:MakeWorld(folder)
debug.setmemorycategory("Collision")
-- Process existing parts
for _, instance in ipairs(folder:GetDescendants()) do
if instance:IsA("BasePart") and instance.CanCollide then
instance.CollisionGroup = "GameArea"
end
end
-- Handle new parts
folder.DescendantAdded:Connect(function(instance)
if instance:IsA("BasePart") and instance.CanCollide then
instance.CollisionGroup = "GameArea"
end
end)
end
return module
As stated previously by MrChickenRocket, there are some mispredicts on rotated base parts due to how Roblox replicates them with slight inaccuracies. We can’t account for that in the collision detection now, so it may be necessary to round them on the client and server at runtime or manually replicate the accurate CFrames.
I don’t think this is for fighting games because I’m pretty sure it allows both clients to desync while still validating [ whatever clients must have seen ] on the server.
Assuming I’m correct, most games should be able to use this. However, for fighting games it’s not ideal to have any form of desync.
I found a pretty good article that shows the downsides of both netcodes
Netcode Architectures Part 3: Snapshot Interpolation | SnapNet
vs.
Netcode Architectures Part 2: Rollback | SnapNet
For those looking for a head start on client-side prediction rollback, you should be able to find helpful information in this thread.
Humanoids are giving me a receive rate of 200kbps on a 70 player server, would chickynoid fix this? What would receive rates per player look like? I assume the best solution for low receive rate would be client-sided physics characters, but that comes with cheats being easy to make.
Differences in Jump Height when you press vs hold the jump button
anybody know a fix?
It should be inside the walking move state, I modified mine a lot, so I don’t remember exactly where, but it should be in there.
This might be the issue
@MrChickenRocket I am desperate by replying to this thread, I have been tired with humanoids recently and their horrible movement so I took chickynoids collision for my own character controller that is client side instead of server side. Everything has been going well but now I can’t find a balance between smooth interpolation for replicating players as well as having accurate lag compensation. I pretty much have converted all of the custom synced time code from chickynoid into my own project. Right now I have lag compensation working perfectly but replicated players movements are super jittery and unpredictable. All of my code for replicating is done pretty much 1 to 1 like chickynoid, even interpolating positions uses a bind to render stepped right now and I still get this issue. I’m curious as to your thoughts on what might be causing this issue. Since chickynoid does both perfectly well and as much as I look through the code I still can’t get mine to work right. (Ended up fixing this by just sending the players position every frame. For some reason this works and it was the only things I neglected that chickynoid does since techniclly it sends a “position” or a command every frame.)
Are you using roblox physics for the movement
Like i stated in the post above i am using chickynoids collision system and have completely ditched humanoids altogether.
If you are going to make it client sided you shouldn’t use the physics system from chickynoid, there’s no reason to use it.
Build a custom character controller using Roblox physics or take a look at their character controller instances.
Trust me i’ve tried, roblox physics has all sorts of its own quirks like trying to go up slopes well, etc. The main reason i’m using collision from chickynoid is because i want quake movement and having aabb collision boxes for player size makes collision and movement feel good. At least i’ll go this way until roblox shape casts actually have margins and aren’t complete trash.
You can’t use roblox physics for character controllers for rollback
He said he is using the physics system for client side.
what’s the differences between AlwaysThink, ActiveThink and AlwaysThinkLate?
AlwaysThink runs every frame, Active think runs while it is the current chickynoid move type, AlwaysThink late runs after always think
alright thanks (aaaaaaaaaaaaaaaaaa)