Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by NewPath · Oct 13, 2015 at 07:29 PM · rotationphysicscollisions

How to smoothly re-orient an object after a collision?

I have a vehicle traveling in a forward motion, and for the most part I always want its rotation to be 0,0,0 (it can "strafe" but not turn).

There are some stationary obstacles with standard colliders. When the vehicle hits one, it knocks the vehicle around a bit but I want the vehicle to then correct its orientation and continue moving forward at a rotation of 0,0,0.

Here are a few things I've tried that aren't working:

First I've tried just doing a continual correction with some smoothing, like this:

 _rb.rotation = Quaternion.Lerp(_rb.rotation, Quaternion.Euler(0, 0, 0), smoothing * Time.deltaTime);

Where _rb is the vehicle's RigidBody and smoothing is a float (set around 10). This almost works, because it does correct the orientation a bit, but of course the problem with this kind of smoothing is that you never reach the target value of the lerp. It just makes exponentially smaller increments towards it. At some point I have to reach 0,0,0 or the vehicle drifts off to a side rather than moving straight.

I also tried setting up a time-stepped lerp. I gave a total time and then on collision I set a timer to that value and then calculate the steps like this:

     if (_timer > 0)
     {
         float step = 1 - (_timer / forwardCorrectionTime);
         _rb.rotation = Quaternion.Lerp(_rb.rotation, Quaternion.Euler(0, 0, 0), step);
         _timer -= Time.deltaTime;
     }

This sort of works if I set the correction time to something reasonably long, like greater than 5 seconds, but I want the correction to happen more quickly. If I lower the time then it will perform the correction, but then the ship jukes back to an incorrect rotation - I'm guessing that perhaps the physics engine is still performing the effects of the collision after the corrective rotation.

The only reliable method I've found is simply forcing the rotation instead of using a lerp, but this of course kills the effect of the collision and is not what I'm going for.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by toromano · Oct 19, 2015 at 12:28 PM

Before attempting to modify position or rotation of a rigidbody, you should make it kinematic. Did you try that ? Something like:

 if (mReorientationEnabled)
 {
     _rb.isKinematic = true;
     _rb.rotation = Quaternion.Lerp(_rb.rotation, Quaternion.Euler(0, 0, 0), smoothing * Time.deltaTime);
 }
 else
 {
     _rb.isKinematic = false;
 }





Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image NewPath · Oct 20, 2015 at 04:07 PM 0
Share

I haven't tried that because I actually still want physics to be active even while I'm correcting the orientation. For instance, the craft could hit an object that sends it on a collision course with another object, or another object could collide with it while I'm correcting - in which case I would just re-adjust or re-start the correction.

avatar image PictonicStudio NewPath · Oct 20, 2015 at 05:24 PM 0
Share

I don't want to put this in an answer yet, but when you lerp the angle back reset the velocity so it doesnt have any torque.

avatar image toromano NewPath · Oct 20, 2015 at 06:32 PM 0
Share

If you want to modify orientation while physics is active, you need something like PID controller for your craft's orientation. First give an impulse in up direction for your craft to have a space for orientation (if it is a ground vehicle), then give torque proportional to difference between your current orientation and target rotation.

avatar image
0

Answer by YoungDeveloper · Oct 19, 2015 at 12:46 PM

@toromano Mentioned lerp wil work but, technically it will never reach it's target, you will be creating zeno's paradox. You will (if ever) reach the target because of the float tail rounding. But this is important if getting to target is a thing and it has to be correct. For start Id use Vector3.MoveTowards() and edit localEulerAngles or rotation directly (converting my vector to Quaternion.Euler() first).

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Eno-Khaon · Oct 20, 2015 at 06:54 PM

Here's a thought on an approach to this... Let's say you want a slight delay after an impact, followed by a recovery time based on how far you were turned by the physics interaction:

 enum DrivingState {Driving, Crashing, Recovering}
 DrivingState state = DrivingState.Driving;
 
 // This can serve as a baseline multiplier for how long it takes to recover to drive again.
 // This can be further scaled if desired based on the severity of the impact (i.e. dot product of vehicle velocity and normal of face impacted)
 public float crashDelayMod; // in seconds
 // This, instead, is a multiplier for degrees-per-second to rotate
 public float recoveryDelayMod;
 float recoveryTimer; // Can be reused for the actual time spent on both states
 Quaternion crashRotation; // Where were you looking at the very last moment of the crash?
 float recoveryAngle; // The angle to correct for after impact, scaled on recovery speed by recoveryDelayMod
 
 // ...
 
 void OnCollisionEnter(Collision other)
 {
     if(!other.CompareTag("ground") // faster than (other.tag != "ground")
     {
         state = DrivingState.Crashing;
         recoveryTimer = 0.0f;
     }
 }
 
 void Update()
 {
     if(state != DrivingState.Crashing)
     {
         // Driving Controls handled here
         
         if(state == DrivingState.Recovering)
         {
             recoveryTimer += Time.deltaTime;
             float recoveryPercent = recoveryTimer * (recoveryDelayMod / recoveryAngle);
             _rb.rotation = Quaternion.Slerp(crashRotation, Quaternion.identity, recoveryPercent);
             if(recoveryPercent >= 1.0f)
             {
                 state = DrivingState.Driving;
             }
         }
     }
     else //if(state == DrivingState.Crashing) // The implied result
     {
         recoveryTimer += Time.deltaTime;
         if(recoveryTimer >= crashDelayMod)
         {
             crashRotation = _rb.rotation;
             recoveryTimer = 0;
             recoveryAngle = Quaternion.Angle(crashRotation, Quaternion.identity);
             if(recoveryAngle > 0) // Need to straighten out
             {
                 state = DrivingState.Recovering;
             }
             else // Didn't turn whatsoever from the impact
             {
                 state = DrivingState.Driving;
             }
         }
     }
 }

Just a heads up that I did write this without testing it, but hopefully this at least offers an idea of how this can be approached.

Edit: In the end, I forgot to turn the state back to "Driving" -- Whoops!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

41 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Compute the torque needed to rotate an object at a constant rate 3 Answers

Can't set Bounce Threshold below .3 0 Answers

More realistic physics? 0 Answers

move player to its rotating direction? 2 Answers

Returning a rigidbody back to its original x and z rotations through physics forces. 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges