Hi,
For the last few days, I've been trying to make my platforms/lifts perfect for both the player, and physical objects. I've thought I solved the issue explained here, but upon further investigation, I noticed a few problems. When the platform goes down, the physical object is put to sleep, and does not wake up when the platform goes back down. I've tried a bunch of things to keep it awake, but the box reacted to violently, and the overall result was bad.
In the demo, I made a non-physics based script which worked for the demo, but when I went to use it in levels, the physics update did not update the player, and the player would just "fall through" the platform.
I would just keep using the standard sliding door script as it solves both problems, but the platform itself reacts to physical impact. So in a case, a box can be falling for a few meters, and when it crashes on the platform, it sinks below the floor brush. I've made a script that prevents this when the platform is resting, but it can still be offset when the platform is moving.
Collision Rules:
---------------------------------------------------
--[[Collsion Defines: Make new Collision Rules ]]--
---------------------------------------------------
Collision.CharacterBlocker = 9
Collision.PropBlocker = 10
Collision.Clip = 11
Collision.PickInfo = 12
Collision.PickedUpProp = 13
Collision.Item = 14
Collision.JointObject = 15
Collision.PickInfoCrouch = 23
-- Props can activate triggers.
Collision:SetResponse(Collision.Prop, Collision.Trigger, Collision.Trigger) -- Comment me out if you don't want this!
-- CSG Collisions
Collision:SetResponse(Collision.CharacterBlocker, Collision.Character, Collision.Collide)
Collision:SetResponse(Collision.PropBlocker, Collision.Prop, Collision.Collide)
Collision:SetResponse(Collision.PropBlocker, Collision.PickedUpProp, Collision.Collide)
Collision:SetResponse(Collision.PropBlocker, Collision.VecBox, Collision.Collide)
Collision:SetResponse(Collision.Clip, Collision.Character, Collision.Collide)
Collision:SetResponse(Collision.Clip, Collision.Prop, Collision.Collide)
Collision:SetResponse(Collision.Clip, Collision.PickedUpProp, Collision.Collide)
-- Picked up objects can still collide with triggers, but never characters.
Collision:SetResponse(Collision.PickedUpProp, Collision.Character, Collision.Collide)
Collision:SetResponse(Collision.PickedUpProp, Collision.Scene, Collision.Collide)
Collision:SetResponse(Collision.PickedUpProp, Collision.Prop, Collision.Collide)
Collision:SetResponse(Collision.PickedUpProp, Collision.Trigger, Collision.Trigger)
Collision:SetResponse(Collision.PickedUpProp, Collision.PickedUpProp, Collision.None)
-- Items
Collision:SetResponse(Collision.Item, Collision.Character, Collision.Trigger)
Collision:SetResponse(Collision.Item, Collision.Scene, Collision.Collide)
Collision:SetResponse(Collision.Item, Collision.Prop, Collision.Collide)
Collision:SetResponse(Collision.Item, Collision.Trigger, Collision.Trigger)
Collision:SetResponse(Collision.Item, Collision.PickedUpProp, Collision.None)
-- PickInfo
Collision:SetResponse(Collision.PickInfo, Collision.Scene, Collision.Collide)
Collision:SetResponse(Collision.PickInfo, Collision.Prop, Collision.Collide)
Collision:SetResponse(Collision.PickInfo, Collision.PickedUpProp, Collision.Collide)
Collision:SetResponse(Collision.PickInfo, Collision.Trigger, Collision.None)
Collision:SetResponse(Collision.PickInfo, Collision.Item, Collision.Collide)
Collision:SetResponse(Collision.PickInfo, Collision.JointObject, Collision.None)
Collision:SetResponse(Collision.PickInfoCrouch, Collision.Scene, Collision.Collide)
Collision:SetResponse(Collision.PickInfoCrouch, Collision.Prop, Collision.Collide)
Collision:SetResponse(Collision.PickInfoCrouch, Collision.PickedUpProp, Collision.None)
Collision:SetResponse(Collision.PickInfoCrouch, Collision.Trigger, Collision.None)
Collision:SetResponse(Collision.PickInfoCrouch, Collision.Item, Collision.Collide)
Collision:SetResponse(Collision.PickInfoCrouch, Collision.JointObject, Collision.None)
--JointObject
Collision:SetResponse(Collision.JointObject, Collision.Character, Collision.Collide)
Collision:SetResponse(Collision.VecBox, Collision.JointObject, Collision.Collide)
Now here is my current platform code based off the sliding door script.
import "Scripts/Functions/ReleaseTableObjects.lua"
Script.enabled=true--bool "Enabled"
Script.openstate=false--bool "Start Open"
Script.distance=Vec3(0,0,0)--Vec3 "Distance"
Script.movespeed=1--float "Move speed" 0,100,3
Script.opensoundfile=""--path "Open Sound" "Wav File (*wav):wav|Sound"
Script.closesoundfile=""--path "Close Sound" "Wav File (*wav):wav|Sound"
Script.loopsoundfile=""--path "Loop Sound" "Wav File (*wav):wav|Sound"
Script.closedelay=-1
Script.opened=false
function Script:Start()
self.entity:SetGravityMode(false)
if self.entity:GetMass()==0 then
self.entity:SetMass(10)
end
self.sound={}
self.sound.stop01 = Sound:Load("Sound/Gameplay/VecPlatform/platform_stop01.wav")
self.sound.stop02 = Sound:Load("Sound/Gameplay/VecPlatform/platform_stop02.wav")
-- Collision Fix
self.entity:SetCollisionType(Collision.JointObject)
self.protector= Model:Box(1,1,1)
self.protector:SetPosition(self.entity:GetPosition(true))
self.protector:SetRotation(self.entity:GetRotation(true))
self.protector:SetQuaternion(self.entity:GetQuaternion(true))
self.protector:SetShape(self.entity:GetShape())
self.protector:SetShadowMode(0) -- Fix the shadow mode for the platform
self.protector:SetGravityMode(false)
self.protector:SetCollisionType(Collision.PropBlocker)
self.protector:SetParent(self.entity)
local material = Material:Load("Materials/Effects/Invisible.mat")
self.protector:SetMaterial(material)
material:Release()
if self.opensoundfile~="" then self.sound.open = Sound:Load(self.opensoundfile) end
if self.loopsoundfile~="" then self.sound.loop = Sound:Load(self.loopsoundfile) end
if self.closesoundfile~="" then self.sound.close = Sound:Load(self.closesoundfile) end
if self.sound.loop~=nil then
self.loopsource = Source:Create()
self.loopsource:SetSound(self.sound.loop)
self.loopsource:SetLoopMode(true)
self.loopsource:SetRange(50)
end
self.opentime=0
--Create a motorized slider joint
local position=self.entity:GetPosition(true)
local pin=self.distance:Normalize()
self.joint=Joint:Slider(position.x,position.y,position.z,pin.x,pin.y,pin.z,self.entity,nil)
if self.openstate then
self.openangle=0
self.closedangle=self.distance:Length()
else
self.openangle=self.distance:Length()
self.closedangle=0
end
self.joint:EnableMotor()
self.joint:SetMotorSpeed(self.movespeed)
local e = self.entity:CountChildren()
for n=1,e do
--System:Print(n)
cl = n - 1
local c = self.entity:GetChild(cl)
--c:SetColor(1,1,1,0)
c:SetShadowMode(Light.Dynamic)
end
--This will move, so have the shadowmode dynamic.
self.entity:SetShadowMode(Light.Dynamic)
end
function Script:Toggle()--in
if self.enabled then
if self.openstate then
self:Close()
else
self:Open()
end
end
end
function Script:Open()--in
if self.enabled then
self.opentime = Time:GetCurrent()
if self.openstate==false then
if self.sound.open then
self.entity:EmitSound(self.sound.open)
end
self.joint:EnableMotor()
self.protector:Hide()
self.joint:SetAngle(self.openangle)
self.openstate=true
self.component:CallOutputs("Open")
if self.loopsource~=nil then
self.loopsource:SetPosition(self.entity:GetPosition(true))
if self.loopsource:GetState()==Source.Stopped then
self.loopsource:Play()
end
end
end
end
end
function Script:Close()--in
if self.enabled then
if self.openstate then
if self.sound.close then
self.entity:EmitSound(self.sound.close)
end
self.joint:EnableMotor()
self.joint:SetAngle(self.closedangle)
self.openstate=false
if self.loopsource~=nil then
self.loopsource:SetPosition(self.entity:GetPosition(true))
if self.loopsource:GetState()==Source.Stopped then
self.loopsource:Play()
end
end
self.component:CallOutputs("Close")
end
end
end
function Script:UpdatePhysics()
end
function Script:Disable()--in
self.enabled=false
self.joint:DisableMotor()
self.component:CallOutputs("Disable")
end
function Script:Enable()--in
self.enabled=true
self.joint:EnableMotor()
self.component:CallOutputs("Enable")
end
function Script:UpdatePhysics()
--Disable loop sound
local angle
if self.openstate then
angle = self.openangle
else
angle = self.closedangle
end
if math.abs(self.joint:GetAngle()-angle)<0.1 then
if self.sound.loop~=nil then
if self.loopsource:GetState()~=Source.Stopped then
self.loopsource:Stop()
end
end
if self.openstate==false then
if self.opened==true then
self.protector:Show()
self.component:CallOutputs("OnFullyClosed")
self.opened=false
self.entity:EmitSound(self.sound.stop02)
System:Print("Fully Closed")
end
else
if self.opened==false then
self.component:CallOutputs("OnFullyOpened")
System:Print("Fully Opened")
self.entity:EmitSound(self.sound.stop01)
self.opened=true
end
end
else
if self.sound.loop~=nil then
if self.loopsource:GetState()==Source.Stopped then
self.loopsource:Resume()
end
end
self.component:CallOutputs("onresume")
end
if self.sound.loop~=nil then
if self.loopsource:GetState()==Source.Playing then
self.loopsource:SetPosition(self.entity:GetPosition(true))
end
end
--Automatically close the door after a delay
if self.closedelay>0 then
if self.openstate then
local time = Time:GetCurrent()
if time-self.opentime>self.closedelay then
self:Close()
end
end
end
end
function Script:Release()
ReleaseTableObjects(self.sound)
if self.loopsource then
self.loopsource:Release()
self.loopsource=nil
end
self.sound=nil
end
Is there a better way of making a platform that updates physics and the player but does not react to heavy objects, or objects with momentum? I really don't want to take any shortcuts as I don't want any puzzles to be limited/gimped depending on platforms. If you need/want any more of my attempts/code, I'll happy supply it.
Thanks.