Jump to content
Haydenmango

Inherited Parent Object Shape (Help)

Recommended Posts

So I have a player and a weapon. I pickup the weapon by parenting it to my entity. I drop the weapon by calling weaponentity:SetParent(nil) and then it drops like it should.

 

My problem is that the weapons collision shape doesn't change back to normal when it drops. I imagine that it keeps the shape it inherited from its parent. It is hard to describe so I added a video to show what's going on.

If anyone knows what I can do to fix this let me know. I have tried to change the weapons shape back to its original shape when it is dropped but that hasn't worked.

 

--video

 

https://www.youtube.com/watch?v=woqWma6JJUQ

Share this post


Link to post

Changing my weapons shape was what I thought would fix this problem but it doesn't.

 

My issue still occurs whether I change my weapons shape or not.

 

Here is my code so you may understand what is happening--

--pickup code

if window:KeyHit(Key.G) then
if (App.world:Pick(self.camera:GetPosition(),Transform:Point(0,0,self.useDistance,self.camera,nil),pickInfo,0,true)) then
if pickInfo.entity.script then
if pickInfo.entity.script.weapon then
 if self.carryingEntity==nil and self.weapon~="torch" then
 if self.weaponentity~=nil then
 self.weaponentity.script:Drop()
 end
 self.weaponentity=pickInfo.entity
 self.weapon=self.weaponentity.script.name
 self.weaponentity:SetShape(nil) --you can comment this out and the problem still occurs
 self.weaponentity:SetMass(0)
 self.weaponentity:SetCollisionType(Collision.None)
 self.weaponentity:SetPosition(self.palm:GetPosition(true))
 self.weaponentity:SetRotation(self.palm:GetRotation(true)+self.weaponentity.script.rotation)
 self.weaponentity:SetParent(self.palm)
 self.weaponentity:SetShadowMode(0)
 end
 end
end
end
end

--drop code

function Script:Start()
self.shape=self.entity:GetShape()
self.shape:AddRef()
end

function Script:Drop()
self.entity:SetParent(nil)
self.entity:SetShape(self.shape) --you can comment this out and the problem still occurs
self.entity:SetMass(self.mass)
self.entity:SetCollisionType(Collision.Prop)
self.entity:SetShadowMode(1)
end

Share this post


Link to post

No need to call SetShape, using setCollision to "none" or "prop" should work, i would just put the weapon at some distance from hand when dropping it to avoid collision problems. That's strange caus it worked on your video for the first stick, it

 

What you could do :

-Avoid calling SetShape and AddRef in start functions, just duplicate the sticks in the level editor and would just call SetCollision "none" or "prop" only when picking or dropping a stick.

- Instead of suing SetParent, try each update frame to position and rotate thane stick by code to self.palm.

- You don't need to call SetMass(0) as you have SetCollision(0) perhaps, and using setPosition and SetRotation each frame will override any physic beahviour

 

Make it simple.

Share this post


Link to post

I don't think you understand. I just said it doesn't even work when I don't mess with my weapons shape.

My issue still occurs whether I change my weapons shape or not.

 

And in my video the problem occurs once the weapon is dropped. Once my weapon is dropped it has some sort of extended collision shape as you can see in the video. So no it did not work for the first stick in my video.

 

In case you still don't get the shape part this is what my original code was(this was the code used in the video)--

--pickup code

if window:KeyHit(Key.G) then
if (App.world:Pick(self.camera:GetPosition(),Transform:Point(0,0,self.useDistance,self.camera,nil),pickInfo,0,true)) then
if pickInfo.entity.script then
if pickInfo.entity.script.weapon then
	 if self.carryingEntity==nil and self.weapon~="torch" then
	 if self.weaponentity~=nil then
	 self.weaponentity.script:Drop()
	 end
	 self.weaponentity=pickInfo.entity
	 self.weapon=self.weaponentity.script.name
	 self.weaponentity:SetMass(0)
	 self.weaponentity:SetCollisionType(Collision.None)
	 self.weaponentity:SetPosition(self.palm:GetPosition(true))
	 self.weaponentity:SetRotation(self.palm:GetRotation(true)+self.weaponentity.script.rotation)
	 self.weaponentity:SetParent(self.palm)
	 self.weaponentity:SetShadowMode(0)
	 end
	 end
end
end
end

--drop code

function Script:Drop()
self.entity:SetParent(nil)
self.entity:SetMass(self.mass)
self.entity:SetCollisionType(Collision.Prop)
self.entity:SetShadowMode(1)
end

 

This results in the same issue shown in my video.

Share this post


Link to post

I was really hoping I wouldn't have to do this--

- Instead of suing SetParent, try each update frame to position and rotate thane stick by code to self.palm.

but it is the only thing I have tried that fixes the problem.

 

Is there really no way to get rid of the shape my weapon inherits from its parent?? Is this intended behaviour or am I missing something? Things would be much more simple if I could just use SetParent() instead of constantly checking if my weapon is being held then constantly moving it if it is.

Share this post


Link to post

Using SetParent, is just coding less, but behind the scene, it just calls the same code : SetPosition and SetRotation if im' not wrong.

So i would go that way calling SetPosition and SetRotation and not using SetParent, you won't gain or loose performance.

For the collision shape problem, i don't knwo as i didn"t had that problem and didn't has to change or use Shape functions as models was imported and dropped in the editor only without needind to change shape, so i can't help you on these specific parts.

Share this post


Link to post

That would work but I have lots of weapons all over my map. If I don't use SetParent() then each one of those weapons is going to need an UpdateWorld() function which means all of those weapons will be constantly looping through that function to check if they are "active" rather than just being turned on and off when they are being used. I think that is where I will lose performance.

 

Oh well though... for now I may have to do it manually instead of using SetParent(). It is just such a bummer because it seems like it wouldn't be impossible to set an objects shape back to normal after its parent is cleared. Thanks for the help/suggestions by the way Yougroove.

Share this post


Link to post

No need to place this code in all weapons UpdateWorld() functions. In your player script make a variable that will hold a weapon like self.weapon. When you pick a weapon set that picked entity to this entity variable so that now your player script has a "pointer" to that entity via self.weapon. Then inside your player UpdateWorld() you set position/rotation to that self.weapon entity. When you drop the weapon just set the self.weapon to nil. In your UpdateWorld() you'll see if self.weapon is nil or not and if not then set position/rotation else do nothing with it.

Share this post


Link to post

Very true. I just came to that solution a few minutes ago as well. I still don't like this though(moving my weapons manually doesn't work well with my animations and it looks really choppy). dry.png I wish someone could confirm whether this is just how the engine works or if I am missing a function to correct my mistakes.

When you have a parented entity and set its parent to nil it shouldn't keep the characteristics of its previous parent.... or should it?

 

edit- When I search around for more information about SetParent() it only says

This function can be used to parent one entity to another. A child entity will maintain the same local orientation when its parent moves.
so SetParent() should only change the orientation of the entity. It seems SetParent() isn't well documented or bugged because my child entity is also inheriting its parents Physics Shape.

Share this post


Link to post

So make a small little test scene showing this and attach it to a bug report post.

Share this post


Link to post

Will do. Just making sure I wasn't missing anything obvious before I post a bug report.

 

--edit for now I found a fix. still posting a bug report as it doesn't solve the actual issue.

function Script:Drop()
self.entity:SetParent(nil)
self.entity:SetMass(self.mass)
self.entity:SetCollisionType(Collision.Prop)
self.entity:SetShadowMode(1)
local spawn=self.entity:Instance()
spawn:SetPosition(Transform:Point(0,0,1,self.entity,nil))
self.entity:Release()
end

Share this post


Link to post

Is this part of each weapon?

 

Generally you don't release self.entity ever as it's a special variable that LE fills in, but since this is a little snippet I'm not sure why you are doing that.

Share this post


Link to post

No it is the whole weapon. ohmy.png I happen to do self.entity:Release() quite often and I thought it worked. What would be the proper way to release/destroy an entity then?

Share this post


Link to post

Well that's the thing, self.entity is a special variable that the LE engine fills in before the scripts Start() function is called (probably during map load) and then it sets it to the entity/model that the script is attached too. Why do you want to release it? If I'm dropping the thing back into the world I would assume you would still want the entity in the world and have it's script work so you can pick it up later?

 

Now I see above you spawn an instance of this entity, but why do that? I'm confused as I would think you pick up the entity then you drop the same entity. Why make an instance and release self.entity?

Share this post


Link to post

Well that ties into the actual issue I posted about. The code above was my workaround to get rid of the physics shape my "dropped weapon" inherited from its parent. Creating an Instance of the "dropped weapon" got rid of the unwanted physics shape. I then release the "dropped weapon" so that the instance of it I created pretty much replaces it.

 

So in this case I do not want the entity back into the world because it has its parents physics shape which I do not want it to have. I had to create a instance of the entity (which magically gets rid of the unwanted physics shape) to fix my issue.

Share this post


Link to post

Are you able to re-pick up the weapon and have the script work? I would suspect releasing self.entity would screw up the script. Perhaps Instance() makes another instance of the script attached to it too?

Share this post


Link to post

Yes it works as it should when instanced. I believe instance seems to copy the entites script as well as the changes made to it.

If you have a script like-

Script.health=80

then your entity dies because its health reaches 0 and you want to respawn it-

self.entity:Instance()

self.entity:Release()

this would create another dead entity because its Script.health is still equal to 0 which would then loop this death code and probably crash the game. you would need to do this-

local spawn=self.entity:Instance()

spawn.script.health=80

self.entity:Release()

now your instance will spawn with 80 health. You also need to set the instances position I believe.

That is how I have been releasing and respawning entities so far.

Share this post


Link to post

Cool. I've always just called Load() which if it's already available will make an instance (of course you need the model/prefab name for that). This will create a fresh script with all the default values.

 

In the Instance() way you could probably call self.entity.script:Start() manually and if you have your init code in there it'll reset everything to what it should be as a fresh instance. However if you init variables at the top of the script outside Start() then this probably wouldn't work.

Share this post


Link to post

I think it carries over the init variables at the top as well! Almost all of my entities load through Instance() after my game initially starts and I noticed that you do have to call spawn.script:Start() when the entity is instanced because that will not run otherwise but other than that everything (in the entities script) seems to carry over.

 

A cool trick for respawn time is to Hide() the dieing entity and then wait a set amount of "respawntime" then call a custom Death() function that Instances your dieing entity, reset the script values(for the instanced entity), Show() the instanced entity, and release the dieing entity.

Share this post


Link to post

That seems like a good idea when you want to keep the same amount of "things" in the world. In my bomb killer game I've created a spawner script to keep pumping out bombs at a given rate, at 1 of x random locations (defined by pivots) with a max count of y. Your method would be perfect for like MMO type games where you have respawns.

 

What are you respawning (besides the weapons)? Animals?

Share this post


Link to post

Using Instance() I respawn my animals and weapons so far. It works great for my open world survival game!

Simply hiding objects when they die and then switching their location and showing them when they respawn seems to work in most cases but I instance my animals because they go through a complex script that would be hard to reset by Hiding and repositioning them.

Share this post


Link to post
Very true. I just came to that solution a few minutes ago as well. I still don't like this though(moving my weapons manually doesn't work well with my animations and it looks really choppy). dry.png I wish someone could confirm whether this is just how the engine works or if I am missing a function to correct my mistakes.

 

This is generally how you attach clothes, weapons to character bones generally in other engines also.

Or sometimes they have a general function call, but that finally call the same position/rotation code behind the scene.

It's up to you to create for each weapon script specific values to adjust their position and rotation to player hand : position offset adjustement and rotation offset adjustement.

Here is pseudo code :

 

WeaponStick.lua

start()
PosOffsetX = 0.2
RotOffsetX = 0.5
end

 

Player.lua

-- function called by updateWorld()
function : placeWeapons( weaponsLeft, weaponRight)

rot = hand:getRotation()
finalRotX = rotX + weaponsLeft.script.rotOffsetX
pos = hand:getPosition()
finalPosX = posX + weaponsLeft.script.posOffsetX
weaponsLeft:SetRotation(finalRot)
weaponsLeft:SetPosition(finalPos)

--- (same code for weaponRight)

-- return into player updateWorld() function
end


 

I don't knwo if you understand the code, but it's one way of doing it.

 

The best way to adjust weapons offsets in rotation and position :

Place a pivot on each weapon as child, the pivot should be positionned in a way it will make the weapon perfectly fit into the player hand. So by code you retrieve the pivot position and just call SetPosition to move it to the hand position, no need ot use offsets as the invisible pivot is done for that.

 

A good tutorial on attaching different weapons (+ pivot offsets) is really lacking in LE3, if i have time i'll make one.

Share this post


Link to post

Yeah if I worked on it I could make my weapon system use that type of method. Using a pivot as a placeholder could be a very good idea as well. Anyways I look forward to seeing your video if you decide to make one.

Share this post


Link to post

I will make a playable demo instead if i have time, but nothing new, as it will be simply using a pivot on each object for the best placement in the player hand.

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...