- Home /
Modify rotation based on passing rigidbody's velocity and direction?
Hello!
I've got a fairly complex scenario where I need to update an objects rotation speed and clockwise/counter-clockwise direction. The rotation is just about the Z axis as I've scripted my game to be 2D in the X and Y. I'm not using gravity but have created my own custom "orbiting" gravity (it's a slingshot physics/puzzle game in space).
Here's a picture of the scenario I'm trying to accomplish:
The black circle represents an object who's position doesn't change, but is rotating via a transform.RotateAround
. The blue sphere is traveling with a rigidbody and velocity throughout the game area.
I already detect when the blue circle is close enough to affect the black circle's rotation, but how can I determine which direction the black circle needs to rotate in, and by what magnitude? I think it would relate to the blue circle's velocity, normalized vector, and position relative to the black circle- but I can't piece the three together logically.
Keep in mind the blue circle may come from any direction, not just from below.
What I've tried which sorta works but not smoothly/realistically:
I've been attempting to calculate which Cartesian quadrant the blue circle is in based on the black circle representing the origin. Then, I determine if the blue circle is moving faster in the X or Y direction, and spin appropriately. This doesn't always work and doesn't look "natural"... I'm not too good at linear algebra, so I'm unsure of any other way to achieve this? Please help!
Note: I can post scripts if needed (I'm using JavaScript), but they're a bit lengthy- I'll leave them out for now because I think I'm going in the wrong direction and don't want to mess anyone else up who may be in my position.
EDIT: Sorry about the pictures not showing up, they don't seem to want to cooperate =/
This is too vague. I suppose that when the sphere passes within a certain distance, the black object must follow the sphere velocity - if the sphere velocity is 5 m/s and it's at 3 m from the object center, for instance, the object must rotate at 0.26 revolutions per second, which gives 5m/s at 3m.
But there are several other possibilities to consider. What should happen when:
1- The sphere passes at a large distance (nothing?)
2- The sphere hits the rotator (never happens?)
3- The object is rotating in one direction and the sphere passes in the opposite direction (follow the sphere velocity? reduces velocity?)
Answer by aldonaletto · Aug 23, 2011 at 04:45 PM
Despite the description is somewhat vague about some points, I wrote a script which can serve to your purpose - or at least can show you how to do the necessary calculation (which isn't so easy as it may seem).
To test this script, follow these steps:
1- Create an empty object and attach the script below
2- Add a sphere colldier and set its radius to the distance the sphere can be detected
3- Create the rotor object and call it "Rotor"
4- Child the Rotor to the first object
It's ready. Whenever a rigidbody enters the trigger, the script calculates the distance it will pass from the rotor and sets the variable rps (revolutions per second) to a suitable speed (as the sphere "pushed" the rotor):
private var rotor: Transform; private var rps: float = 0; // revolutions per second
function Start(){ rotor = transform.Find("Rotor"); }
function OnTriggerEnter(hit: Collider){ if (hit.rigidbody){ // ignore non rigidbody objects var vel = hit.rigidbody.velocity.magnitude; // gets the sphere speed var dir = hit.rigidbody.velocity.normalized; // and its direction var start = hit.transform.position; // start is the sphere position var point = rotor.position; // point is the rotor center // find the nearest point to the rotor the sphere will pass through var tgPt = start + Vector3.Dot(point-start, dir)*dir; var radius = Vector3.Distance(tgPt, point); // distance from the rotor center rps = vel/(2*Mathf.PI*radius); // calculate rotations per second var cross = Vector3.Cross(dir, tgPt-point); // cross product will give the direction if (cross.z > 0) rps = -rps; // correct rotation direction if needed } }
function Update(){ rotor.Rotate(0, 0, 360*rps*Time.deltaTime); // rotate around Z axis }