Skip to content

Instantly share code, notes, and snippets.

@ditzel
Created July 14, 2018 12:43
Show Gist options
  • Star 83 You must be signed in to star a gist
  • Fork 23 You must be signed in to fork a gist
  • Save ditzel/ae6ebc115d767da9a5a1e1f70dee27e5 to your computer and use it in GitHub Desktop.
Save ditzel/ae6ebc115d767da9a5a1e1f70dee27e5 to your computer and use it in GitHub Desktop.
Rope Physics
using UnityEngine;
public class DistanceJoint3D : MonoBehaviour {
public Transform ConnectedRigidbody;
public bool DetermineDistanceOnStart = true;
public float Distance;
public float Spring = 0.1f;
public float Damper = 5f;
protected Rigidbody Rigidbody;
void Awake()
{
Rigidbody = GetComponent<Rigidbody>();
}
void Start()
{
if (DetermineDistanceOnStart && ConnectedRigidbody != null)
Distance = Vector3.Distance(Rigidbody.position, ConnectedRigidbody.position);
}
void FixedUpdate()
{
var connection = Rigidbody.position - ConnectedRigidbody.position;
var distanceDiscrepancy = Distance - connection.magnitude;
Rigidbody.position += distanceDiscrepancy * connection.normalized;
var velocityTarget = connection + (Rigidbody.velocity + Physics.gravity * Spring);
var projectOnConnection = Vector3.Project(velocityTarget, connection);
Rigidbody.velocity = (velocityTarget - projectOnConnection) / (1 + Damper * Time.fixedDeltaTime);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FrictionJoint3D : MonoBehaviour {
[Range(0,1)]
public float Friction;
protected Rigidbody Rigidbody;
void Awake()
{
Rigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
Rigidbody.velocity = Rigidbody.velocity * (1 - Friction);
Rigidbody.angularVelocity = Rigidbody.angularVelocity * (1 - Friction);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RopeRoot : MonoBehaviour {
public float RigidbodyMass = 1f;
public float ColliderRadius = 0.1f;
public float JointSpring = 0.1f;
public float JointDamper = 5f;
public Vector3 RotationOffset;
public Vector3 PositionOffset;
protected List<Transform> CopySource;
protected List<Transform> CopyDestination;
protected static GameObject RigidBodyContainer;
void Awake()
{
if(RigidBodyContainer == null)
RigidBodyContainer = new GameObject("RopeRigidbodyContainer");
CopySource = new List<Transform>();
CopyDestination = new List<Transform>();
//add children
AddChildren(transform);
}
private void AddChildren(Transform parent)
{
for (int i = 0; i < parent.childCount; i++)
{
var child = parent.GetChild(i);
var representative = new GameObject(child.gameObject.name);
representative.transform.parent = RigidBodyContainer.transform;
//rigidbody
var childRigidbody = representative.gameObject.AddComponent<Rigidbody>();
childRigidbody.useGravity = true;
childRigidbody.isKinematic = false;
childRigidbody.freezeRotation = true;
childRigidbody.mass = RigidbodyMass;
//collider
var collider = representative.gameObject.AddComponent<SphereCollider>();
collider.center = Vector3.zero;
collider.radius = ColliderRadius;
//DistanceJoint
var joint = representative.gameObject.AddComponent<DistanceJoint3D>();
joint.ConnectedRigidbody = parent;
joint.DetermineDistanceOnStart = true;
joint.Spring = JointSpring;
joint.Damper = JointDamper;
joint.DetermineDistanceOnStart = false;
joint.Distance = Vector3.Distance(parent.position, child.position);
//add copy source
CopySource.Add(representative.transform);
CopyDestination.Add(child);
AddChildren(child);
}
}
public void Update()
{
for (int i = 0; i < CopySource.Count; i++)
{
CopyDestination[i].position = CopySource[i].position + PositionOffset;
CopyDestination[i].rotation = CopySource[i].rotation * Quaternion.Euler(RotationOffset);
}
}
}
@ditzel
Copy link
Author

ditzel commented Jun 10, 2019 via email

@happygiant
Copy link

Thank you! One other question: Can the ropes collide with the environment and with each other? And can they be attached to rigid bodies? thanks

@dradb
Copy link

dradb commented Nov 3, 2019

ropeProblem

Can you help please? The rope is in 4 segments with 4 bones plus a tail bone. Script is on the first bone. No errors showing.
Thank you.

@dradb
Copy link

dradb commented Nov 4, 2019

How is the "RotationOffset" being calculated? The rope appears as a zig zag without segments being rotated. If the segments are very small the zig zag may be hard to see.

@Z-Buffer-Arrow
Copy link

Hello. Where should the three rows be placed ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment