Rope or rope like objects can be found in many places in game. Cable lines between poles, vines hanging from trees or spiders swinging by web othey all have similar kind of behavior. We are going to create that and see how it can be used in game.
The rope we are going to create will two components. Vertices and line. We will call them Node
and Stick
. A Stick
will have two Nodes
connected to it making link between them. Node
will be responsible for simulating movements, maintaining structure of rope and handling physics. There will also be fixed nodes that will not move and will act as attached point for rope. Stick
will act as constraints between two nodes keeping them within certain distance.
Creating a Node
As Node
is responsible for movement, let's first create a method to move it. In our Node
class define move function that will move it.
void Move(Vector3 moveVector) {
//get movement vector and translate it with that vector
transform.Translate(moveVector);
}
Movement of vertices will be done from FixedUpdate
. We will be calculating it's velocity using position in previous frame and add gravity to it. It will make our node react to gravity making it fall freely.
public bool isFixed; //if true this point will not be affected by gravity or stick constraint and act as connected point for rope
public static float gravity = -9.8 f; //value of gravity to calculate the rate at which object falls
public Vector2 previousPosition; //position of vertices in previous update. It will be used to calculate velocity in next frame
//We are not directly using FixedUpdate here because order of updating is importaint.
//So just create a method for now which will be updated from other place
public void UpdateNode() {
if (isFixed) return; //dont move if fixed point
Vector2 velocity = (Vector2) transform.position - previousPosition;
calculate velocity to preserve momentum
previousPosition = transform.position; //save current position to be used in next update
//add acceleration
velocity += Vector2.up * gravity * Time.fixedDeltaTime * Time.fixedDeltaTime;
//move object
Move(velocity);
}
Creating a Stick
We will be using LineRenderer
to make a stick. It will have two nodes that will be connected and a length
parameter that will define constraints for the distance between two nodes.
First, let's create a method to make a line between two nodes
private LineRenderer lineRenderer;
private void UpdateLineRenderer() {
lineRenderer.SetPositions(new [] {
node1.transform.position,
node2.transform.position
});
}
Now, we need to create a UpdateStick
method for handling constraints between nodes. This will just move nodes towards each other if their distance is larger than length
public float length;
public void UpdateStick() {
Vector2 center = (node1.transform.position + node2.transform.position) / 2; //calculate midpoint betwen node
if (!node1.isFixed) {
Vector2 node1DirTowardCenter = ((Vector2) node1.transform.position - center).normalized; //calculate direction towards center point
node1.transform.position = node1DirTowardCenter * length / 2 + center; //move point at the right distance i.e half the length from center
}
if (!node2.isFixed) {
//do same for another node
Vector2 node2DirTowardCenter = ((Vector2) node2.transform.position - center).normalized;
node2.transform.position = node2DirTowardCenter * length / 2 + center;
}
//make a line between two node after updating node position is completed
UpdateLineRenderer();
}
Now we need to initialize lineRenderer
and calculate position at Awake
private void Awake() {
lineRenderer = GetComponent < LineRenderer > ();
lineRenderer.useWorldSpace = true;
length = Vector2.Distance(node1.transform.position, node2.transform.position); //calculate distance between nodes at begining. we will be using it to maintain distance throughout simulation
UpdateLineRenderer(); //update line renderer to connect two points
}
Creating a Rope
Finally, we will create a Rope
class that will update each vertice and stick. Updates will happen in FixedUpdate
method as it will give a consistent result.
public class Rope: MonoBehaviour {
public Node[] nodes; //collection for nodes in scene
public Stick[] sticks; //collection for sticks in scene
private void Awake() {
//find all nodes and sticks in scene
nodes = FindObjectsOfType < Node > ();
sticks = FindObjectsOfType < Stick > ();
}
void FixedUpdate() {
//update nodes at first
foreach(Node node in nodes) {
node.UpdateNode();
}
for (int i = 0; i < 3; i++) {
//we may want to update sticks multiple times because one node will be updated by multipe sticks.
//doing multiple iteration will give precise result but single iteration is enough for simpler games
//update sticks to maintain distance between nodes
foreach(Stick stick in sticks) {
//update only if gameobject is active
if (stick.gameObject.activeSelf)
stick.UpdateStick();
}
}
}
}
Setting up in Unity editor
Create a GameObject
for Node
and Stick
in the scene and add respective scripts to it.Stick
should have LineRenderer
attached to it. Connect the  required Nodes
in node1
and node2
of stick. Finally, add Rope
script in scene and we are good to go.
Also, we can enable or disable Stick
object to get cutting and joining effect of rope.
Further improvements and customization
This is a really basic and simple system to make rope-like objects. Using only this will not be enough for a good game. So, what else to add to it? Well, there are many. You can add wind effect along with gravity in node. Or add collider in vertices so that it will interact with other physical objects. Also, another interesting thing to do is make a playable character that can grab/release a Node
and swing like a monkey swinging from rope to rope. Basic cloth simulation can also be done by arranging Node
in the grid and connecting four nodes around it with Stick
. There are just so many possibilities.
Thank you for reading. If you have any question or suggestion please comment below.