Child Objects with Associated Bodies

Hi, all. I'm currently working on a project which involves a number of "Ship" objects which all share a large number of behaviors with one another. Each ship has four associated spawners (guns) which spawn different projectiles in similar, but not identical ways from ship to ship. I've encountered some odd behavior when trying to implement the latest projectile, however, and was hoping for a little elucidation on the matter.

Most of the projectiles spawned by the ships' spawners are to be completely detached from their respective spawners upon spawning, but one in particular is meant to be parented by its spawner, and move along with it (this behavior might seem a little odd, but I'm wishing to implement it this way so as to leverage the base Ship class' behaviors for all of its descendents). Unfortunately, when parenting the spawned projectile to its spawner, the projectile doesn't move along with it at a 1:1 ratio, but rather follows it incredibly slowly, in effect not being attached to its parent in any meaningful way at all. I've found that the forum threads, Creating a Laser and UseSelfAsParent Makes Spawner Move Twice as Fast seem to address the same problem, and removing the projectile's Body attribute does "resolve" the issue, but the fact remains that this projectile must have a Body in order to collide with its necessary colliders. I attempted to circumvent the issue by following the Passing Items from one Object to Another tutorial, and explicitly setting the parent of spawned objects, but this results in the same behavior.

Is there some trick to parenting objects with Body attributes that I'm unaware of, or do I really need to dispense with my universal spawner behavior and incorporate these projectiles as body parts of their associated ships? Thanks in advance.

Comments

  • Quick questions before going further:

    • do you need those projectiles to have a solid body? ie. you only need them to be solid if you want them to bounce off or push other bodies.
    • does setting them as non-solid help with your issue?
    • do you need the projectiles to have the spawner as parent (ie. move with it) or simply as owner? (both are set by the ChildList property, but they're actually independent, behavior-wise)
  • @iarwain, I don't need the projectiles to be solid, and they currently aren't, so that's apparently not the issue. I do need the projectiles to have the spawner as parent, though, because they're ideally meant to move along with it/share its space.

  • edited November 2019

    @zgcrowno I tried to replicate your issue but to no avail. I added this at the top of BounceAlt.ini:

    [Tank]
    TrackList       = CursorTrack
    Graphic         = @
    Texture         = ball.png
    Pivot           = center
    Spawner         = Cannon
    
    [Cannon]
    Object          = Shell # EmptyShell
    WaveSize        = 1
    WaveDelay       = 0.4
    ObjectSpeed     = (200, 0)
    UseSelfAsParent = true
    
    [Shell]
    Graphic         = @
    Pivot           = center
    Texture         = +.png
    LifeTime        = 10
    HSV             = (0, 0.8, 0.8) ~ (1, 0.9, 0.9)
    ChildList       = DebugDisplay
    Body            = @
    PartList        = @
    Dynamic         = true
    CustomGravity   = (0, 0)
    Inertia         = 1
    Solid           = true
    Type            = sphere
    Friction        = 1
    SelfFlags       = Ball
    CheckMask       = Wall
    
    [EmptyShell@Shell]
    Texture         = o.png
    Solid           = false
    
    [DebugDisplay]
    Graphic         = @
    Text            = @
    String          =
    Pivot           = top
    IgnoreFromParent= position.rotation rotation
    Position        = (0, 20)
    TrackList       = DebugTrack
    
    [DebugTrack]
    0               = > Object.GetParent ^, > Object.GetSpeed <, Object.SetText ^ <
    Loop            = true
    
    [CursorTrack]
    0               = > Mouse.GetPosition, > Render.GetWorldPosition <, Object.SetPosition ^ <
    Loop            = True
    

    Then, after starting orx, I'd open the console and execute object.create Tank.
    Now by moving the mouse, you'd move the tank and its weapon (spawner) as well as some of the projects that are solid and some that aren't. Everything behave as expected for me.

    Would you be able to zip a small repro case of your issue for me to investigate?

  • @iarwain, I actually managed to recreate the issue by modifying your posted config ever so slightly:

    [Tank]
    TrackList       = CursorTrack
    Graphic         = @
    Texture         = ball.png
    Pivot           = center
    Spawner         = Cannon
    Body            = @
    PartList        = @
    Dynamic           = true
    FixedRotation     = true
    CustomGravity     = (0, 0)
    Type              = sphere
    SelfFlags         = Tank
    CheckMask         = Wall
    
    [Cannon]
    Object          = Shell # EmptyShell
    WaveSize        = 1
    WaveDelay       = 0.4
    ObjectSpeed     = (0, 0)
    UseSelfAsParent = true
    
    [Shell]
    Graphic         = @
    Pivot           = center
    Texture         = +.png
    LifeTime        = 10
    HSV             = (0, 0.8, 0.8) ~ (1, 0.9, 0.9)
    ChildList       = DebugDisplay
    Body            = @
    PartList        = @
    Dynamic         = true
    CustomGravity   = (0, 0)
    Inertia         = 1
    Solid           = true
    Type            = sphere
    Friction        = 1
    SelfFlags       = Ball
    CheckMask       = Wall
    
    [EmptyShell@Shell]
    Texture         = o.png
    Solid           = false
    
    [DebugDisplay]
    Graphic         = @
    Text            = @
    String          =
    Pivot           = top
    IgnoreFromParent= position.rotation rotation
    Position        = (0, 20)
    TrackList       = DebugTrack
    
    [DebugTrack]
    0               = > Object.GetParent ^, > Object.GetSpeed <, Object.SetText ^ <
    Loop            = true
    
    [CursorTrack]
    0               = > Object.SetSpeed < (200, -200, 0)
    Loop            = true
    

    Basically, all that's changed is that the CursorTrack model sets speed instead of position, The Cannon model's ObjectSpeed is (0, 0) instead of (200, 0), and the Tank model has Body and BodyPart attributes. This is the exact behavior I've been wrestling with. Thanks for taking a look!

  • The CursorTrack is invalid, I guess you meant Object.SetSpeed ^ (200, -200) ? I'll give it a try.

  • Ah, sorry about that. I haven't done hardly any work with the command module yet.

  • edited November 2019

    No worries. I narrowed the issue down to "one of the parents has a body", no matter if they have parts or not. I'll try to debug this over the weekend and will let you know what I find.
    The physics simulation is fiddly and doesn't like this kind of parenting from the outside forced onto itself.

  • Awesome. Thanks for all your time, @iarwain!

  • My pleasure!

    So, I found the issue and it's actually somewhat familiar but it's been over 5 years since I touched this code and I forgot most of the details.

    The issue at hand is that, in the case of objects directly moved by orx (either with SetPosition or SetSpeed when they don't have a body), the changes are processed individually before the physics simulation.
    In the case of objects moved by a speed (with a body)/force/impulse they'll be updated by the physics simulation, at the same time as your children.
    In this case, the children's physics simulation will not use the up-to-date values from their parents as those are also unknown at that time.
    At the moment, I don't have any fix, so your best option is to not have object with bodies that have parents with bodies as well. I'll try to test an idea I have and will let you know how it goes, but don't get your hopes up, it's not one of the most robust features as the physics simulation itself wasn't created with parenting (as in sub-spaces, like in orx itself) in mind.

  • That's what I was afraid of. Obviously, it'd be great if I could parent largely "indiscriminately", but I can always adopt a method of designating body-less parents, of which only the furthest descended children are bodied.

  • Hi @zgcrowno. I've tried a couple of things but unfortunately none of them were able to cover all the possible cases or body/non-body parenting.

    I think I'll put this on hold for now and will pick it up if I get any new ideas. I'll add a warning message in debug when a child with body is set as being child/grand-child of another object with body to help people diagnose their issue.
    I'm afraid that's the best I can do at the moment, sorry!

  • edited November 2019

    No worries, @iarwain. I'm sure this is a tricky issue. I did have a question, though: Is this problem one that may be solved with joints? I'm thinking specifically of this tutorial.

  • I've actually managed to get the behavior I need by using weld joint couplings down the hierarchy, as this seems to be the most manageable approach for my use case. Any projectile which is to be parented by its spawner simply constructs a joint between itself and its spawner's owning object at creation. The only real tricky part of this process was realizing that any child object which is joined to its parent by a joint must not have the FixedRotation attribute of its Body set to true, as that seemingly "breaks" the joint, disallowing simultaneous movement between parent and child. Regardless, it's working now, and in a way that doesn't seem like I'm grossly abusing the systems at play!

  • I'm glad you got it working, and yes, to answer your question (a bit too late!), joints can be used as long as they allow you to express your needs in a satisfactory way.
    In the eventuality you're not spawning your child objects overtime but upong creation, you could also specify the joints in config instead.

Sign In or Register to comment.