danidomen Posted February 13, 2018 Share Posted February 13, 2018 (edited) Hi, I have some switches and doors (SwingingDoors) that have Use function and calls to open or light up the rooms. But now I want that when my VR controller collide with the door or the light, first detect that I can "interact" with it (atm painting a Sphere...) and when I click on controller trigger, call to "Use" function of the collided entity (door or switch). Now, I replicated the code from FPSPlayer to interact with the E Key, and is "working" but is very awful I'm trying to write what I'm doing (very very very bad) on VRPlayer function Script:UpdateWorld() local pickInfo = PickInfo() --Usable object with Trigger Button: DANI if VR:GetControllerButtonDown(VR.Right,VR.TriggerButton)==true then local p0 = controller:GetPosition(true) local p1 = Transform:Point(0,0,self.useDistance,controller,nil) if self.entity.world:Pick(p0,p1, pickInfo, self.pickradius, true) then --Looks for any entity in the hierarchy that has a "Use" function local usableentity = self:FindUsableEntity(pickInfo.entity) if usableentity~=nil then --Use the object, whatever it may be usableentity.script:Use(self) end end end self.canUse = false pickInfo = PickInfo() local p0 = controller:GetPosition() local p1 = Transform:Point(self.useDistance,self.useDistance,self.useDistance,controller,nil) if self.entity.world:Pick(p0,p1, pickInfo, self.pickradius, true) then if self:FindUsableEntity(pickInfo.entity)~=nil then self.picksphere:SetPosition(pickInfo.position); self.canUse=true else local mass = pickInfo.entity:GetMass() if mass>0 and mass<=self.maxcarryweight then self.canUse = true end end else self.picksphere:SetPosition(0,0,0) end Edited February 20, 2018 by danidomen solved Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted February 14, 2018 Share Posted February 14, 2018 15 hours ago, danidomen said: But now I want that when my VR controller collide with the door or the light, You want your character controller to collide with the door in order to open it? Your code suggest that you use a pick function to interact with objects. 15 hours ago, danidomen said: Now, I replicated the code from FPSPlayer to interact with the E Key, and is "working" but is very awful Can you clarify what is working and what is not working. Do see anything that shouldn't happen. Error log? Perhaps a video recording? Quote Link to comment Share on other sites More sharing options...
danidomen Posted February 14, 2018 Author Share Posted February 14, 2018 Hi @AggrorJorn, Sure, here is the video. One half is with VR with the strange "pick" function to "use" the objects, and the other half of the video is with FPSPlayer and nice pick/use of switches and doors. Yes, I know that "pick" is not the way to do this on VR (the switch directly not detect nothing, also the ball is "printed" always on what is like the mass center of the controller and not when "collision" happens), but I don't find info explaining how the collision system works, or how detect collision at the controller with another object and "callback" to the Use function of the object. 1 Quote Link to comment Share on other sites More sharing options...
Josh Posted February 14, 2018 Share Posted February 14, 2018 If you look in the VR player script I set it up so you can pick up objects. I think I used the entity distance command to detect intersections between a point on the controller and the object. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted February 15, 2018 Share Posted February 15, 2018 Yep, you can find the code that does this in VRPlayer.lua: local mass = entity:GetMass() if mass>0 and mass<10 then local pos = self.currentcontroller:GetPosition(true) local d = entity:GetDistance(pos,true) if d <= self.grippadding then self.heldobject[self.currentcontrollerindex] = entity Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
danidomen Posted February 15, 2018 Author Share Posted February 15, 2018 Hi @Josh Fine, I created the functions understanding a bit more how you used to "grab" the objects. So I have writed this, and is a bit better, but the ball is stuck on the air on front of the "Use" entity, although the controller not touched when I move away the controller from the "Use" entity. I tried with a two "else" clausules but with not sucess because then the ball is never "positioned" (I supposed that is positioned but as fast that they never appear on screen because of the "else") function VRPlayer_TouchingItems(entity,extra) if entity==extra then return end local self = tolua.cast(extra,"Entity").script local mass = entity:GetMass() local pos = self.currentcontroller:GetPosition(true) local d = entity:GetDistance(pos,true) if d <= self.grippadding then local usableentity = self:FindUsableEntity(entity) if usableentity~=nil then if VR:GetControllerButtonHit(VR.Right,VR.TriggerButton)==true then usableentity.script:Use(self) else self.picksphere:SetPosition(pos); end else --With this next line, the ball never is "positioned" because this seems to be continuosly updated at ms frequency, so the above SetPosition is like nothing --self.picksphere:SetPosition(0,0,0); end else --Same with this next line, the ball never is "positioned" because this seems to be continuosly updated at ms frequency, so the above SetPosition is like nothing --self.picksphere:SetPosition(0,0,0); end if entity:CountVisibleChildren()>0 then local n for n=0,entity:CountChildren()-1 do VRPlayer_TouchingItems(entity:GetChild(n),extra) end end end function VRPlayer_IntersectingController(controller,extra) if controller~=nil then local aabb = AABB() aabb.min = controller:GetPosition(true) aabb.max = aabb.min aabb.min = aabb.min - Vec3(extra.grippadding) aabb.max = aabb.max + Vec3(extra.grippadding) aabb:Update() extra.currentcontroller = controller extra.currentcontrollerindex = n world:ForEachEntityInAABBDo(aabb,"VRPlayer_TouchingItems",extra.entity) end end function Script:UpdateWorld() local n for n=0,1 do local controller = VR:GetControllerModel(VR.Left+n) VRPlayer_IntersectingController(controller,self) end A LOT OF OTHER STUFF Quote Link to comment Share on other sites More sharing options...
danidomen Posted February 20, 2018 Author Share Posted February 20, 2018 Hi all! Well! I think that is the best "approach" I can do, and is near the perfect expected result, so I share with all the community how I made it (really is possible to write better code, but is my first try with Lua and with Leadwerks haha) On VRPlayer I made the following modifications: On the script variables declaration at the top: Script.pickradius=0.05 Script.hitBallTime=0 Script.hitBallDelay=50 Script.clickUsed=false Script.clickUseTime=0 Script.clickUseDelay=500 On the "Script:Start()" function, before the "--Create teleporter beam" comment add this function Script:Start() blablabla self.picksphere=Model:Sphere() self.picksphere:SetColor(1.0,0.0,0.0) self.picksphere:SetPickMode(0) self.picksphere:SetScale(self.pickradius*2.0) --Create teleporter beam blablabla Add this new function VRPlayer_TouchingItems function VRPlayer_TouchingItems(entity,extra) if entity==extra then return end local self = tolua.cast(extra,"Entity").script local mass = entity:GetMass() local time = Time:GetCurrent() if self.clickUsed == true and time-self.clickUseTime>self.clickUseDelay then self.clickUseTime = 0 self.clickUsed = false --This is needed to have control on not to make click so quickly (open/close/open/close the door because ButtonDown). Reason explained below end local pos = self.currentcontroller:GetPosition(true) local d = entity:GetDistance(pos,true) local usableentity = self:FindUsableEntity(entity) if d <= self.grippadding and usableentity~=nil then if VR:GetControllerButtonDown(VR.Right,VR.TriggerButton)==true then --Why use ButtonDown and not hit, is because a lot of times Hit is not reachable, so to "stop" on continuos clicking, i make this control if self.clickUsed == false then self.clickUsed = true self.clickUseTime = time usableentity.script:Use(self) end else self.hitBallTime = time self.picksphere:SetPosition(pos); end else if time-self.hitBallTime>self.hitBallDelay then self.picksphere:SetPosition(0,0,0); end end end Add this new function VRPlayer_IntersectingController function VRPlayer_IntersectingController(controller,extra) if controller~=nil then local aabb = AABB() aabb.min = controller:GetPosition(true) aabb.max = aabb.min aabb.min = aabb.min - Vec3(extra.grippadding) aabb.max = aabb.max + Vec3(extra.grippadding) aabb:Update() extra.currentcontroller = controller extra.currentcontrollerindex = n world:ForEachEntityInAABBDo(aabb,"VRPlayer_TouchingItems",extra.entity) end end On the "Script:UpdateWorld()" function, before the "----Check if teleporter is active and the button was released" comment add this function Script:UpdateWorld() local n for n=0,1 do local controller = VR:GetControllerModel(VR.Left+n) VRPlayer_IntersectingController(controller,self) end And last, taked from FPSPlayer, add this new function to VRPlayer script function Script:FindUsableEntity(entity) while entity~=nil do if entity.script then if type(entity.script.Use)=="function" then --If "enable" has not been set, it still won't be "false" so this will pass: if entity.script.enabled~=false then return entity else return nil end end end entity = entity:GetParent() end return nil end 1 Quote Link to comment Share on other sites More sharing options...
Maaco Posted April 13, 2018 Share Posted April 13, 2018 @danidomen: Thanks for sharing this: works perfect and has helped me a lot! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.