0
Answered
Schazzwozzer 4 months ago • updated by Lazlo Bonin (Lead Developer) 4 months ago 3

I'm hoping someone can help me understand some strange behavior I'm seeing with Chronos.

I want to do a custom implementation of gravity. Normally, I'd simply uncheck Rigidbody.useGravity and do this:

private void FixedUpdate ()
{
    timeline.rigidbody.AddForce( Physics.gravity, ForceMode.Acceleration );
}

This works correctly with Unity's default physics (if I remove the timeline reference, of course). However, using this code alongside Chronos' scaled time (timescale is 2.0) causes major discrepancies, as this image shows:

The yellow sphere is simply a rigidbody with a Timeline. The green sphere is a rigidbody with a Timeline, using my custom gravity code. They both use the same global clock, mass, drag, bounciness, etc. As you can see, it's way off.

The problem isn't that I can't find the right formula. This one, for instance, works just fine in keeping the two objects synchronized.

private void FixedUpdate ()
{
    timeline.rigidbody.AddForce( Physics.gravity * timeline.fixedDeltaTime, ForceMode.VelocityChange );
}

I'm just curious: why? Am I overlooking something obvious, or is there some quirk to how Chronos works with ForceMode.Acceleration? Should I, as a rule, prefer to use Impulse and VelocityChange, multiplying by fixedDeltaTime myself?

Chronos Version:
2.2
Unity Version:
5.6.0f3
Under Review

Hi Schazzwozzer,

First, can you confirm that the issue is still present in the latest version (v.2.4.9)?

Also, can you paste a snippet of your "custom gravity code"?

If the issue persists in v.2.4.9, I'm afraid you'll have to stick to your manual adjustment for now. 

It's been more than 2 years now since I did all the physics accuracy calculations, so I must admit I'm a bit rusty on them. I remember going over multiple test cases with my physicist friend to make sure physics reacted the same way with all time scales, but obviously I must have missed some edge cases.

In other words, there shouldn't be a rule of thumb with ForceMode - every one should work out of the box. But I can't fix them yet if they don't. I do intend to review them all with a much more robust unit testing for v.3.0, but this might take a while. For version 2.x, I don't want to change the default calculations because it might break existing projects using Chronos. Chronos uses semantic versioning which only allows for backwards incompatibility on major version changes.

Can I ask what methods you used to draw the trajectory of the spheres? It might come in handy while I prepare v.3.0.

Cheers,

Lazlo

+1

Hi Lazlo,

The trajectory drawing is just the built-in Unity Trail Renderer component. No clever stuff even needed there!

So, turns out I've been using the latest version the whole time. I'm pretty sure, at least — I only purchased the package back in late May, which seems to be after 2.4.9 was released. I reported 2.2 because that's what I found in the changelog.pdf file that Chronos includes.

If you'd like to look at this further, I've uploaded a UnityPackage of my test scene. You'll need to import Chronos separately, of course. https://www.dropbox.com/s/0r47l6mzxb62vqy/ChronosGravitySimTest.unitypackage?dl=0

The test scene instantiates and launches spheres based on what's in the "Launcher" object's Launch Target Prefabs array. Included in the package are four sphere prefabs:

  • Non-Chronos, normal Unity gravity
  • Non-Chronos, simulated gravity
  • Chronos, normal Unity gravity
  • Chronos, simulated gravity

The first three produce essentially the same trajectories. The fourth, when its Clock is a non-1 value, does not.

The simulated gravity script is included, of course, but if you'd like a quick glimpse of it, here's the entire thing:

public class SimulatedGravity : MonoBehaviour
{
    private new Rigidbody rigidbody;
    private Timeline timeline;

   private void Awake ()
    {
        rigidbody = GetComponentInChildren<Rigidbody>();
        timeline = GetComponentInChildren<Timeline>();
   }     private void FixedUpdate ()
    {
        if( timeline )
        {
            timeline.rigidbody.AddForce( Physics.gravity, ForceMode.Acceleration );
            //timeline.rigidbody.AddForce( Physics.gravity * timeline.fixedDeltaTime, ForceMode.VelocityChange );
        }
        else
            rigidbody.AddForce( Physics.gravity, ForceMode.Acceleration );
   }
}

The commented-out line is the formula that DOES replicate standard gravity.

Anyway, I understand that you can't issue a quick fix. I mostly wanted to be sure there wasn't something obvious that I was overlooking (which could easily still be the case), and if not, pass that along. For now, I'll continue using the formula I've just mentioned.

Thanks for your time.

Answered

Many thanks for your time and the thorough report. I'll take another crack at it whenever I get to v.3.0. Using a trail renderer is clever, haha! It didn't even cross my mind.