Determine speed/acceleration of an object when it's held (parented) by character?

I’m trying to figure out a way to determine the speed of an object while it’s being held by my character.

Since it’s being held, it’s not being moved by forces and hence the velocity of the rigidbody always reads zero. How could I get the speed or acceleration of such an object? I tried comparing the position of the transform and dividing by Time.fixedDeltaTime and it sort of works, but seems to give surprising results at times - any better ways?

Since it is being held by your character then i would think that the speed of your character is the speed of that unless your character is not the parent of the object.

Umh,
My character’s hand is the parent of that object. My goal is to figure out how fast he is swinging that object. Doesn’t have to be even accurate, I just want to know when the object (or the hand) moves “fast”.

Oh, and I also tried rigidbody.GetRelativePointVelocity() with the relative point being the shoulder of that character and even (0,0,0) but that keeps giving me zero as well…

Difference between 2 position in space = Distance (10 units, 10 km)
Distance / Time = Speed (10 units/frame, 10 km/h)
Speed = Velocity

Thus :

Vector3 lastPos = Vector3.zero;

void Update() {
    Vector3 distancePerFrame = transform.position - lastPos; // transform.position is in global space, not in local/parent
    lastPos = transform.position;

    Vector3 speed = distancePerFrame * Time.deltaTime; // could be anything to scale frame => sec => hour

    Debug.Log(speed);
}

Edit : If you want to give the velocity to the rigidbody of the object, Unity has a method to add velocity without taking the mass into account : suited for the above’s code

yes, that kinda works. I was just wondering if there was a better solution. But thanks!

If you consider the circular motion only, which is okay for swinging motions, then the child’s velocity will be exactly the parent’s velocity plus the tangential velocity due to continuous rotation around the parent’s axis. The tangential velocity of the child is found by taking the cross product of the radius vector between the parent and child and the parent’s angular velocity vector (in radians per second).

The acceleration of velocity is found by subtracting the current velocity from the previous velocity in the previous time step, and then dividing by the current time delta.

Vector3 previousVelocity = Vector3.zero; // initialize this to the child's initial velocity
void Update()
{
   Vector3 tangentialVelocity = Vector3.Cross((child.transform.position - parent.transform.position), parent.rigidbody.angularVelocity * Mathf.Deg2Rad);
   Vector3 currentVelocity = tangentialVelocity + parent.rigidbody.velocity;
   Vector3 currentAcceleration = (currentVelocity - previousVelocity) / Time.deltaTime;
   previousVelocity = currentVelocity;
}

And I will have have to double-check my math on this one when I get home. This is off the top of my head. Seems like it’s right, though.

Ok, thanks I will try that too!

Interesting coincidence; I’ve been working on something along these lines myself for the past few days.

In my case, the held objected is parented to the transform of a character controller (for now, I’m just using the First Person Controller prefab that comes with Unity). Since the FPC doesn’t have an attached rigidbody, however, rather than using parent.rigidbody.angularVelocity to obtain the player’s angular velocity I compute angular speed separately for yaw and pitch using a four-point backwards finite difference approximation. These speeds are then used to compute the resulting yaw and pitch tangential velocity vectors in global coordinates using the same underlying physics as the code Brian posted.

However, I’m currently unsatisfied with the results. Since the player can rotate the FPC at far greater speeds than would be possible in real life (which is typical of FPS games and even mentioned in the Unity documentation), the angular speeds are often quite high and result in unrealistically large tangential velocities. The video linked below provides a typical example:

This is in stark contrast to something like the Source engine, in which releasing a held physics object generally results in it flying only a few metres before hitting the ground. I assume that Source’s behaviour involves some sort of “cheating” since players can rotate just as quickly in Source-based games as they can in those made using Unity.

Any thoughts on a nice way to adjust the tangential velocity before it’s applied to the previously-held object? I’ve tried scaling the velocity down by factors in the range of 5-10, which improves things but still feels somewhat off. I’ve considered computing the resulting centripetal force (F = (m*v^2)/2), clamping that, then recalculating the velocity, but I haven’t actually tried it yet. Perhaps clamping the velocity might produce a better result. On the whole, I suppose I’m just reluctant to deviate from “correct” physics, but if anything impairs player immersion I suspect it’s cubes approaching the speed of light.

Wow, that was complex enough to make my head spin!
I’m currently ok with not-so-correct physics as long the object flies, but it’s great that you’re putting in the effort!

It’s actually not too complicated; finite difference methods are just a mathematically-robust way to approximate derivatives given discrete data. I used a backwards FD since it’s possible to know the angular position on the current frame and on as many previous frames as you care to store, but there’s no way to know what it will be in the future, which rules out the use of a central finite difference (these generally provide better estimates than backwards or forwards FDs). Wikipedia conveniently has a table of FD coefficients available.

One small issue is that the pitch and yaw angles can’t simply be plugged into a finite difference equation as-is since they wrap around at 360 degrees. This means that going from 350 to 10 degrees in yaw (for example) looks like a change of -340 degrees even though it almost certainly represents a change of +20 degrees in the player’s rotation. To deal with this, rather than storing the past four angles, I store the past three angular differences, then use them to work backwards from the current angular position when evaluating the finite difference equation. On each frame, I compute the current angle minus the previous angle; if the magnitude of this difference is 180 degrees or less, the difference is simply stored. However, if it’s more than 180 degrees, the difference is recomputed with the larger of the two angles shifted by 360 degrees.

For example, in the theta1 = 350, theta2 = 10 case, since 10 - 350 = -340 and |-340| > 180, the difference would be recalculated as 10 - (350 - 360) = 20.

The rest of my implementation uses the standard tangential velocity = angular velocity cross radial position circular motion equation discussed previously.

Of course, as I mentioned above, this results in rather high tangential velocities that, although technically correct, just don’t feel right. So far, I’ve obtained the most satisfactory results by scaling down the magnitude of the pitch and yaw angular velocity vectors by 5 and clamping the magnitude of the overall tangential velocity vector to 10 m/s, but I’d welcome any other ideas.

You can also use the LinearAcceleration() function here:

http://wiki.unity3d.com/index.php/3d_Math_functions