tl;dr Moving my game from Processing to Unity. Code responsible for grappling by manually changing the player's velocity doesn't work even though it's basically copy/pasted.
Hi, I've been working on a project of mine over the summer on Processing, and last week I decided to translate it over to Unity.
What I'm having a problem with is the grapple/rope physics. It's supposed to essentially keep the player inside a circle (made by the endpoint of the rope and the length of the rope). When the player falls outside of this circle, the player's position is moved back to the edge of the circle and the player's velocity is set to tangent of the circle.
Decreasing the length of the rope while swinging is supposed to speed you up. (See Floating Point)
On Processing, it works perfectly just as described above, but when I basically copy/pasted the code into unity it loses momentum too quickly (always ends up stopping at the same angle on the other side the player started on). Here is the code for both (run on each physics frame):
(I've also made some images to describe the motion that both versions produce)
Processing
Code
(warning: bad and redundant)
physics update:
exists = (endPoint != null);
if(lgth<=0) lgth = 1;
if(exists) {
currentLength = phs.position.dist(endPoint);
if(currentLength > lgth) {
float angle = getAngle(endPoint, phs.position);
phs.addPosition(abs(currentLength - lgth), angle);
float angleBetween = getAngle(phs.position, endPoint);
PVector relativeVelocity = new PVector(phs.velocity.x + phs.position.x, phs.velocity.y + phs.position.y);
float displacement = angleBetween - 90;
Line l1 = lineFromTwoPoints(relativeVelocity, endPoint);
Line l2 = lineFromAngle(phs.position, displacement);
PVector pointToLerpTo = intersection(l1, l2);
if(pointToLerpTo!=null) {
phs.velocity.x = pointToLerpTo.x-phs.position.x;
phs.velocity.y = pointToLerpTo.y-phs.position.y;
}
else phs.velocity.mult(0);
}
}
when the player shortens the rope, speed increases:
if(exists) {
float newLgth = lgth-d;
float distance = getDistance(phs.position, endPoint);
if(distance > newLgth) {
float ratio = (distance-newLgth)/lgth;
phs.velocity.setMag(phs.velocity.mag()*(1+ratio));
}
lgth = newLgth;
}
Motion from Processing (good)
Player starts by moving downwards at left edge of rope circle. Doesn't lose speed and continues going around multiple times until gravity slows it down.
Unity
Code
both code blocks from above are handled in the same place here, under FixedUpdate()
(problematic part seems to be the velocity section)
distance = Vector2.Distance(transform.position, endpoint);
if(connected && distance > length) {
//lerp position -> endpoint// keep gameObject within length of the rope
float posLerpAmount = (distance - length) / distance;
transform.position = Vector2.Lerp(transform.position, endpoint, posLerpAmount);
//'lerp' velocity -> endpoint// keep the velocity locked to the tangent of the circle around the endpoint
Vector2 relativeVelocity = GetComponent<Rigidbody2D>().velocity + (Vector2)transform.position;
Line l1 = Geometry.LineFromTwoPoints(relativeVelocity, endpoint);
Line l2 = Geometry.LineFromAngle(transform.position, Geometry.GetAngle(endpoint, transform.position) - 90);
if(!Geometry.AreParallel(l1, l2)) {
Vector2 pointToLerpTo = Geometry.Intersection(l1, l2) - (Vector2)transform.position;
GetComponent<Rigidbody2D>().velocity = pointToLerpTo;
}
else GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
//increases the magnitude of the velocity based on how far the rope moved the object's position
float ratio = (distance - length) / length;
GetComponent<Rigidbody2D>().velocity *= 1 + ratio;
distance = length;
}
Motion from Unity (bad)
Player starts by moving downward at left edge of rope circle. Gains a little bit of speed from gravity, then will always stop 45 degrees on the other side where it started (regardless of starting speed), then slowly fall back down to the bottom of the circle.
If anyone needs me to explain the Geometry class (lines, intersections) then I can, but I think it's mostly self-explanatory. Otherwise, I think I explained this the best I could. Thanks in advance for any help.
(also, StackOverflow isn't letting me add the Unity2d tag so I guess I gotta settle for Unity3d)
See Question&Answers more detail:
os