• PhysicsSimulate not being called
    4 replies, posted
I'm working on a vehicle that will handle its own motion entirely on its own - as such I'm disabling gravity and using PhysicsSimulate. Two main questions arise from this: 1. In running a few tests I'm finding that the PhysObj keeps being put to sleep when it stops moving - how can I prevent this? User input is handled in the physics function (currently), so should I just constantly wake the physics object in the think method or move the controls to the think function and wake it on input? Or is there a better way? 2. How do the units work when returning linear force - the standard formula of F=m*a doesn't seem to be valid here based on my initial tests (or else I don't know how the source units relate). For example, I'd like to know how much force to apply to make a mass 100 object move 50 units vertically in 1 second - how would this be calculated? I could post code but it's pretty simple and I've already verified that the problem is the object falling asleep - both through querying if it's asleep via console and by finding that it starts working correctly if I give it some velocity with the physics gun.
I'm not sure it will help, but take a look at [url=http://developer.valvesoftware.com/wiki/Dimensions]this[/url].
I don't know about any of your fancy physics problems, but when I was messing around with PhysicsSimulate I had a similar problem of it not being called. All you need to do is in your ENT:Initialize(), use [b][url=wiki.garrysmod.com/?title=Entity.StartMotionController]Entity.StartMotionController [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b].
Issue #1 is workable, as I've started waking the physObj when I expect motion. However, I'm having a lot more trouble with problem #2, the motion. Varying mass and desired time mess up the measured time (varying distance to travel is ok). Here's my test code: shared.lua [lua]ENT.Type = "vehicle"//"anim" ENT.Base = "base_anim" ENT.PrintName = "Your Everyday Tank Tester" ENT.Spawnable = true ENT.Mass = 500 //In kg, the mass of the object ENT.Dist = 100 //In source game units, the distance to travel ENT.Time = 6 //In seconds, how long to take to travel that distance[/lua] init.lua [lua]AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile( "shared.lua" ) include('shared.lua') //Standard spawn function, ignore it function ENT:SpawnFunction( pl, tr ) if (!tr.Hit) then return end local ent = ents.Create("forceTest") ent:SetPos(tr.HitPos+Vector(0,0,20)) ent:Spawn() ent:Activate() return ent end function ENT:Initialize() self.Entity:SetModel("models/props_interiors/pot01a.mdl") self.Entity:PhysicsInit(SOLID_VPHYSICS) //Todo: These two may be unecessary self.Entity:SetMoveType(MOVETYPE_VPHYSICS) self.Entity:SetSolid(SOLID_VPHYSICS) self.Entity:SetUseType(SIMPLE_USE) //Todo: Is there a better way to do this? self.Entity:GetPhysicsObject():SetMass(self.Mass) self.Entity:GetPhysicsObject():EnableGravity(false) self.Entity:GetPhysicsObject():SetDamping(0,0) //These two are currently unnecessary but self.Entity:GetPhysicsObject():Wake() self.Entity:GetPhysicsObject():EnableMotion(true) //Enables custom physics self.Entity:StartMotionController() self.Active=false self.DoPush=false self.StartHeight=0 self.StartTime=CurTime() end function ENT:Think() if (self.Active) then if (self.Entity:GetPos().z>self.StartHeight+self.Dist) then local diff = CurTime()-self.StartTime print("Travelled "..self.Dist.." units at "..CurTime()..", in "..diff..".") self.Active=false end end end function ENT:OnRemove() //Todo: Confirm if this is necessary self.Entity:StopMotionController() end function ENT:Use( activator, caller ) if (!self.Active) then self.Active=true self.DoPush=true self.Entity:GetPhysicsObject():Wake() //Wake it up self.StartHeight=self.Entity:GetPos().z self.StartTime=CurTime() print("Starting to ascend @ "..self.StartTime) print("Ascent should take "..self.Time.." if everything is correct!") end end function ENT:PhysicsSimulate(phys, deltatime) if (self.DoPush) then self.DoPush=false local force = self.Mass * ((self.Dist*.75) / math.pow(self.Time,2)) //0.75 in = 1 hammer unit print("Pushing with force "..force.."!") return vector_origin,Vector(0,0,force),SIM_GLOBAL_ACCELERATION else return vector_origin,vector_origin,SIM_GLOBAL_ACCELERATION end end[/lua] cl_init.lua is omitted as it's just setting up the render group and including shared.lua. The measurements from my testing are as follows: [code] Mass Dist Time Actual 1000 100 5 2.31 750 100 5 3.14 500 100 5 4.63, 4.45,4.47,4.61,4.48 100 100 5 22.305 500 500 5 ~4.55 500 100 5 ~4.5 500 50 5 ~4.5 500 10 5 ~4.5 500 100 6 ~6.5 500 100 5 ~4.5 500 100 4 ~2.95 500 100 3 ~1.66 500 100 2 ~.75 500 100 1 ~0.33[/code] The most important line of all that is the calculation for force, which is "force = self.Mass * ((self.Dist*.75) / math.pow(self.Time,2))". This should be correct- kg * in / s^2 is the formula given on the phys_thruster page, and the Dimensions page lists 1 unit being equal to 0.75 inches. Varying mass and time make for inconsistent results. I'm still not sure how to fix this, as it's required for my vehicle to be able to accurately calculate force to reach points in specific amounts of time (and I'm not using the shadowcontrol function as these forces vary between physics ticks, which don't have an associated time to my knowledge). Any thoughts? [QUOTE=NullPoint;19330394]I'm not sure it will help, but take a look at [url=http://developer.valvesoftware.com/wiki/Dimensions]this[/url].[/QUOTE] Definitely helpful, since it not only gave a units-to-inches conversion rate but also led to [url=http://developer.valvesoftware.com/wiki/Phys_thruster]here[/url] which gives the force formula as F=kg·in/s^2. [QUOTE=Entoros;19332892]I don't know about any of your fancy physics problems, but when I was messing around with PhysicsSimulate I had a similar problem of it not being called. All you need to do is in your ENT:Initialize(), use [b][url=wiki.garrysmod.com/?title=Entity.StartMotionController]Entity.StartMotionController [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b].[/QUOTE] I actually came across your topic earlier today while searching facepunch for info! While useful to note, in this particular case it's definitely being enabled, the engine was just putting it to sleep due to non-motion. I've resolved that part of the issue, temporarily, by waking it when I expect it to move.
If you're having trouble with getting the timing right for the physics, I would recommend using [b][url=wiki.garrysmod.com/?title=PhysObj.ComputeShadowControl]PhysObj.ComputeShadowControl [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]. You can use the params to tell it exactly how long it should take to move to a particular position and angle, as well as applying damp and clamping the maximum velocity if need be.
Sorry, you need to Log In to post a reply to this thread.