Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 VVander · Apr 07, 2012 at 03:38 AM · rotationquaternionangleeuleranglesconstrain

How to Constrain Quaternion Rotations Over Time?

Right now in our first-person game we have an aiming system similar to (but not exactly like) Red Orchestra (http://www.youtube.com/watch?v=oiP82nAV9xM if you're not familiar): when the player moves the mouse, the screen will reorient perfectly, but the gun's aim will interpolate to follow the player's head with a little lag (to simulate imperfect aim when firing from the hip).

However, though right now the implementation we have works, it doesn't constrain the gun's movement when the player moves their aim too quickly for the gun to catch up. The result is that if the player moves the aim too quickly the gun will fall so far behind that it ends up just rotating around and around if the player moves their aim quickly enough. Anyway, here's the relevant code we have so far, along with some failed solutions I've already tried. Anyone have any ideas on how to solve this problem? Obviously I don't understand Quaternions well enough to solve this myself.

 public float maxAngle; //maximum angle of difference between gun and aim point
 public float aimDistance; //the distance at which to aim along the player's actual line of vision.
 public float aimSpeed; //the speed at which the gun point catches up to the view point
 private Vector3 aimPoint; //the line at which the gun is aiming - i.e., the line from the gun point to the point directly in front of from the player's vision. Currently sets the gun's rotation to follow to that point
 
 private void aimLook() //called once per frame from Update()
 {
     //calculate the aimPoint as the current look direction outwards aimDistance distance
     aimPoint = transform.forward * aimDistance;
     
     //calculate new rotation to have the gun look at the aimPoint
     Quaternion aimAtAimPoint = Quaternion.LookRotation(aimPoint);        

 //interpolate between the current aim and the desired aim point
     Quaternion modAimAtAimPoint = Quaternion.Lerp(unmodifiedAimRotation, aimAtAimPoint, Time.deltaTime * aimSpeed);
     


 //BEGIN SOLUTION ATTEMPT 1
         //if the interpolated rotation angles are too far away from the center, constrain them
         //Vector3 rotation = modAimAtAimPoint.eulerAngles;        
         
         //if(modAimAtAimPoint.eulerAngles.z > maxAngle || modAimAtAimPoint.eulerAngles.z < -maxAngle)
         //    rotation.z = maxAngle;
         //if(modAimAtAimPoint.eulerAngles.y > maxAngle || modAimAtAimPoint.eulerAngles.y < -maxAngle)
         //    rotation.y = maxAngle;
         //if(aimAtAimPoint.eulerAngles.z > maxAngle || aimAtAimPoint.eulerAngles.z < -maxAngle)
         //    rotation.z = maxAngle;
             
         //modAimAtAimPoint.eulerAngles = rotation;
 //END SOLUTION ATTEMPT 1
         
         
                 
         //BEGIN SOLUTION ATTEMPT 2
 //        Quaternion modAimAtAimPoint;
 //        float difference;
 //        
 //        //if the interpolated aim is too far away from the aimAtAimPoint, keep interpolating until it isn't
 //        do
 //        {
 //            //interpolate between the current aim and the desired aim point
 //            modAimAtAimPoint = Quaternion.Lerp(unmodifiedAimRotation, aimAtAimPoint, Time.deltaTime * aimSpeed + .1f);
 //            
 //            difference = Quaternion.Angle(modAimAtAimPoint, aimAtAimPoint);
 //            Debug.Log(difference);
 //        }while(difference > maxAngle || difference < -maxAngle);
 //        END SOLUTION ATTEMPT 2
     
     
     //set the gun's actual aim to the interpolated aim
     gunPoint.transform.rotation = modAimAtAimPoint;
 }
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

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by aldonaletto · Apr 07, 2012 at 04:14 AM

I did something similar once just Lerp'ing the weapon to follow its parent. That's my hierarchy:

Player
  Camera
    Weapon Holder <- script attached to this empty object
      Machine Gun
      Rocket Launcher
      Laser Gun
      etc.
That's the script:

var speed: float = 15; private var localRot: Quaternion; private var curRot: Quaternion;

function Start () { localRot = transform.localRotation; // save starting local rotation curRot = transform.rotation; }

function Update () { // targetRot is the ideal rotation: var targetRot = transform.parent.rotation localRot; // curRot follows targetRot with some delay: curRot = Quaternion.Lerp(curRot, targetRot, speed Time.deltaTime); transform.rotation = curRot; }

EDITED: I can't understand your script because some parts are missing, but I suppose it's similar to mine: you get the desired rotation and Lerp to it using Time.deltaTime (we both should use Slerp instead!).
Supposing aimAtAimPoint is the desired rotation and curRotation the current rotation, you can limit the angle between them with the following code (C#, this time!):

    public float maxAngle = 10;
    private Quaternion curRotation; // the current weapon rotation
    ...
    // Slerp to it over time:
    curRotation = Quaternion.Slerp(curRotation, aimAtAimPoint, Time.deltaTime * aimSpeed);
    float angle = Quaternion.Angle(curRotation, targetRot);
    if (angle > maxAngle){ // if maxAngle exceeded...
        // find max rotation using interpolation:
        curRotation = Quaternion.Slerp(aimAtAimPoint, curRotation, maxAngle/angle);
    }
    ...
How it works: if angle > maxAngle, the value maxAngle/angle is exactly what you need to find the max acceptable rotation by interpolating between aimAtAimPoint and curRotation. The interpolation must be linear in degrees, what means Slerp, the spherical interpolation.
Comment
Add comment · Show 2 · 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 VVander · Apr 07, 2012 at 05:25 PM 0
Share

Unfortunately that doesn't seem to work. It actually just makes the weapon keep the same rotation over time (it just Lerps the gun back to wherever it was pointing to begin with, no matter where the player is looking). I made sure to disable our previous rotation code so that didn't affect it, so I'm not sure why it's doing that.

Forgive me if I'm wrong, but it seems like your script would have the same problems in the end anyway (the gun not rotating fast enough if the player moves the camera too quickly). Our goal is to have the gun's rotation constrained so that it never points anywhere off screen from a first-person perspective.

avatar image aldonaletto · Apr 08, 2012 at 11:41 PM 0
Share

I don't know why my script didn't work in your case, but maybe it's due to differences in the hierarchy. Anyway, you can limit the max angle between the ideal and the delayed rotations using a smart trick with interpolation. Take a look at my answer: I edited it to include this limit (and translated it to C#, too...)

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

Object makes random jumps in rotation 1 Answer

Head and body rotate threshold 1 Answer

quaternion.eulerAngles 1:1 angle conversion 1 Answer

How do I clamp the Z-Axis Rotation for this code? 1 Answer

Rotating sprite through touch (storing current rotation) 0 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