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
1
Question by schizmo · Oct 03, 2016 at 06:01 AM · quaternionlerpquaternionslerping

[SOLVED] Rotation/angled offset in Quaternion.Lerp for a carried GameObject

I'm working on a first person game (more of an anti game) where the player can carry and throw various game objects.

When a key is pressed, the script first checks to see if an object can be grabbed or used, and if it can be grabbed it starts a coroutine to hold and carry the object. The coroutine functions for the duration that the object is held, Slerping the heldObject position and Lerping the heldObject rotation against the position and rotation of the main camera respectively. It performs very well, and any direction the camera rotates in, the heldObject also rotates in that direction.

However, due to the way Lerp/Slerp function, when grabbing the heldObject the heldObject rotates to face away from the camera, no matter what orientation the object was in when it was picked up. As a result, items on the floor or against a surface often rotate immediately into surrounding objects, either pushing the other objects or stalling the heldObject in some way, causing issues.

What I would like to do is add an offset to the Lerp rotation so that the heldObject maintains its initial orientation from the mainCamera perspective, but still Lerp rotation from the mainCamera.

As an example, if i grab a cube with the left side of the cube facing the mainCamera, I want the left side to continue facing the mainCamera when the player carries the object around. currently, grabbing a cube quickly rotates it so the back side is facing the camera, and that causes issues.

the relevant portion of my script is as follows:

 IEnumerator HoldObject (GameObject heldObject) {
         holding = true;
         heldObject.transform.SetParent (null); //detach heldObject from any parent, like drawers or surfaces
         heldObject.gameObject.GetComponent<Rigidbody> ().velocity = Vector3.zero; //prevent existing velocity from affecting carry
         heldObject.gameObject.GetComponent<Rigidbody> ().angularVelocity = Vector3.zero; //prevent existing angular veloctiy from affecting carry
         heldObject.gameObject.GetComponent<Rigidbody> ().useGravity = false; //prevent gravity from affecting carry
         distance = Vector3.Distance (heldObject.transform.position, mainCamera.transform.position); //set initial carry distance to heldObject initial distance from player
 
         while (holding == true) { //the "HoldObject" coroutine only functions while holding an object
 
             //TODO: figure out how to calculate angular offset to shift rotation so that the object doesn't automatically snap forward
 
             heldObject.transform.position = Vector3.Slerp (heldObject.transform.position, mainCamera.transform.position + mainCamera.transform.forward * distance, 0.1f);
             heldObject.transform.rotation = Quaternion.Lerp (heldObject.transform.rotation, mainCamera.transform.rotation, 0.1f);
 
             if (Input.GetAxis ("Mouse ScrollWheel") > 0f) { //scroll mousewheel up to increase distance of heldObject
                 if (distance < 3f) {
                     distance += 0.2f;
                 }
             }
 
             if (Input.GetAxis ("Mouse ScrollWheel") < 0f) { //scroll mousewheel down to decrease distance of heldObject
                 if (distance > 1f) {
                     distance -= 0.2f;
                 }
             }
 
             yield return new WaitForFixedUpdate();
 
         }
     }

I am aware that a * operator can be used to mix/add/multiply/something two Quaternions together, and I have tried to create a Quaternion offset at the start of the coroutine using various methods (Angle, AngleAxis, FromToRotation, LookRotation) between the mainCamera and the heldObject, but every single one results in the heldObject spinning wildly out of control. The only time it doesn't spin wildly is when the offset is very near 0, which happens in some configurations on the initial grab as the heldObject.transform.rotation is 0, 0, 0 in the world by default for many of the objects I'm testing with.

I imagine the final code for rotation would look something like this:

         heldObject.transform.rotation = (Quaternion.Lerp (heldObject.transform.rotation, mainCamera.transform.rotation, 0.1f) * offset);

but I cannot figure out how to create a proper offset that doesn't send my heldObjects into a tailspin.

any help would be appreciated, I'm still somewhat new this so hopefully I haven't left out a vital detail that would lead someone else to a correct answer to the problem I'm having.

Ultimately if it can't be fixed it still behaves beautifully, I'm just being nit-picky about the behavior of the script and I'd really prefer to perfect it.

Thank you

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

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Mindmapfreak · Oct 03, 2016 at 10:39 PM

If I undestand you correctly you want something like:

 //When picking up the object
 offset = Quaternion.Inverse(mainCamera.transform.rotation) * heldObject.transform.rotation;
 //Then
 heldObject.transform.rotation = mainCamera.transform.rotation * offset;
 //Or with lerp (remove the line above if you use this one and vice versa)
 heldObject.transform.rotation = Quaternion.Lerp(heldObject.transform.rotation, mainCamera.transform.rotation * offset, 6.0f*Time.deltaTime); //You should probably use Time.deltaTime in your timed calculations to make your game framerate independent

I am not sure what you mean by

but still Lerp rotation from the mainCamera

and why you Lerp the rotation, shouldn't the object instantly have the correct rotation?

Comment
Add comment · Show 1 · 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 schizmo · Oct 03, 2016 at 11:00 PM 0
Share

Both solutions work with slight variations, you helped lead me to the source of my problem! I was adding the offset to the outside of the Lerp calculation, which forced the Lerp to calculate against the offset at the start of each frame. By including the offset within the Lerp (or disregarding it entirely, per your example on line 4) the desired result is achieved.

I was just overcomplicating things when the solution was simple. thank you!

avatar image
0

Answer by txzeenath · Oct 04, 2016 at 03:00 AM

Just an idea from a noob.

You may need calculate a transform with Quaternion.Inverse and the item's original rotation to get a proper offset. (Quaternion.Inverse(itemRot)*cameraRot). If I remember right, multiplying by the inverse will give you your relative transform.

I'm sure someone who actually has practice with this stuff could give a clean example. (My multiplication order is probably flipped too lol)


You could also Lerp the rotation based on Vector3.Distance between the target position and current position. So the closer it gets to the target position the higher the lerp "step" on rotation. Which should give it a smooth rotation that gets faster as it approaches center.

 float bufferZone = 100F;
 float minSpeed = 0.001F;
 float maxSpeed = 0.1F;
 float deltaDist = Vector3.Distance(heldObject.transform.position,mainCamera.transform.forward * distance);
 float step = MathF.Clamp(bufferZone/deltaDist,minSpeed,maxSpeed);
 heldObject.transform.rotation = Quaternion.Lerp (heldObject.transform.rotation, mainCamera.transform.rotation, step);


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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Copy rotation of targetObject to current object with an influence in the range from 0-1. 0 Answers

Quaternion.Lerp and Vector3.MoveTowards arent smoothing 1 Answer

Changing rotation of Quaternion 0 Answers

Quaternion.Lerp and Vector3.MoveTowards arent smoothing 1 Answer

Vector3.lerp giving me the incorrect Quaternion 1 Answer


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