Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to make the Start/End Prefab able to be Raycasted?
#11
Sorry, but i need to ask you again Sonrojado

When i want to grab the End Prefab, my handle will be created on the Start Prefab and im carrying it not the End Prefab.
But when i grab the Start Prefab, its okay.

Code:
public override void OnInteract(NetworkIdentity _player, bool _release)
    {
            base.OnInteract(_player, _release);

            m_handleGO = new GameObject("Obi Handle");
            m_handle = m_handleGO.AddComponent<ObiParticleHandle>();
            m_handle.Actor = m_rope;

            Debug.Log("Interact with: " + gameObject.name);

            m_handleGO.transform.position = transform.position;

            m_handle.AddParticle(0, transform.position, 1f);
        }        
    }
Reply
#12
(02-11-2017, 10:57 PM)Rexima Wrote: Sorry, but i need to ask you again  Sonrojado

When i want to grab the End Prefab, my handle will be created on the Start Prefab and im carrying it not the End Prefab.
But when i grab the Start Prefab, its okay.


Code:
   public override void OnInteract(NetworkIdentity _player, bool _release)
   {
           base.OnInteract(_player, _release);

           m_handleGO = new GameObject("Obi Handle");
           m_handle = m_handleGO.AddComponent<ObiParticleHandle>();
           m_handle.Actor = m_rope;

           Debug.Log("Interact with: " + gameObject.name);

           m_handleGO.transform.position = transform.position;

           m_handle.AddParticle(0, transform.position, 1f);
       }        
   }

Hi,

You need to change the particle you're adding to the handle. To grab the start of the rope, you should add first particle to the handle (index 0, like you have now). To grab the end of the rope, add the last particle in the rope instead:


Code:
m_handle.AddParticle( rope.UsedParticles-1, transform.position, 1f);
Reply
#13
Thank you very much, it works now.

I have an another question, is it possible to rotate the Start or End Prefab, when its added to an Pin Constraint?
I want to use this rope asset to connect various machines together.
And when i fix the Start or End prefab, it hangs, but i want that its more stiff and looks like its real connected to the machine.

Is it also possible to get some informations, if the rope is stretched?
I want to change the length of it, when the character is moving and the rope is stretched.
I also need to know it, because if the rope is stretched and the max length is exceeded, the player should drop the rope.
Btw. where do i set the max length of the rope? - Pooled Particles

When the length of the rope was changed, than UsedParticles doesnt work anymore to get the last particle (End prefab)

Sorry for this amount of questions, but i can't find any answer on the wiki/forum
Reply
#14
(03-11-2017, 03:49 PM)Rexima Wrote: Thank you very much, it works now.

I have an another question, is it possible to rotate the Start or End Prefab, when its added to an Pin Constraint?
I want to use this rope asset to connect various machines together.
And when i fix the Start or End prefab, it hangs, but i want that its more stiff and looks like its real connected to the machine.

Is it also possible to get some informations, if the rope is stretched?
I want to change the length of it, when the character is moving and the rope is stretched.
I also need to know it, because if the rope is stretched and the max length is exceeded, the player should drop the rope.
Btw. where do i set the max length of the rope? - Pooled Particles

When the length of the rope was changed, than UsedParticles doesnt work anymore to get the last particle (End prefab)

Sorry for this amount of questions, but i can't find any answer on the wiki/forum

Hi!

Fixing/pinning the last 2 particles instead of just the last one will allow orientation to kick in. (1 point in space does not define a direction/orientation, 2 points however do). Similarly, fixing the first two particles instead of the first one works in the same way for the start of the rope.

When changing the length of the rope, UsedParticles should still give you the total amount of particles in the rope. However, If your ObiRopeCursor is not at the end (for example it is in the middle, or at the start of the rope) then the "new" particles generated when increasing its length will be added in the middle of the rope, so UsedParticles-1 will no longer be the last one in the rope (but the most recently added one, close to the cursor).

In this case, the best way is to use  GetConstraintIndexAtNormalizedCoordinate(). This will return the index of the distance constraint at a given point in the rope (0 is the start, 1 is the end, any value in between is a percentage).

Then you can use the constraint index to get the two particles joined by it.


Code:
int constraint = rope.GetConstraintIndexAtNormalizedCoordinate(1); //get last constraint in the rope (use 0 for first one)

ObiDistanceConstraintBatch distanceBatch = rope.DistanceConstraints.GetBatches()[0] as ObiDistanceConstraintBatch;

// get the last two particles in the rope:
int lastParticle = distanceBatch.springIndices[constraint*2+1];
int prevParticle = distanceBatch.springIndices[constraint*2];

PD: As a side note, you can enforce a maximum rope length yourself if you wish too. No need to rely on the amount of pooled particles. Simply check rope.RestLength and no longer call ChangeLength() if the rope is too long (or too short). RestLength is not affected by stretching or compressing the rope, it reflects the actual "logical" length of the rope, not the apparent one.
Reply
#15
Perfect, it works great. Now i have a problem to remove the pinned constraints Indeciso
How do i get the index, when i pinned a constraint?
For example, when i try to remove it with this
Code:
batch.RemoveConstraint(0);
batch.RemoveConstraint(1);

Edit: Actually im solving it like this, but it's not the best option to remove both constraints.
Code:
for (int i = 0; i < batch.ConstraintCount; i++)
            {
                if(batch.pinBodies[i] == m_obiCollider)
                {
                    batch.RemoveConstraint(i);
                }
            }

            for (int i = 0; i < batch.ConstraintCount; i++)
            {
                if (batch.pinBodies[i] == m_obiCollider)
                {
                    batch.RemoveConstraint(i);
                }
            }

I remove for each end the previous pin and not like expected for the startprefab the both constraints.

And is it also possible to get some informations, if the rope is stretched?
Reply
#16
Is this pin constraint doing something different than what you are doing with the particle handles? If so..

You're going to have to keep track of the index yourself. When adding a pin constraint you'll need to set the pins index to the current pin constraints count. When removing a pin index, all the higher indices will need to be decremented. You can see in this snippet the dictionary keeps a pair of an ObiCollider and its pinned index. If you are pinning multiple indices to the same collider, this method won't work but you can get the jist of what needs to happen.


Code:
public Dictionary<ObiCollider, int> pinnedColliders = new Dictionary<ObiCollider, int>();

       public ObiRope actor;

       public void PinObiColliderToParticle(ObiCollider obiCollider, int particleIndex, Vector3? pinOffset = null, int? pinStiffness = null)
       {
           if (pinnedColliders.ContainsKey(obiCollider))
               return;

           ObiPinConstraintBatch batch = actor.PinConstraints.GetBatches()[0] as ObiPinConstraintBatch;
           actor.PinConstraints.RemoveFromSolver(null);

           // Set the pin as the next availiable index in the batch
           pinnedColliders.Add(obiCollider, batch.ConstraintCount);

           batch.AddConstraint(particleIndex, obiCollider, pinOffset == null ? Vector3.zero : pinOffset.Value, pinStiffness == null ? 1 : pinStiffness.Value);

           actor.PinConstraints.AddToSolver(null);
           actor.PinConstraints.PushDataToSolver();
       }

       public void UnpinObiCollider(ObiCollider obiCollider)
       {
           if (!pinnedColliders.ContainsKey(obiCollider))
               return;

           ObiPinConstraintBatch batch = actor.PinConstraints.GetBatches()[0] as ObiPinConstraintBatch;
           actor.PinConstraints.RemoveFromSolver(null);

           int pinIndex = pinnedColliders[obiCollider];

           batch.RemoveConstraint(pinIndex);

           pinnedColliders.Remove(obiCollider);

           List<ObiCollider> keys = new List<ObiCollider>(pinnedColliders.Keys);

           // Decrement the pinned indices that are greater than the removed index
           foreach (ObiCollider collider in keys)
           {
               int checkIndex = pinnedColliders[collider];

               if (checkIndex >= 0 && checkIndex > pinIndex)
               {
                   pinnedColliders[collider]--;
               }
           }

           actor.PinConstraints.AddToSolver(null);
           actor.PinConstraints.PushDataToSolver();
       }

You may use the snippet you're using at the start of a scene to assign what indices each object are. This is useful for when you pin things in the editor. Then from there you would need to manage them manually. Once a pin index is removed all other indices must be updated like i mentioned, so you need some kind of structure to keep track.

To see if the rope is stretching, you will also need to keep track of whats happening. Once your character has touched to rope, get the ropes length to get the initial stretch. Then as the character is interacting with the rope, keep checking against the initial stretch value to see if it has increased. If it has increased, then have the rope cursor extend the rope. I have a few snippets on seeing if the rope is stretching. There are other ways which might be more useful if you're checking the stretch to start the cursor. You can get the force resistance between the particles and if it exceeds your defined force threshold you can tell the cursor to extend the rope. I don't know what you're dealing with exactly so I'll give you a simple one. All this does is iterate though the particles and gets the distance between each one and adds them up.


Code:
public float GetRopeLength(ObiRope rope)
       {
           float ropeLength = 0;
           Vector3 a, b;

           for (int i = 0; i < rope.particleIndices.Length - 1; i++)
           {
               int particleIndex = rope.particleIndices[i];

               a = rope.GetParticlePosition(particleIndex);
               b = rope.GetParticlePosition(particleIndex + 1);

               ropeLength += Vector3.Distance(a, b);
           }

           return ropeLength;
       }
Reply
#17
Just one thing to add to what niZmo said: ObiRope already has a method to get the "real" length, including stretch:


Code:
float length = rope.CalculateLength();
No need to roll your own.

Also, niZmo's one would not work in case of a torn or extended/shortened rope, since particle ordering can change. The built-in method however, iterates over distance constraints instead of particles, so it will return the correct length in all cases.
Reply
#18
Whoops, the class I refactored that length method from keeps track of its particles. The class keep track of cut rope pieces and has its own particlesIndices array which would keeps the correct particle order. Anyway yup overlooked that when refactoring it for him lol.
Reply
#19
Thank you very much, i got everything working, like i planned.
But i have at least one question, is it possible to check if the rope is stretched?
Is there any function to check if im stretching the rope?
Reply
#20
This is pretty much what you want to do. But as above you can get the length of the rope and check it when ever you want to see if it has stretched.
Reply