• 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
3
Question by The Spaniard · Jul 03, 2012 at 12:02 AM · rotationphysicsquaternions

How to use target rotation on a configurable joint to make the object point in a certain direction?

Hello, I'm trying to set up the player carrying a box in my first person game, using a configurable joint, and I've managed to get it all working except from the rotation of the box. I would like it such that the front face of the box always towards the player (on the horizontal plane) and the bottom face of the player always points downwards in the direction of gravity. The configurable joint is set connecting the box to the player camera, so that the box is the child of the camera, which in turn is the child of the player object. This is necessary for smooth movement of the box with the player. All the configurable joint properties are set in local space.

However, I can't for the life of me understand quaternions, and I can't get the rotation to work. Any help would be greatly appreciated. Ideally, the box's rotation as the player moves should be like that found in Portal, but with a "bouncier" feel due to the physics joint.

Thank you in advance,

The Spaniard

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
10
Best Answer

Answer by mstevenson · Feb 15, 2013 at 06:48 AM

A configurable joint's target rotation is difficult to compute. Joints have their own coordinate space, and they always begin with a rotation of Quaternion.identity (equivalent to no rotation at all) regardless of their transform's local or world rotation.

I've written two extension methods that allow you to easily set a ConfigurableJoint's target rotation using either a local or world rotation value. You'll need to cache your joint's local or world rotation on Start (depending on which method you intend to use) so that these methods can counter-rotate the value during the calculation.

Example usage:

 var startRotation = transform.localRotation;
 var myJoint = GetComponent<ConfigurableJoint> ();
 myJoint.SetTargetRotationLocal (Quaternion.Euler (0, 90, 0), startRotation);

ConfigurableJointExtensions.cs:

 public static class ConfigurableJointExtensions {
     /// <summary>
     /// Sets a joint's targetRotation to match a given local rotation.
     /// The joint transform's local rotation must be cached on Start and passed into this method.
     /// </summary>
     public static void SetTargetRotationLocal (this ConfigurableJoint joint, Quaternion targetLocalRotation, Quaternion startLocalRotation)
     {
         if (joint.configuredInWorldSpace) {
             Debug.LogError ("SetTargetRotationLocal should not be used with joints that are configured in world space. For world space joints, use SetTargetRotation.", joint);
         }
         SetTargetRotationInternal (joint, targetLocalRotation, startLocalRotation, Space.Self);
     }
     
     /// <summary>
     /// Sets a joint's targetRotation to match a given world rotation.
     /// The joint transform's world rotation must be cached on Start and passed into this method.
     /// </summary>
     public static void SetTargetRotation (this ConfigurableJoint joint, Quaternion targetWorldRotation, Quaternion startWorldRotation)
     {
         if (!joint.configuredInWorldSpace) {
             Debug.LogError ("SetTargetRotation must be used with joints that are configured in world space. For local space joints, use SetTargetRotationLocal.", joint);
         }
         SetTargetRotationInternal (joint, targetWorldRotation, startWorldRotation, Space.World);
     }
     
     static void SetTargetRotationInternal (this ConfigurableJoint joint, Quaternion targetRotation, Quaternion startRotation, Space space)
     {
         // Calculate the rotation expressed by the joint's axis and secondary axis
         var right = joint.axis;
         var forward = Vector3.Cross (joint.axis, joint.secondaryAxis).normalized;
         var up = Vector3.Cross (forward, right).normalized;
         Quaternion worldToJointSpace = Quaternion.LookRotation (forward, up);
         
         // Transform into world space
         Quaternion resultRotation = Quaternion.Inverse (worldToJointSpace);
         
         // Counter-rotate and apply the new local rotation.
         // Joint space is the inverse of world space, so we need to invert our value
         if (space == Space.World) {
             resultRotation *= startRotation * Quaternion.Inverse (targetRotation);
         } else {
             resultRotation *= Quaternion.Inverse (targetRotation) * startRotation;
         }
         
         // Transform back into joint space
         resultRotation *= worldToJointSpace;
         
         // Set target rotation to our newly calculated rotation
         joint.targetRotation = resultRotation;
     }
 }

I've posted this code to Gist and will keep it updated if any modifications are required as I continue using these methods:

https://gist.github.com/mstevenson/4958837

Comment
Add comment · Show 9 · 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 aeroson · Aug 01, 2013 at 06:49 PM 0
Share

Thank you. $$anonymous$$ake sure your angular motor mode is set to position, if it is not it will try to reach targetAngularVelocity as well at the same time.

avatar image HarvesteR · Feb 15, 2014 at 04:50 PM 0
Share

Thank you!! I've been scratching my head about this for the last couple of weeks...

Originally I had tried converting local to/from joint space by usin Quaternion.FromToRotation(axis, Vector3.right), but without the secondary axis as a term, that will fail on several situations.

Your method is far more reliable. I love how you created the jointToWorld rotation.

Cheers!

avatar image Oxters · Mar 30, 2020 at 01:09 PM 1
Share

While this is an old thread, I just wanted to share my experience. @mstevenson 's answer worked for me and gave me the correct rotation, but it had one issue. If you have say 30 configurable joints in the scene, there is a significant slow down. I think the reason is because there are two cross functions. Anyway I came up with an alternative that worked for me and is faster for my 30 joints.

 /// <summary>
         /// Sets the target rotation of the joint to be the given rotation relative to the original rotation
         /// </summary>
         /// <param name="joint">The joint whose target rotation is to be set</param>
         /// <param name="currentRotation">The orientation you would like the joint to be in</param>
         /// <param name="originalRotation">The original orientation of the joint</param>
         public static void SetTargetRotation(this ConfigurableJoint joint, Quaternion currentRotation, Quaternion originalRotation)
         {
             joint.targetRotation = Quaternion.identity * (originalRotation * Quaternion.Inverse(currentRotation));
         }


I've added the function to my helpers repo here.

avatar image godfreyidk Oxters · Apr 17, 2020 at 02:00 PM 0
Share

@Oxters, does your extension replace the SetTargetRotationInternal() method that deals with Cross products?

avatar image Oxters godfreyidk · Apr 17, 2020 at 02:20 PM 0
Share

The function I wrote is it's own thing. So you would make the static class with only the function I wrote in it.

Show more comments
avatar image
2

Answer by The-Arc-Games · Jul 03, 2012 at 08:42 AM

You usually sort this by means of parenting. Basically, very much likely the box model will have some 'local' axes that are different from unity's world axes, and thus what's "forward" or "up" for the box, faces in a different direction than unity's world.

To fix this, you create an empty gameobject, assign the box model as a child of this, and orient -the box- model to align to the parent, world aligned object.

This way, if you

 parentgameobject.transform.LookAt(Vector3.Forward);

you'll see that the box actually looks forward. The only inconvenience is that you will need to apply joint, collider and rigidbody to the -parent-, and thus handling becomes a little less intuitive.

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 True_Beef · Feb 09, 2020 at 12:20 PM

Hello from the future!

Sorry to perform necromancy, but I wanted to post something for all to see when hitting the same Quaternion brick-walls that I have gotten multiple concussions from.


Almost any sane person thinks of rotations as being on a coordinate plane of X , Y and Z. This is true, and can be applied, however suffers from various issues, and also wont work with unity's joint system (PhysX).

The issue is that most of the Quaternions in unity present themselves as Euler angles to the untrained eye. It isn't until you start messing with them that you realize they AREN'T, and then don't know where to go after the ensuing rage of not understanding why your rotations JUST WONT FREAKING WORK.


I've found this AMAZING teacher presenting Quaternions in an understandable format that I think a lot of people could benefit from. I didn't get it the first time, but after a few re-watches and taking some notes (not unlike a uni course) it clicked, and I was able to apply it in unity. Take a look, and evolve to a quaternion master!

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.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

11 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

Related Questions

Boat Rotation in 2 axis 0 Answers

How to keep rotation from switching between - and + after a 360? 0 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Rotating an object in level editor 1 Answer

Rotating an object to match a rigidbody's direction of movement. 2 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges