Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Rope saving and restore by Json
#11
(25-06-2024, 09:58 AM)josemendez Wrote: You'll need to store blueprint control points as well anyway, so the start/end points of each rope will be stored in your JSON. At this point you can probably just have one scene in your game and store the entire level setup in JSON.


Sure! let me know if you need further help Sonrisa

Hi, I'm back, sorry to bother you again. After some attempts, I have made some significant progress, which is really very exciting.  Guiño
But now I have encountered some new problems. I have uploaded the latest results and problem pictures in the attachment.


Following your advice, I have now saved the length and position of the particles, as well as the ControlPoints in the blueprint, while inTangent and outTangent are Vector.zero, so I didn't save it in order to save space. When instantiating the rope, the originally stored controlPoints are restored through the blueprint's AddControlPoints() method, and after the blueprint is fully loaded, the stored positions are reset to the particles, which allows for the restoration of the shape of the rope for the vast majority of the time as it was before it was saved. So now the generated rope is really similar to what it was before it was saved. But there is still some loss of detail, which directly affects the difficulty of the game in the actual gameplay.


Here is the code to save controlPoints.
Code:
JSONObject GetRopeControlPoints()
    {
        var rope = gameObject.GetComponent<ObiRope>();
        var pointsArray = JSONObject.emptyArray;
        //var inTangentArray = JSONObject.emptyArray;
        //var outTangentArray = JSONObject.emptyArray;
        foreach (var obiWingedPoint in rope.ropeBlueprint.path.m_Points.data)
        {
            pointsArray.Add((JSONNode)obiWingedPoint.position);
            //inTangentArray.Add((JSONNode)obiWingedPoint.inTangent);
            //outTangentArray.Add((JSONNode)obiWingedPoint.outTangent);
        }
        var jsonObject = JSONObject.emptyObject;
        jsonObject.AddField("points", pointsArray);
        //jsonObject.AddField("inTangent", inTangentArray);
        //jsonObject.AddField("outTangent", outTangentArray);
        return jsonObject;
    }


Here is the code when instantiating the rope.
Code:
        ObiRopeBlueprint blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
        blueprint.path.Clear();
        blueprint.resolution = 1;
       
        int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
       
        int posIndex = 0;
        foreach (var obiWingedPoint in controlPoints)
        {
            blueprint.path.AddControlPoint(obiWingedPoint.position, obiWingedPoint.inTangent, obiWingedPoint.outTangent,
                Vector3.up, ropeMass, 0.1f, ropeThickness, filter, Color.yellow, $"pos_{posIndex}");
            posIndex++;
        }
     
        blueprint.path.FlushEvents();
        blueprint.GenerateImmediate();     
   
        ObiParticleAttachment attachment1 = rpObject.AddComponent<ObiParticleAttachment>();
        ObiParticleAttachment attachment2 = rpObject.AddComponent<ObiParticleAttachment>();
     
        rope.ropeBlueprint = blueprint;
       
        attachment1.target = transformA;
        attachment2.target = transformB;
        attachment1.particleGroup = blueprint.groups[0];
        attachment2.particleGroup = blueprint.groups.Last();

        // Parent the actor under a solver to start the simulation:
        rpObject.transform.SetParent(obiSolverObject.transform);
       
        return rpObject;


The images in the attachment should sufficiently illustrate the situation of the problem. Here, I will provide a brief description as well, just in case the images cannot be viewed:  After the restoration, the shape of the rope is really close to it was saved. However, some areas where the ropes are twisted with each other are lost, regardless of the complexity of the twists. As can be seen in image 6, even simple windings can sometimes be lost, even though they had clearly occurred by the first frame.
From image 5, it can be observed that the particles extracted from rope.solverIndices are not contiguous in position, which I believe to be normal according to the Obi documentation. However, I am not certain if this is the cause of the loss of detail.

可以看到从rope.solverIndices中取出的particle,在位置上并不是连续在一起的,根据obi的资料后,我觉得这应该是正常的。但是不确定是否这是导致细节丢失的原因。
The order of the particles in rope.elements is coherent. I have tried to save and restore these particles, but the problem persists.

In the level, there are pre-placed Obi solvers with various parameters and constraints that have been adjusted. The instantiated rope has been saved as a prefab, and the parameters have also been adjusted. Therefore, the parameters and constraints applied when restoring the rope using the data should be the same as before the data was saved. Thus, I did not store the constraints in the JSON, and no operations were performed during restoration.

Is there any step that I have missed?


Attached Files Thumbnail(s)
           
Reply
#12
Hi,

You're setting the blueprint's resolution to 100. It can't go past 1 (distance between particle centers == rope thickness). Is this the same resolution of the blueprint you originally created?. Also make sure the blueprint thickness is the same. Otherwise the amount of particles in the blueprint as well as the distance between them will be different.

Also keep in mind that Obi is a position-based engine. This means velocities are derived from positional deltas, you should set both solver.positions as well as solver.prevPositions to the same values, otherwise particle velocities will be non-zero at the start because velocity = (pos-prevpos) / time.

Quote:it can be observed that the particles extracted from rope.solverIndices are not contiguous in position, which I believe to be normal according to the Obi documentation. However, I am not certain if this is the cause of the loss of detail.

This will only happen if your ropes have had their length changed at runtime using a cursor, or if they have been cut. Otherwise order should be contiguous. If you're not doing either, then it means you're either storing or loading particles in the wrong order.

kind regards
Reply
#13
(27-06-2024, 12:22 PM)josemendez Wrote: You're setting the blueprint's resolution to 100. It can't go past 1 (distance between particle centers == rope thickness). Is this the same resolution of the blueprint you originally created?. Also make sure the blueprint thickness is the same. Otherwise the amount of particles in the blueprint as well as the distance between them will be different.
The blueprint's resolution should be 1; that was my mistake, a paste error.

(27-06-2024, 12:22 PM)josemendez Wrote: Also keep in mind that Obi is a position-based engine. This means velocities are derived from positional deltas, you should set both solver.positions as well as solver.prevPositions to the same values, otherwise particle velocities will be non-zero at the start because velocity = (pos-prevpos) / time.


This will only happen if your ropes have had their length changed at runtime using a cursor, or if they have been cut. Otherwise order should be contiguous. If you're not doing either, then it means you're either storing or loading particles in the wrong order.
I will try setting the prevPositions, indeed, I  didn't set them in the code.


Well, I did indeed change the length of the rope during runtime using the cursor. Previously, I had written a random algorithm to generate key points for the rope's path, and then I added these key points to the controlPoints to make the rope generate according to this path. This approach resulted in a very long rope, with excess length bunched up, but the interweaving between the ropes was indeed effective, so I had to contract it until all the ropes were tightened, at which point the ropes had no excess length and all maintained the randomly generated interweaving state. I am not sure if this approach is reasonable.  Random algorithm is really tough to me. (I am eager to receive some recommendations for good entanglement generation algorithms. Sonrojado Llorar )


(27-06-2024, 12:22 PM)josemendez Wrote: Also keep in mind that Obi is a position-based engine. This means velocities are derived from positional deltas, you should set both solver.positions as well as solver.prevPositions to the same values, otherwise particle velocities will be non-zero at the start because velocity = (pos-prevpos) / time.


This will only happen if your ropes have had their length changed at runtime using a cursor, or if they have been cut. Otherwise order should be contiguous. If you're not doing either, then it means you're either storing or loading particles in the wrong order.

kind regards
I have tried setting solver.positions and solver.prevPositions, but it didn't have much effect.

For now, it seems I have hit a deadlock. Contracting the rope to reduce the impact of the random path generation on it appears to be inevitable for me at this point.

(27-06-2024, 12:22 PM)josemendez Wrote: This will only happen if your ropes have had their length changed at runtime using a cursor, or if they have been cut. Otherwise order should be contiguous. If you're not doing either, then it means you're either storing or loading particles in the wrong order.

When I stored the particles before, I directly iterated through rope.solverIndices. If it's because I changed the length of the rope, which caused the order of the particles to be disrupted, Then rope.elements must be continuous. I tried only using rope.elements when storing, and assigning directly to solver.positions[particlesIndices[i]] during restore, but it still didn't work. The root cause is that the order in rope.solver.positions is disordered, right?
Reply