Hi, I’m currently trying to create a projectiles system and was wondering if there was any way of rewinding time. This so that the server can see to a reasonable degree what the client saw based on their ping to validate a projectile collision. Thanks.
Have you tried using raycast to get what the projectile hit?
You seem to have misunderstood the post. I will indeed use raycasts to validate a collision. Though I would require the world to be what the client saw when the projectile hit and so I would need a way to rewind time.
So something for like a “kill cam” or something like that?
No, not really. This is the process in which the system is supposed to work:
Client sends a requests for a bullet to be instantiated.
Server validates the request and sends a signal to other clients to replicate the bullet
The client which created the bullet hits something and tells the server about it.
The server then must validate the hit via methods such as checking the trajectory.
The last part of that is where I need time to be rewound, because the latency between the client and server causes positions of moving objects to be slightly out of sync. If I can rewind time, the validation on the server’s end would be more accurate.
There may be other ways, but to me what comes in mind is maybe make it so the client sends the time and position of the bullet when it “hit” and then a list of near objects with their magnitude or position; and then use that information in the verification process. Though tbh, i dont think using client information to verify is the best way (since we all know we cant trust the client).
A solution could be to “fast forward time” , so instead of starting from the player that was hit and drawing a raycast you could start from the shooter and see the next position in time of the target player
Look into methods of Lag Compensation. That’s the process of the server essentially rewinding time to account for a player’s latency.
I haven’t personally created a system like it, but hopefully searching that term on here and on Google will help you find what you’re after.
Hi thanks for the response. I’ve already researched a little into lag compensation. That’s where I got the time reversal from. I just want to know a viable way to tackle creating a system like it. The idea I have right now if to log a position of all objects which I mark as movable every X seconds so that way I have a way to get all the positions of movable objects at X time. Then, I can create dummy objects so that the validation can take place. However, the issue I have with this is creating dummy objects that possess an accurate hitbox.
Not too sure how to go about this.
I’m not sure if this would help or not, but the way I do it is I have client side hit detection. So on the client raycast from a start point to an end point and if a player is in-between that’s a “Hit”. I tell the server where the, start point of the ray is, where the endpoint of the ray is and lastly where the player I hit was.
The server now has that data, so firstly it will make sure the start point of the ray makes sense by checking that point from the distance of the player that fired the projectile. Then, if its a real projectile it will do a d = v*t check to make sure that the projectile would have been near the point of impact (if you don’t have real projectiles don’t worry about it.). This is the part you were curious about Im pretty sure. Its a function I made to make sure that the player hit was in the path of the ray.
the way this works is basically just checking if the player was in the bounds of the raycast. here is an image explaining the concept
In this image the function would return true because the player hit point is inside of the red square. Otherwise, it would return false.
Discrep is the amount of “give” you give in studs.
Point1, and Point2 are the start and end points
Point Between is the position of the player hit.
function IsPointBetween(Discrep, Point1, Point2, PointBetween)
local function CheckPoint(Point1Axis, Point2Axis, PointBetweenAxis)
local BetweenPoint = false
if Point1Axis > Point2Axis then
Point1Axis = Point1Axis + (Discrep)
Point2Axis = Point2Axis + (-1*Discrep)
if PointBetweenAxis <= Point1Axis and PointBetweenAxis >= Point2Axis then
BetweenPoint = true
end
elseif Point1Axis < Point2Axis then
Point2Axis = Point2Axis + (Discrep)
Point1Axis = Point1Axis + (-1*Discrep)
if PointBetweenAxis >= Point1Axis and PointBetweenAxis <= Point2Axis then
BetweenPoint = true
end
end
return BetweenPoint
end
local X = CheckPoint(Point1.X, Point2.X, PointBetween.X)
local Y = CheckPoint(Point1.Y, Point2.Y, PointBetween.Y)
local Z = CheckPoint(Point1.Z, Point2.Z, PointBetween.Z)
if X and Y and Z then
return true
else
return false
end
end
I have in fact made exactly this for my game project very recently based on Valve’s method and it works very well. However, requires a few tweaks.
What I do is I calculate every player’s average ping over the past 4-7 seconds (I keep adjusting this from time to time till it feels accurate) and rewind the character positions based on the firing player’s ping - this will sync the server into seeing what the local player saw x milliseconds ago.
The client only sends a fire initiation remote providing the direction of the camera, then the server applies all the appropriate spread, recoil etc.
When rewinding, I clone the characters and set their positions according to the saved values every x milliseconds. Currently the character positions get saved 10 times per second or more, then I interpolate between two of these saves to get the accurate positions based on the TargetTime calculated by using the firing player’s ping.
The red clone in this video shows what the server sees based on the ping: