Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Attaching a rope and updating position multiple times
#1
Hello,

I've been trying for the last couple of days to get the rope to do what we need and just can't quite get it to play nicely. Hoping you can help.

The use case is as follows:

  • The rope is attached to the ground at one end
  • Initially, the other end is attached to the player
  • At specific places, when the player initiates it, we want the rope to attach to a point on the wall
  • At this point, the rope would have three attachments (the ground, the point on the wall, and the player)
  • This will then happen repeatedly so the rope may eventually have six attachments for example (ground, wall, wall, wall, wall, player)
My first approach was to create a single rope and use a pre-built blueprint and then just update the blueprint as time went on, adding new particle attachments and using the cursor to extend the length of the rope, but I couldn't get it to work.

Second, I tried generating a blueprint with code in case that was the issue, no luck.

My current approach was to generate a new rope for each segment (so each rope would just have two attachments and there would be a series of ropes in a list).

When I try to do this, the first rope attaches as desired properly. The second rope, attaches, but the positions of the particles do no update. So I can see the particles are attached but they are not in the right place.

Here is the code I am using to control the rope:

Code:
public class RopeController : MonoBehaviour
{
    private ObiSolver _solver;
    private ObiRope _rope;
    private ObiRopeBlueprint _blueprint;
    private int _ropeId = -1;

    private string _cp1Name;
    private string _cp2Name;

    public void Init(int ropeId, float ropeLength, float ropeMass,
        float ropeRotationalMass, Transform attachment1, Transform attachment2)
    {
        StartCoroutine(InitCoro(ropeId, ropeLength, ropeMass, ropeRotationalMass, attachment1, attachment2));
    }

    private IEnumerator InitCoro(int ropeId, float ropeLength, float ropeMass,
        float ropeRotationalMass, Transform attachment1, Transform attachment2)
    {
        _ropeId = ropeId;
       
        _solver = GetComponentInParent<ObiSolver>();
        if (_solver == null)
        {
            Debug.LogError("No ObiSolver found in parent");
        }
        _rope = GetComponent<ObiRope>();
        _rope.GetComponent<MeshRenderer>().enabled = false;

        _blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
        _blueprint.resolution = 1f;
        _blueprint.pooledParticles = 100;
        _blueprint.thickness = 0.03f;

        int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
        Vector3 posCp1 = Vector3.zero;
        _cp1Name = $"Rope{_ropeId}_CP1";
        Vector3 posCp2 = new Vector3 (-4, 0, 0);
        _cp2Name = $"Rope{_ropeId}_CP2";
        _blueprint.path.Clear();
        _blueprint.path.AddControlPoint(posCp1, Vector3.zero, Vector3.zero, Vector3.up,
            ropeMass, ropeRotationalMass, 1f, filter, Color.white, _cp1Name);
        _blueprint.path.AddControlPoint(posCp2, Vector3.zero, Vector3.zero, Vector3.up,
            ropeMass, ropeRotationalMass, 1f, filter, Color.white, _cp2Name);
        _blueprint.path.FlushEvents();

        yield return _blueprint.Generate();

        _rope.ropeBlueprint = _blueprint;

        SetAttachment(attachment1, _cp1Name);
        SetAttachment(attachment2, _cp2Name);

        yield return null;

        _rope.GetComponent<MeshRenderer>().enabled = true;


        _rope.ropeBlueprint = _blueprint;
    }

    private void SetAttachment(Transform attachmentTarget, string particleGroupName)
    {
        // add a particle attachment to the rope
        var particleAttachment = _rope.gameObject.AddComponent<ObiParticleAttachment>();

        // disable the attachment
        particleAttachment.enabled = false;

        // find the particle group we want to attach to
        var particleGroup = _rope.ropeBlueprint.groups.Find(x => x.name == particleGroupName);

        // set the attachment's particle group to the one we found
        particleAttachment.particleGroup = particleGroup;

        // get the particle index of the first particle in the group
        var particleIndex = particleAttachment.particleGroup.particleIndices[0];

        // set the position of that particle to the attachment target
        _solver.positions[particleIndex] = _solver.transform.InverseTransformPoint(attachmentTarget.position);

        // set the attachment's target to the transform we want to attach to
        particleAttachment.target = attachmentTarget;

        // re-enable the attachment
        particleAttachment.enabled = true;
    }
}


and these are instantiated from a system class as follows:

Code:
public class RopeSystemIncremental : MonoBehaviour
{
    [SerializeField] private Material _ropeMat;
    [SerializeField] private Transform _groundAttachmentTra;
    [SerializeField] private Transform _playerAttachmentTra;
    [SerializeField] private Transform _TESTINGgrabbableAttachmentTra;
    [SerializeField] private RopeController _ropePF;

    private float _defaultRopeLength = 4f;
    private float _ropeMass = 0.1f;
    private float _ropeRotationalMass = 0.1f;
    private ObiSolver _solver;

    private List<RopeController> _ropes = new List<RopeController>();

    private void Awake()
    {
        _solver = GetComponentInChildren<ObiSolver>();
    }

    [ContextMenu("FirstOne")]
    private void FirstOne()
    {
        InstantiateRope(_groundAttachmentTra, _playerAttachmentTra);
    }

    [ContextMenu("SecondOne")]
    private void SecondOne()
    {
        InstantiateRope(_TESTINGgrabbableAttachmentTra, _playerAttachmentTra);
    }

    private RopeController InstantiateRope(Transform attachment1, Transform attachment2)
    {
        var ropeCont = Instantiate(_ropePF, Vector3.zero, Quaternion.identity, _solver.transform);
        _ropes.Add(ropeCont);
        ropeCont.gameObject.name = "Rope " + _ropes.Count;
        ropeCont.Init(_ropes.Count, _defaultRopeLength, _ropeMass, _ropeRotationalMass, attachment1, attachment2);
        return ropeCont;
    }
}

Been hitting my head against the wall with this for a while now! Would really appreciate your help. Many thanks in advance.
Reply


Messages In This Thread
Attaching a rope and updating position multiple times - by stateofplay - 27-02-2024, 03:02 PM