Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Extend a rope when the attached object shot from a position
#1
Basically I have a rope and I attached a Sphere on it with colliders and rigidbody on the end.

I want to shot it with the rigidbody's addForce with the red line angle. But in this time I want to increase the rope's length.

[Image: Screenshot-1.png]



What is the correct way to to this?
Reply
#2
(19-09-2022, 01:08 PM)lacasrac Wrote: Basically I have a rope and I attached a Sphere on it with colliders and rigidbody on the end.

I want to shot it with the rigidbody's addForce with the red line angle. But in this time I want to increase the rope's length.

[Image: Screenshot-1.png]



What is the correct way to to this?

Hi there,

Depends on what you want to do exactly. Do you want the rope to be simulated as the rigidbody flies around, you can measure the distance between the point where the rope is shot from and call cursor.ChangeLength() (see: http://obi.virtualmethodstudio.com/manua...ursor.html)

Or, if you want the rope to be a straight line that follows the rigidbody and starts simulating once the rigidbody hits something, you can use the technique shown in the "RopeGrapplingHook" sample scene.

kind regards,
Reply
#3
(20-09-2022, 09:58 AM)josemendez Wrote: Hi there,

Depends on what you want to do exactly. Do you want the rope to be simulated as the rigidbody flies around, you can measure the distance between the point where the rope is shot from and call cursor.ChangeLength() (see: http://obi.virtualmethodstudio.com/manua...ursor.html)

Or, if you want the rope to be a straight line that follows the rigidbody and starts simulating once the rigidbody hits something, you can use the technique shown in the "RopeGrapplingHook" sample scene.

kind regards,


Thanks, basically the RopeGrapplingHook working.
But I have more probleme:

When the rope attached to the floor (reached the floor at the bottom) I need to attach the rope last particle to my ragdoll leg.
How is it possible? After I attached to the leg I just keep the rest of the code. So add invMass to 10 and just change the length currLen--

I tried that with a fixed joint but with no luck. The fixed joint not stable at all.

Thanks
Reply
#4
(25-09-2022, 07:49 AM)lacasrac Wrote: Thanks, basically the RopeGrapplingHook working.
But I have more probleme:

When the rope attached to the floor (reached the floor at the bottom) I need to attach the rope last particle to my ragdoll leg.
How is it possible? After I attached to the leg I just keep the rest of the code. So add invMass to 10 and just change the length currLen--

I tried that with a fixed joint but with no luck. The fixed joint not stable at all.

Thanks

Attaching to a rag doll leg is no different from attaching to any other object: use a dynamic particle attachment. See:
http://obi.virtualmethodstudio.com/manua...ments.html

If the rope intersects the leg, take special care to ensure the rope is not colliding against it, otherwise instabilities will arise as the rope is simultaneously told to be inside and outside the leg collider. This is described in the above link, in the "Attachments inside colliders" section.

kind regards,
Reply
#5
(27-09-2022, 08:05 AM)josemendez Wrote: Attaching to a rag doll leg is no different from attaching to any other object: use a dynamic particle attachment. See:
http://obi.virtualmethodstudio.com/manua...ments.html

If the rope intersects the leg, take special care to ensure the rope is not colliding against it, otherwise instabilities will arise as the rope is simultaneously told to be inside and outside the leg collider. This is described in the above link, in the "Attachments inside colliders" section.

kind regards,


Here is my updated code, came after the floor reached the floor

Code:
private ObiParticleAttachment _lastAttachment;
private GameObject _lastAttachmentGo;

  public void AddNewControlPoint(Transform t, GameObject ropeEnd) {
            if (_lastAttachmentGo == null) {
                _lastAttachmentGo = t.gameObject;
               
                ropeEnd.GetComponent<CapsuleCollider>().enabled = false;

                var coll = _lastAttachmentGo.AddComponent<ObiCollider>();
                if (collideWithEverything)
                    coll.Filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
                else
                    coll.Filter = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);

                var pos = new Position();
                pos.Transform = t;
                pos.AttachmentType = ObiParticleAttachment.AttachmentType.Dynamic; 
                positions.Add(pos);

                var i = positions.Count - 1;

                var p = positions[i].Transform.position;

                var startPositionLS = transform.InverseTransformPoint(p);
                var tangentLS = Vector3.down;

                if (i + 1 < positions.Count)
                {
                    var nextP = positions[i + 1].Transform.position;
                    var endPositionLS = transform.InverseTransformPoint(nextP);
                    tangentLS = (endPositionLS - startPositionLS).normalized;
                }

                var filter = 1;
                if (collideWithEverything)
                    filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
                    //CollideWithNothing
                else
                    filter = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);

                var blueprint = rope.ropeBlueprint;

                blueprint.path.AddControlPoint(startPositionLS, -tangentLS, tangentLS, Vector3.up, mass,
                    mass, 1,
                    filter, Color.white, "ctrl_" + i);

                blueprint.path.FlushEvents();
                blueprint.GenerateImmediate();

                rope.ropeBlueprint = blueprint;

                //               
                Debug.Log("AddNewControlPoint i " + i + " " + positions.Count);
                _lastAttachment = gameObject.AddComponent<ObiParticleAttachment>();
                _lastAttachment.target = positions[i].Transform;
                _lastAttachment.attachmentType = positions[i].AttachmentType;
                _lastAttachment.particleGroup = blueprint.groups[i];
            }
        }



Transform t is the ragdoll leg. RopeEnd is just for visualization

collideWithEverything is always false

What is the probleme here? The rope jumping back again
Reply
#6
(27-09-2022, 11:30 AM)lacasrac Wrote: Here is my updated code, came after the floor reached the floor

Code:
private ObiParticleAttachment _lastAttachment;
private GameObject _lastAttachmentGo;

  public void AddNewControlPoint(Transform t, GameObject ropeEnd) {
            if (_lastAttachmentGo == null) {
                _lastAttachmentGo = t.gameObject;
               
                ropeEnd.GetComponent<CapsuleCollider>().enabled = false;

                var coll = _lastAttachmentGo.AddComponent<ObiCollider>();
                if (collideWithEverything)
                    coll.Filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
                else
                    coll.Filter = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);

                var pos = new Position();
                pos.Transform = t;
                pos.AttachmentType = ObiParticleAttachment.AttachmentType.Dynamic; 
                positions.Add(pos);

                var i = positions.Count - 1;

                var p = positions[i].Transform.position;

                var startPositionLS = transform.InverseTransformPoint(p);
                var tangentLS = Vector3.down;

                if (i + 1 < positions.Count)
                {
                    var nextP = positions[i + 1].Transform.position;
                    var endPositionLS = transform.InverseTransformPoint(nextP);
                    tangentLS = (endPositionLS - startPositionLS).normalized;
                }

                var filter = 1;
                if (collideWithEverything)
                    filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
                    //CollideWithNothing
                else
                    filter = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);

                var blueprint = rope.ropeBlueprint;

                blueprint.path.AddControlPoint(startPositionLS, -tangentLS, tangentLS, Vector3.up, mass,
                    mass, 1,
                    filter, Color.white, "ctrl_" + i);

                blueprint.path.FlushEvents();
                blueprint.GenerateImmediate();

                rope.ropeBlueprint = blueprint;

                //               
                Debug.Log("AddNewControlPoint i " + i + " " + positions.Count);
                _lastAttachment = gameObject.AddComponent<ObiParticleAttachment>();
                _lastAttachment.target = positions[i].Transform;
                _lastAttachment.attachmentType = positions[i].AttachmentType;
                _lastAttachment.particleGroup = blueprint.groups[i];
            }
        }



Transform t is the ragdoll leg. RopeEnd is just for visualization

collideWithEverything is always false

What is the probleme here? The rope jumping back again

Hi,

I don't see any obvious issues with your code. When are you calling AddNewControlPoint()? Its name suggests that you're adding new control points to the blueprint at runtime, which isn't the intended use case. Blueprints are generated once and used to generate one (or more) ropes, setting the blueprint of a rope will essentially destroy the rope and re-create it from scratch using the particle and constraint data contained in the blueprint. This will make your rope "jump" to a new position and shape.

If you want to change the length of a rope at runtime, you should use cursor.ChangeLength().
Reply
#7
(28-09-2022, 07:19 AM)josemendez Wrote: Hi,

I don't see any obvious issues with your code. When are you calling AddNewControlPoint()? Its name suggests that you're adding new control points to the blueprint at runtime, which isn't the intended use case. Blueprints are generated once and used to generate one (or more) ropes, setting the blueprint of a rope will essentially destroy the rope and re-create it from scratch using the particle and constraint data contained in the blueprint. This will make your rope "jump" to a new position and shape.

If you want to change the length of a rope at runtime, you should use cursor.ChangeLength().

This is the order:

0, I have 2 controlpoints and a rope blueprint by default 
1, raycast from the origin to the player
2, increase the rope length until reach the player with ChangeLength + update their positions, set invMass 0
3, AddNewControlPoint on the player's leg transform
4, pull up the player with the rope: invMass set Back to 10, and changeLength decrease
5, after 2 seconds I need to detach the last control point, so remove that last control point (DeleteLastControlpoint)

What is the good ordering on this? Is it possible to detach the rope after attached to something?

I need to add the last point in runtime and then just delete it...
Reply
#8
(28-09-2022, 09:16 AM)lacasrac Wrote: This is the order:

0, I have 2 controlpoints and a rope blueprint by default 
1, raycast from the origin to the player
2, increase the rope length until reach the player with ChangeLength + update their positions, set invMass 0
3, AddNewControlPoint on the player's leg transform
4, pull up the player with the rope: invMass set Back to 10, and changeLength decrease
5, after 2 seconds I need to detach the last control point, so remove that last control point (DeleteLastControlpoint)

What is the good ordering on this? Is it possible to detach the rope after attached to something?

I don't see why you would need to add or remove control points at runtime, I think you're misunderstanding the core concept of blueprints. Their only purpose is to specify the initial shape of the rope and particle placement/count at the start, that's it. Once the rope is created and the simulation starts, the blueprint (and the control points) basically stop being used, you're only concerned about particles then. If you wish to add or remove attachments, you can just create/destroy new ObiParticleAttachment components. If you wish to change the length of the rope, you use a cursor.

You don't need to create or destroy control points to create attachments, control points have nothing to do with attachments whatsoever. An attachment is a component that takes a particle group and attaches it to an object. You can simply destroy the attachment to remove it (or even just disable it), you don't need to add or destroy control points in the blueprint.

Note that attachments take a particle group as input, not a control point. Even though the blueprint will create a particle group for each control point for convenience, you can create your own particle groups at runtime since they're just a scriptable object.
Reply
#9
(28-09-2022, 12:33 PM)josemendez Wrote: I don't see why you would need to add or remove control points at runtime, I think you're misunderstanding the core concept of blueprints. Their only purpose is to specify the initial shape of the rope and particle placement/count at the start, that's it. Once the rope is created and the simulation starts, the blueprint (and the control points) basically stop being used, you're only concerned about particles then. If you wish to add or remove attachments, you can just create/destroy new ObiParticleAttachment components. If you wish to change the length of the rope, you use a cursor.

You don't need to create or destroy control points to create attachments, control points have nothing to do with attachments whatsoever. An attachment is a component that takes a particle group and attaches it to an object. You can simply destroy the attachment to remove it (or even just disable it), you don't need to add or destroy control points in the blueprint.

Note that attachments take a particle group as input, not a control point. Even though the blueprint will create a particle group for each control point for convenience, you can create your own particle groups at runtime since they're just a scriptable object.

I tried that with this code

Code:
                ObiParticleGroup group = ScriptableObject.CreateInstance<ObiParticleGroup>();
                group.SetSourceBlueprint(rope.blueprint);
                group.name = "last_one";
                _lastAttachment.particleGroup = group;


but with no luck

ArgumentNullException: Value cannot be null.
Obi.ObiNativeList`1[T].CopyFrom (Obi.ObiNativeList`1[T] source, System.Int32 sourceIndex, System.Int32 destIndex, System.Int32 length) (at Assets/Obi/Scripts/Common/DataStructures/NativeList/ObiNativeList.cs:253)
Obi.ObiPinConstraintsBatch.Merge (Obi.ObiActor actor, Obi.IObiConstraintsBatch other) (at Assets/Obi/Scripts/Common/Blueprints/Constraints/Batches/ObiPinConstraintsBatch.cs:114)
Obi.ObiConstraints`1[T].Merge (Obi.ObiActor actor, Obi.IObiConstraints other) (at Assets/Obi/Scripts/Common/Blueprints/Constraints/ObiConstraints.cs:55)
Obi.ObiSolver.PushConstraints () (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1389)
Obi.ObiSolver.BeginStep (System.Single stepTime) (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1518)
Obi.ObiUpdater.BeginStep (System.Single stepDeltaTime) (at Assets/Obi/Scripts/Common/Updaters/ObiUpdater.cs:63)
Obi.ObiFixedUpdater.FixedUpdate () (at Assets/Obi/Scripts/Common/Updaters/ObiFixedUpdater.cs:46)

Can you share a working example? I cannot find anything in the samples...
Reply
#10
(29-09-2022, 10:08 AM)lacasrac Wrote: I tried that with this code

Code:
                ObiParticleGroup group = ScriptableObject.CreateInstance<ObiParticleGroup>();
                group.SetSourceBlueprint(rope.blueprint);
                group.name = "last_one";
                _lastAttachment.particleGroup = group;


but with no luck

ArgumentNullException: Value cannot be null.
Obi.ObiNativeList`1[T].CopyFrom (Obi.ObiNativeList`1[T] source, System.Int32 sourceIndex, System.Int32 destIndex, System.Int32 length) (at Assets/Obi/Scripts/Common/DataStructures/NativeList/ObiNativeList.cs:253)
Obi.ObiPinConstraintsBatch.Merge (Obi.ObiActor actor, Obi.IObiConstraintsBatch other) (at Assets/Obi/Scripts/Common/Blueprints/Constraints/Batches/ObiPinConstraintsBatch.cs:114)
Obi.ObiConstraints`1[T].Merge (Obi.ObiActor actor, Obi.IObiConstraints other) (at Assets/Obi/Scripts/Common/Blueprints/Constraints/ObiConstraints.cs:55)
Obi.ObiSolver.PushConstraints () (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1389)
Obi.ObiSolver.BeginStep (System.Single stepTime) (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1518)
Obi.ObiUpdater.BeginStep (System.Single stepDeltaTime) (at Assets/Obi/Scripts/Common/Updaters/ObiUpdater.cs:63)
Obi.ObiFixedUpdater.FixedUpdate () (at Assets/Obi/Scripts/Common/Updaters/ObiFixedUpdater.cs:46)

Can you share a working example? I cannot find anything in the samples...

Hi,

You've created an empty particle group, hence the null ref exception: there's no particles in the group to copy to the attachment. You need to first specify which particles are part of the group. Like this:

Code:
var group = ScriptableObject.CreateInstance<ObiParticleGroup>();
group.particleIndices.Add(particleIndex); //<-- add at least one particle to the group.
_lastAttachment.particleGroup = group;

There's no need to give a name to the group or make it part of the blueprint unless you later want to retrieve it by name.

kind regards,
Reply