Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Use obi rope to generate player lines
#1
I am currently working on a small fishing game using Obi Rope and seeking some advice. Inspired by the RopeGrapplingHook, I'm creating a rope based on the player's lines. My approach involves continuously altering 'cursorMu' between 0.1 and 0.9, along with adjusting 'ChangeLength', to achieve consistent contraction of the rope from both ends. However, I'm encountering a significant challenge: the rope vibrates intensely and behaves unpredictably during generation. I've used a custom outline from a sprite to create a mesh collider. I need to reel in the fish slowly, just like it's shown in the video. If I don't, the fish ends up slipping through the collider of the rope.Could anyone offer insights or suggestions on how to optimize and address this issue?

Thanks in advance for your help!

here is my game video:
Reply
#2
Hi!

Could you share the code you're using to alternate the position of the cursor?

Since your rope has no visible texture/pattern on it, contracting it from just one side should yield visually similar results. Is there any particular reason why this doesn't work for your use case?

kind regards,
Reply
#3
Hi josemendez,

Thanks for your reply! Here is the code about generating the rope and changing the cursor~ Why is the rope not generated for the points in m_Positions? I also want to take a ray starting from the fish and check the number of times the ray passes through the rope to check whether the object is surrounded by the rope, but Query methods don't seem to be able to do it.

Code:
        private async UniTaskVoid ChangeRopeLength1()
        {
            GameManager.Instance.GameStatus = GameStatus.Pull;
           
            // Clear Constraints
            var obiConstraints = m_Rope.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
            obiConstraints?.Clear();
           
            // Generate Blueprint
            var filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
            m_RopeBlueprint.path.Clear();
            m_RopeBlueprint.path.AddControlPoint(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.up, 0.1f, 0.1f, 1, filter, Color.white, "Hook start");
            m_RopeBlueprint.path.AddControlPoint(new Vector3(0, -0.5f, 0), Vector3.zero, Vector3.zero, Vector3.up, 0.1f, 0.1f, 1, filter, Color.white, "Hook end");
            m_RopeBlueprint.path.FlushEvents();

            await m_RopeBlueprint.Generate().ToUniTask(this);

            m_Rope.ropeBlueprint = m_RopeBlueprint;
           
            await UniTask.Yield();
           
            GetComponent<MeshRenderer>().enabled = true;
           
            // Generate Rope
            var prePos = m_AttachPos;
            var lineLength = 0f;
            foreach (var position in m_Positions)
            {
                var direction = position - prePos;
                var preElementsCount = m_Rope.elements.Count;
                // Calculate distance
                lineLength += direction.magnitude;
                m_RopeCursor.ChangeLength(lineLength);
               
                var currentElementCount = m_Rope.elements.Count - preElementsCount;
               
                // Update Positions
                direction.Normalize();
                var elementIndex = 0;
                while (elementIndex < currentElementCount)
                {
                    var ropeElement = m_Rope.elements[elementIndex];
                    var part1 = ropeElement.particle1;
                    var part2 = ropeElement.particle2;

                    var pre = m_Rope.solver.transform.InverseTransformPoint(prePos);
                    m_Rope.solver.positions[part1] = pre;
                    m_Rope.solver.velocities[part1] = Vector4.zero;

                    prePos += direction * ropeElement.restLength;
                    var next = m_Rope.solver.transform.InverseTransformPoint(prePos);
                    m_Rope.solver.positions[part2] = next;
                    m_Rope.solver.velocities[part2] = Vector4.zero;
                    elementIndex++;
                }

                prePos = position;
            }
           
            // Set Mass
            for (var i = 0; i < m_Rope.activeParticleCount; ++i)
            {
                m_Solver.invMasses[m_Rope.solverIndices[i]] = 100;
            }

            await UniTask.Yield();

            // Add Constraints
            var pinConstraintsBatch = new ObiPinConstraintsBatch();
            pinConstraintsBatch.AddConstraint(m_Rope.elements[0].particle1, m_CatAttach, Vector3.zero, Quaternion.identity, 0, 0, float.PositiveInfinity);
            pinConstraintsBatch.AddConstraint(m_Rope.elements[^1].particle2, m_CatAttach, Vector3.zero, Quaternion.identity, 0, 0, float.PositiveInfinity);
            pinConstraintsBatch.activeConstraintCount = 2;
            obiConstraints?.AddBatch(pinConstraintsBatch);
           
            m_Rope.SetConstraintsDirty(Oni.ConstraintType.Pin);
           
            await UniTask.Yield();
           
            while (true)
            {
                var preLength = m_Rope.restLength;
                m_RopeCursor.cursorMu = 0.1f;
                var deltaLength = GameManager.Instance.RopePullSpeed * Time.fixedDeltaTime;
                m_RopeCursor.ChangeLength(m_Rope.restLength - deltaLength);
                await UniTask.WaitForFixedUpdate();
                m_RopeCursor.cursorMu = 0.9f;
                m_RopeCursor.ChangeLength(m_Rope.restLength - deltaLength);
                await UniTask.WaitForFixedUpdate();
                if (m_Rope.restLength < 5f || GameManager.Instance.GameStatus == GameStatus.End)
                {
                    break;
                }
            }
           
            GameManager.Instance.CheckWin();
        }

I need to create an effect similar to the one in the video:
Reply
#4
(11-04-2024, 05:17 PM)Jack Li Wrote: Here is the code about generating the rope and changing the cursor~ Why is the rope not generated for the points in m_Positions? 

What's m_Positions? The code looks like you're trying to generate a rope that passes trough a set of points, but that's precisely what the blueprint is designed for: providing a path that passes trough several control points, and generate a rope out of them. If that's your goal, there isn't any need to loop over m_Positions increasing the length of the rope and manually placing particles yourself. Just create one control point per point in m_Positions.


(11-04-2024, 05:17 PM)Jack Li Wrote: I also want to take a ray starting from the fish and check the number of times the ray passes through the rope to check whether the object is surrounded by the rope, but Query methods don't seem to be able to do it.

No need to use raycast queries for this, there's a much simpler way: just iterate trough all elements in the rope -since they can be considered faces of a polygon- and perform a basic point-in-polygon test like this one: https://wrfranklin.org/Research/Short_Notes/pnpoly.html

About your original issue with the rope jittering, I'm afraid that's unavoidable given your approach: every frame you're removing rope from a different part of it, so the mass distribution at both ends of the rope will change every frame leading to a small jitter. You could increase the solver's sleep threshold slightly, see if that can hide this jitter without affecting rope dynamics too much.

kind regards
Reply