Jump to content
bansama

Problem with collisions

Recommended Posts

Reference: http://www.leadwerks.com/werkspace/topic/8462-how-to-pass-variables-between-scripts-lua/

 

As a follow on to what I was doing in the above topic, I notice that a later update to Leadwerks resulted in my solution breaking a bit. I'm now trying to find a better way to do things. But I have noticed some strange behaviour which I'd like to try and resolve.

 

The following is the basic collision script I am using:

 

Script.entered = false
Script.exited = false
Script.hadCollision = false

Script.Target = nil --entity
Script.Enabled = true --bool


function Script:UpdatePhysics()
if self.entered then
if self.hadCollision == false then
if self.exited == false then
self.exited = true
self.component:CallOutputs("OnExit")

		 -- command for enabling placed here

self.entered = false
end
end
end
self.hadCollision = false
end

function Script:Collision(entity, position, normal)
-- speed
self.hadCollision = true
self.component:CallOutputs("OnCollide")


if self.entered == false then
if self.Enabled == true then
self.component:CallOutputs("OnEnter")
self.entered = true
self.exited = false
end
end
end

 

The basic idea is that on detecting collision, the trigger activates and performs what I need it to do. In this case, it's a teleport. As such, it also needs to disable the script for the receiving end. But when entering the receiver a second time, it should allow the player to return to the original teleport.

 

My problem is, the script detects the player as "exiting" as soon as the player stops moving. Thus, the script activates when the player moves again (either when they walk, or change where they are facing).

 

This can cause a loop where the player rapidly moves from one pad to the other.

 

As such, I'm trying to find a good way to ensure the script only resets to its default active state when the player really does "exit" the entity the script is attached to.

 

The solution I thought of trying was to have an outer pad and an inner pad for both teleporters. These would be separate entities of course. Imagine something like:

 

<Pad a [Pad b]> <Pad c [Pad d]>

 

Pad a and c are the outer pads, these I would want to use to enable the scripts connected to Pad b and d respectively. Pad b and d are the actual teleports, they will move the player to the linked pad [b to d, d to b]. But these scripts need to disable themselves as soon as a teleport has finished.

 

The aim being that the player will not then re-teleport until they have actually left the pad (ie, made contact with pad a or c).

 

Could someone suggest a good way to do this?

 

I was thinking of importing the script attached to the teleport pad into the script attached to the outer pad, but could then not work out how to actually interact with the variables from the imported script.

 

All help and suggestions will be greatly appreciated!

Share this post


Link to post

Yeah, that's the script mine is based on. It has the same problem with it detecting an "exit" as soon as you stop moving even though you're still on the entity.

Share this post


Link to post

Could you not just make a switch which is near the teleporter that you have to press that turns the teleporter on. Afetr one use the switch is automatically set back to off. This might interrupt the flow of the game, depends what you are going for.

 

Another idea is to use Entity:GetDistance that will switch the teleporter back on when you have moved so far away.

Share this post


Link to post

Could you not just make a switch which is near the teleporter that you have to press that turns the teleporter on. Afetr one use the switch is automatically set back to off. This might interrupt the flow of the game, depends what you are going for.

 

Another idea is to use Entity:GetDistance that will switch the teleporter back on when you have moved so far away.

 

The first suggestion is not going to work, no. I am using the teleports as a way to move players around without their knowledge, so having them specifically hit a button isn't going to work in all situations.

 

The second idea might work, thanks. But again, I could use some help on how best to access variables from an imported script, as half the time I try, they cannot be found (I get the usual attempt to access nil value error).

Share this post


Link to post
My problem is, the script detects the player as "exiting" as soon as the player stops moving.

 

Really? I don't recall that happening at all. Are you saying when you get teleported and you move slightly but are still inside the trigger it'll say you've exited? If you don't move at all after teleportation does it do anything?

 

[EDIT]

 

You know what I recall doing. In my video I recall linking each teleporter via a script variable so that I can manipulate the other teleporters script variables because when you teleport over to the other one you have to set it's variable to prevent what you are talking about, and getting telported back. Did you watch the video because I think I go over that in there. I haven't watched it in some time but I recall having to do something like that. Linking each teleporter to each other, but I don't see that in your script.

Share this post


Link to post

Really? I don't recall that happening at all. Are you saying when you get teleported and you move slightly but are still inside the trigger it'll say you've exited? If you don't move at all after teleportation does it do anything?

 

Yep. The script acts as if an "exit" is detected when you stop moving and then move again. I.e., teleport and jump, etc. I can solve that by not allowing the script to enable itself, but that makes the teleport one-way. If I then move away from the teleport and re-enter, it won't send me back to the original teleport.

 

The script above is what I think I should work from for the outer pads (the ones I want to use to enable the teleports. The script I am using on each of the actual teleports is as follows:

 

Script.entered = false
Script.exited = false
Script.hadCollision = false

Script.Target = nil --entity
Script.Enabled = true --bool


function Script:UpdatePhysics()
   if self.entered then
       if self.hadCollision == false then
           if self.exited == false then
               self.exited = true
               self.component:CallOutputs("OnExit")
               --System:Print("Exited")
               --self.Enabled = true  ** this can also be self.Target.script.Enabled = true, doesn't matter it will have the same effect **
               self.entered = false
           end
       end
   end
   self.hadCollision = false
end

function Script:Collision(entity, position, normal)
-- speed
self.hadCollision = true
self.component:CallOutputs("OnCollide")
   if self.entered == false then
       if self.Enabled == true then
           self.component:CallOutputs("OnEnter")
           --System:Print("Entered")
           self.Target.script.Enabled = false
           --entity:SetPosition(self.Target:GetPosition()) -- Teleports
           if entity:GetKeyValue("name") == "Player" then
               EntPlayerCoord = entity:GetPosition():ToString()
               --System:Print("Player "..EntPlayerCoord)
               EntPadCoord = self.entity:GetPosition():ToString()
               --System:Print("Send Pad "..EntPadCoord)
               TarPadCoord = self.Target:GetPosition():ToString()
               --System:Print("Targ Pad "..TarPadCoord)
           end


           PlayerTable = split(EntPlayerCoord, ", ")
           --for key,value in ipairs(PlayerTable) do
           --    System:Print( key .. " has value " .. value)
           --end
           SendPadTable = split(EntPadCoord, ", ")
           --for key,value in ipairs(SendPadTable) do
           --    System:Print( key .. " has value " .. value)
           --end
           TarPadTable = split(TarPadCoord, ", ")
           --for key,value in ipairs(TarPadTable) do
           --    System:Print( key .. " has value " .. value)
           --end

           -- Will need to use checks like this
           -- to help cope with minus numbers, etc., when teleporting
           BaseValue = "0" -- Need to set this to avoid error
           if SendPadTable[1] < BaseValue then
           OffsetX = PlayerTable[1] - SendPadTable[1]
           --System:Print("LT X " .. OffsetX)
           end
           if SendPadTable[2] < BaseValue then
           OffsetY = PlayerTable[2] - SendPadTable[2]
           --OffsetYa = SendPadTable[2] + OffsetY
           --System:Print("LT Y " .. OffsetY)
           end
           if SendPadTable[3] < BaseValue then
           OffsetZ = PlayerTable[3] - SendPadTable[3]
           --System:Print("LT Z " .. OffsetZ)
           end

           if SendPadTable[1] >= BaseValue then
           OffsetX = PlayerTable[1] - SendPadTable[1]
           --System:Print("GT X " .. OffsetX)
           end
           if SendPadTable[2] >= BaseValue then
           OffsetY = PlayerTable[2] - SendPadTable[2]
           --OffsetYa = SendPadTable[2] + OffsetY
           --System:Print("GT Y " .. OffsetY)
           end
           if SendPadTable[3] >= BaseValue then
           OffsetZ = PlayerTable[3] - SendPadTable[3]
           --System:Print("GT Z " .. OffsetZ)
           end

           TargetX = TarPadTable[1] + OffsetX
           TargetY = TarPadTable[2] + OffsetY
           TargetZ = TarPadTable[3] + OffsetZ
           --System:Print ("XYZ: " .. TargetX .. ", " .. TargetY .. ", " .. TargetZ)
           entity:SetPosition(TargetX, TargetY, TargetZ)
       end

       self.entered = true
       self.exited = false
   end    
end



function split(s, delimiter)
   result = {}
   for match in (s..delimiter):gmatch("(.-)"..delimiter) do
    table.insert(result, match)
   end
   return result
end

 

Don't mind the system:prints, I just used those while coding to check what the script was doing. The section commented with ** is where enabling the teleport again is likely causing the problem. This is why I need to work out how best to enable the script again from a different entity. Does this make any sense?

Share this post


Link to post

So I took the script above and remove it to just be the below and it works fine for me. When I teleport and if I'm still touching the trigger I can move very small increments inside the trigger and stop and nothing happens. I then move out of the trigger and back in and I get teleported. I don't get what the problem is. In my example and what I did is make a pivot and set it as the player (collision type of character and physics mode of character controller, and attach the FPSPlayer.lua script to it). Are you doing something different maybe that's causing an issue?

 

Script.entered = false
Script.exited = false
Script.hadCollision = false

Script.Target = nil --entity
Script.Enabled = true --bool


function Script:UpdatePhysics()
       if self.entered then
               if self.hadCollision == false then
                       if self.exited == false then
                               self.exited = true

                               self.component:CallOutputs("OnExit")

                               self.Enabled = true

                               self.entered = false
                       end
               end
       end

       self.hadCollision = false
end

function Script:Collision(entity, position, normal)
-- speed
self.hadCollision = true
self.component:CallOutputs("OnCollide")

   if self.entered == false then
if self.Enabled == true then

self.component:CallOutputs("OnEnter")

           self.Target.script.Enabled = false

           entity:SetPosition(self.Target:GetPosition()) -- Teleports
end

       self.entered = true
self.exited = false
end     
end

Share this post


Link to post

So I took the script above and remove it to just be the below and it works fine for me. When I teleport and if I'm still touching the trigger I can move very small increments inside the trigger and stop and nothing happens. I then move out of the trigger and back in and I get teleported. I don't get what the problem is. In my example and what I did is make a pivot and set it as the player (collision type of character and physics mode of character controller, and attach the FPSPlayer.lua script to it). Are you doing something different maybe that's causing an issue?

 

Even with that stripped down script, the result is the same. The only difference is likely that I am using the default FPSPlayer.pfb. But that has the same Physics mode, Collision type, and script that you are adding to a pivot, so it shouldn't be acting any different. Have you tried your script using the FPSPlayer.pfb?

 

I've tried making a brand new map, using a pivot as the character and again, the same problem occurs.

 

Just in case, I've attached a rar of the new map I just knocked together, along with the script I attached.

_temp.rar

Share this post


Link to post

When I run your map I don't have any trigger objects. The scene only has:

 

Directional Light 2

Box 1

Pad 1

Pad 2

Pivot 2

Share this post


Link to post

When I run your map I don't have any trigger objects. The scene only has:

 

Directional Light 2

Box 1

Pad 1

Pad 2

Pivot 2

 

You probably need to add the included script to Pad 1 and Pad 2, linking to the other pad respectively. The forum was being a pain while I was trying to attach the files.

Share this post


Link to post

The script is attached to the pads but nothing is happening.

 

Note that what you are doing isn't exactly what I do in my video. In my video I have separate cylinder csg in the middle of the pads set to trigger that act as the collision and transporter and the pads are just for visual.

 

My advice is to follow my video linked above exactly and see if you see the issue. There might be something with collision callback when using scene vs trigger and moving/stopping. At least that is something for you try and test to keep debugging.

Share this post


Link to post

The way I would do this would be to default all teleporters to disabled.

 

Create a torus, make it a trigger object and give it an invisible material. Link the trigger collision to a CallOutputs("Enable") and use flowchart to tie it the teleporter so it can enable it.

 

When the collision on the teleporter is triggered also have the script disable the teleporter as standard.

 

This way the teleporters only work when you pass through the triggering torus first.

 

The only caveat is that the inside edge of the torus needs to be over one full character body distance away from the teleporters hit box so you don't get an activate and teleport trigger at the same time on leaving the teleporter.

Share this post


Link to post

@randomkeyhits As far as I know there is no torus csg, which is why I just use a cylinder in the center, but yes the rest of what you said is basically how I made it in the video.

 

@bansama I'm not sure if you watched my video but your map is not like what I did in the video so you might not get the same results. (It's failing to load the script let me reset it and try)

 

[EDIT]

OK, yes this happens now, but all I can tell you is if you follow what I have in my video it works. If you change the pads to trigger and raise them off the ground a little so it's not touching the ground then it works just fine. So something with scene collision and the player that causes the Collision() callback to be called differently than a trigger.

Share this post


Link to post

I have tried exactly as your video, making trigger objects on the pads and adding the script to the triggers. In that case nothing happens. That is, I collide with the trigger and don't teleport. If I add the script to the pads without the teleport, they work as long as their collision type is not trigger (but with the behaviour mentioned at the start of this topic). In short, the Trigger collision type is not working for me.

Share this post


Link to post

Note that I don't think your csg trigger can be touching anything. In your test scene if the pad is level with the ground setting to Trigger didn't work, but if I raised the pad so it's floating in air, it worked.

Share this post


Link to post

Note that I don't think your csg trigger can be touching anything. In your test scene if the pad is level with the ground setting to Trigger didn't work, but if I raised the pad so it's floating in air, it worked.

 

Yeah, I just found this. It only works if I make the trigger object really tall. Perhaps this is connected to the height of the player?

 

This now appears to be working again. I would still like to work out how to use a separate entity to toggle this though just in case something else breaks it again in the future (and it could probably be useful for other things too). That is, to be able to access the variable for enabling/disabling with an imported script. I think I have an idea of how to try this. I just need to wrap my head around self and local variables...

 

Thanks everyone for all the help and ideas thus far.

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...