• Custom physics initialization issues
    2 replies, posted
Hello everyone. I will try to be as short and as clear as possible. There are several issues when you try to initialize a custom (I've tested [URL="http://wiki.garrysmod.com/page/Entity/PhysicsInitConvex"]PhysicsInitConvex[/URL]/[URL="http://wiki.garrysmod.com/page/Entity/PhysicsInitMultiConvex"]PhysicsInitMultiConvex[/URL]). When you initialize a custom physics object only serverside (for [URL="http://wiki.garrysmod.com/page/Entity/PhysicsInit"]PhysicsInit[/URL]([URL="http://wiki.garrysmod.com/page/Enums/SOLID"]SOLID_VPHYSICS[/URL]) it works fine, because client knows what the physics object is by the model files), the object moves correctly but can not be traced (using a gun, the context menu or any other regular trace) or touched (I mean prediction, when you step on it and so on), client doesn't know anything about the physical appearance of it, that's expected behavior. In other case, when you decide to build the same physics object on both client and server using shared code, very strange things start to happen. 1. When you initialize a custom collision mesh in shared, physgun beam breaks on client, it sticks to the spot where you've picked up the object and doesn't update it's target position. Also the object doesn't update it's position as soon as you pick it up with physgun on client. 2. When you receive a full update (can be emulated using [I]cl_fullupdate[/I] console command, requires [I]sv_cheats 1[/I]), clientside physics object just gets destroyed, doesn't matter how you set it up. Here is a sample piece of code that you can use to reproduce this behavior, just paste it to some shared autorun file and refresh on runtime, then use [I]test1[/I] console command to spawn a test entity: [CODE] local Min, Max = Vector( -10, -10, -10 ), Vector( 10, 10, 10 ) local ENT = scripted_ents.Get( "base_gmodentity" ) function ENT:Initialize() self:SetModel( "models/props_junk/TrafficCone001a.mdl" ) self:PhysicsInitConvex( { Vector( Min.x, Min.y, Min.z ), Vector( Min.x, Min.y, Max.z ), Vector( Min.x, Max.y, Min.z ), Vector( Min.x, Max.y, Max.z ), Vector( Max.x, Min.y, Min.z ), Vector( Max.x, Min.y, Max.z ), Vector( Max.x, Max.y, Min.z ), Vector( Max.x, Max.y, Max.z ), } ) self:EnableCustomCollisions( true ) self:SetMoveType( MOVETYPE_NONE ) self:SetSolid( SOLID_VPHYSICS ) self:PhysWake() end local Col = Color( 0, 0, 255, 255 ) function ENT:Draw() render.DrawWireframeBox( self:GetPos(), self:GetAngles(), Min, Max, Col ) end scripted_ents.Register( ENT, "sent_phystest" ) if SERVER then concommand.Add( "test1", function( Ply, Cmd, Args ) local Tr = Ply:GetEyeTrace() local Ent = ents.Create( "sent_phystest" ) Ent:SetPos( Tr.HitPos + Tr.HitNormal * 20 ) Ent:Spawn() Ent:Activate() undo.Create( "Prop" ) undo.SetPlayer( Ply ) undo.AddEntity( Ent ) undo.Finish( "" ) Ply:AddCleanup( "props", Ent ) end ) end [/CODE] In conclusion, the overall behavior of predicted (clientside) physics object is extremely unreliable, especially for entities with custom collision meshes. This should be changed for obvious reasons. Clientside physics objects are very likely to disappear, stuck and do other arbitrary things at random, I don't even talk about the Gravity Gun, it just fucks up everything it touches. I hope anyone here has faced these issues and came up with some solutions, because I faced a dead end because of those in my current project. Thanks. [B]EDIT:[/B] I belive this bug can be somehow connected with [URL="https://github.com/Facepunch/garrysmod-issues/issues/3174"]this[/URL] or [URL="https://github.com/Facepunch/garrysmod-issues/issues/3100"]that one[/URL] In any case, I will probably post a new issue on github with some more details if I won't find an appropriate solution and/or explanation of what's going on
After a short battle with this problem (together with Tripperful), I have concluded that this code fixes the problem, more or less: [code] function ENT:Think() if (CLIENT) then local physobj = self:GetPhysicsObject() if (!IsValid(physobj)) then init_convex(self) -- this re-inits the mesh, code omitted else physobj:SetPos(self:GetPos()) physobj:SetAngles(self:GetAngles()) end end end [/code] My guess would have to be that in a regular scenario, the following happens: 1. A physics entity is created on the server, and the server inits the physics, and tells the client to do the same. 2. The client complies, and creates some kind of 'ghost' or 'shadow' physics object to allow prediction, based on the model it knows about (if the model does not exist on the client, bad things happen). It ties that 'ghost' to the position it receives from the server. 3. When the client receives updates from the server about the entity, this 'ghost' physics object moves with it, and no problems occur. However, we don't have access to this object, and frankly, I don't even know if it's comparable to a physobject (GetPhysicsObject() returns null on client) However, if we want to init physics with a custom mesh, we have to do so on both the client and the server, since it isn't networked to the client from the server automatically. So, what happens is this: 1. The server inits physics on it's own, doing all the necessary calls, including, for example, ent:PhysicsInitConvex() 2. The client has to call ent:PhysicsInitConvex() too, [B]which results in the creation of a clientside PhysObj tied to this entity[/B]. However, this PhysObj isn't completely properly tied to the entity, and it's position and angles don't update in accordance with the updates received from the server. [b]It stays in the same spot and doesn't move, even if the entity moves serverside, leading to strange bugs.[/b] This is fine for clientside-only entities such as gibs and whatnot, but for serverside entities with physics prediction this is disasterous. 3. Even worse, when a client receives a full update about the entity, [b]this physics object is destroyed[/b]. This also happens when you pick it up with a gravgun. I believe that in case of regular physics, this happens too, but since the client knows about the physics, it is instantly re-instantiated, but it doesn't happen with the custom meshes, because the client doesn't remember them. [b]This is bad.[/b] Overall, if you want clientside prediction with custom meshes, you are [b]royally screwed[/b]. I found a fix in the form of the above code, but [b]this kind of situation should not occur at all, and this is clearly a bug.[/b] [b]EDIT:[/b] Despite the physics object staying at the same spot, doing :PhysicsInitConvex() on the client [b]turns on prediction anyway, and you can bump the entity around without prediction errors, and even stand on it[/b]. But if you try pick it up with the physgun, the beam goes to the spot where the physobject is actually located.
I have not read the full post yet since I am currently not home, but clientside physics objects have been severely fucked for many years now. Manually implementing it clientside will not work since it is due to some very bad behaviour that Garry implemented sometime between the EP2 engine update and GM13. [editline]10th May 2017[/editline] This actually has caused my Lua physgun's prediction to be fucked since not only is the main physobj invalid on the client, but the physics object count is different in many cases. I have tried many different solutions of manually creating and moving the physics object/shadow of an entity, but it has only resulted in even worse physics behaviour.
Sorry, you need to Log In to post a reply to this thread.