Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 csaurus · Oct 24, 2013 at 12:32 PM · quaternionslerpturret

Turret Slerp rotation and clamping

Firstly, following on from my turret rotation problem, which is now working wonderfully, I now need to smoothly rotate the turret between targets.

I tried doing it using:

 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetVector,hardpointPosition.transform.up), Time.deltaTime * turnspeed);
             
 gun.transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target.position-transform.position,hardpointPosition.transform.up), Time.deltaTime * turnspeed);

While this did make the turret rotates as expected, the gun can now no longer rotate up or down, which is useless to me. How can I go about fixing this?

Secondly, I also need to prevent the gun from rotating too far downwards, to stop it from trying to aim through the bottom of the turret base. I only need to worry about the maximum downwards angle, as when the gun points directly up, the turret base rotates around to face the target, meaning the gun cannot rotate more than 90 degrees up. What's the best way to go about sorting this out?

Thanks in advance.

Comment
Add comment · Show 2
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 Brian@Artific · Oct 24, 2013 at 04:21 PM 0
Share

Is it possible to construct your turret so that the turret base (rotator) and gun (elevator) are separate GameObjects (the gun being a child of the turret base)?

avatar image csaurus · Oct 24, 2013 at 04:39 PM 0
Share

That's how I have it set up at the moment: Ship > Turret > Gun. The gun variable in the code is just a public Transform that I've assigned the gun model to.

2 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by Brian@Artific · Oct 24, 2013 at 06:44 PM

Here's an excerpt from the Gun script I created for a tank game we worked on last year. In brief: it checks whether the aim point is left or right of a plane orthogonal to the local right of the rotating part of the turret (the turret base) and then checks whether the aim point is above or below a plane orthogonal to the local up of the elevating part of the turret (the gun). It could probably use some optimization, but you're welcome to it...

     /// <summary>
     /// The transform to rotate around the X axis (elevate) when aiming.
     /// </summary>
     public Transform elevator;
 
     /// <summary>
     /// The maximum elevation, in degress, below the zero point.
     /// </summary>
     public float minElevation;
 
     /// <summary>
     /// The maximum elevation, in degress, above the zero point.
     /// </summary>
     public float maxElevation;
 
     /// <summary>
     /// The transform to rotate around the Y axis (rotate) when aiming.
     /// </summary>
     public Transform rotator;
 
     /// <summary>
     /// The maximum rotation, in degress, to the left of the zero point.
     /// </summary>
     public float minRotation;
 
     /// <summary>
     /// The maximum rotation, in degress, to the right of the zero point.
     /// </summary>
     public float maxRotation;
 
     /// <summary>
     /// The accuracy of the weapon, in meters.
     /// </summary>
     public float accuracy;
 
     /// <summary>
     /// The speed at which the weapon may be turned.
     /// </summary>
     public float turnSpeed;
 
     /// <summary>
     /// Rotates and elevates the weapon torwards the target.
     /// </summary>
     /// <param name="target">The target to aim at.</param>
     public virtual void Aim(Vector3 target)
     {
         // Get a plane through the rotation of the weapon
         Plane rot = new Plane(rotator.right, rotator.position);
         if (Mathf.Abs(rot.GetDistanceToPoint(target)) < accuracy)
             return;
 
         // And rotate towards target
         if (rot.GetSide(target))
             Rotate(1.0f); //right
         else
             Rotate(-1.0f); //left
 
         // Get a plane through the elevation of the weapon
         Plane elev = new Plane(elevator.up, elevator.position);
         if (Mathf.Abs(elev.GetDistanceToPoint(target)) < accuracy)
             return;
 
         // And elevate towards target
         if (elev.GetSide(target))
             Elevate(1.0f); //up
         else
             Elevate(-1.0f); //down
     }
 
     /// <summary>
     /// Pivots the weapon up(+) and down(-).
     /// </summary>
     /// <param name="direction">The direction to pivot; up is positive, down is negative.</param>
     public virtual void Elevate(float direction)
     {
         // Clamp the direction input between -1 and 1...
         direction = Mathf.Clamp(-direction, -1.0f, 1.0f);
 
         // Calculate the new angle...
         float angle = elevator.localEulerAngles.x + direction * turnSpeed * Time.deltaTime;
         if (angle > 180)
             angle -= 360;
 
         // Clamp the new angle between the given minimum and maximum...
         angle = Mathf.Clamp(angle, -maxElevation, -minElevation);
 
         // Update the transform...
         elevator.localEulerAngles = new Vector3(angle, elevator.localEulerAngles.y, elevator.localEulerAngles.z);
     }
 
     /// <summary>
     /// Pivots the weapon right(+) and left(-).
     /// </summary>
     /// <param name="direction">The direction to pivot; right is positive, left is negative.</param>
     public virtual void Rotate(float direction)
     {
         // Clamp the direction input between -1 and 1...
         direction = Mathf.Clamp(direction, -1.0f, 1.0f);
 
         // Calculate the new angle...
         float angle = rotator.localEulerAngles.y + direction * turnSpeed * Time.deltaTime;
         if (angle > 180)
             angle -= 360;
 
         // Clamp the new angle between the given minimum and maximum...
         if (Mathf.Abs(minRotation) + Mathf.Abs(maxRotation) > 0)
             angle = Mathf.Clamp(angle, minRotation, maxRotation);
 
         // Update the transform...
         rotator.localEulerAngles = new Vector3(rotator.localEulerAngles.x, angle, rotator.localEulerAngles.z);
     }
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 csaurus · Oct 24, 2013 at 09:15 PM 0
Share

How would I go about adding a target generated from another script into that?

avatar image Brian@Artific · Oct 24, 2013 at 09:58 PM 0
Share

Just add a public variable for the target and pass it to the Aim method in Update, like so:

 public Transform myTarget;
 
 void Update()
 {
     Aim(myTarget.position);
 }
avatar image ZenythStudios · Jan 29, 2019 at 12:53 PM 0
Share

Thanks! This script was a massive help in figuring out a solution for my problem.

avatar image
0

Answer by robertbu · Oct 24, 2013 at 05:11 PM

I have a couple of untested solutions for you. Usually for something like this, I test the solution, but I can't right now. First take a look at my gun script in this answer:

http://answers.unity3d.com/questions/388185/make-the-turret-automatically-rotate-to-look-at-wh.html

It works by managing the gun only on the local rotation, and gun rotates only on its local 'x' axis. The code does this by "transporting" the point so it is effectively (in local coordinates) right in front of the gun so the gun is "forced" to only rotate on the 'x' axis.

For your use, given the turret can have any arbitrary rotation, things are more complex. For calculating the 'Z' distance, you will need to calculate the distance from the pivot point to the point you projected on the plane you used in my last answer. For the 'y' height it will be the signed distance above/below the plane the turret sits on. These two values can be to construct the local rotation of the gun using Quaternion.LookRotation().

As for limiting the rotation, my suggestion is to start with the gun (in the editor) at the midpoint of its travel range. So if the gun could travel up to 90 and down to -20, you would start the gun with an 'x' axis rotation of 35.0. Save the local rotation of the gun in a variable in Start(). Each time you calculate a new rotation, test it with Quaternion.Angle() against the local rotation you saved in Start(). If the angle is above the maximum travel angle (one side), then just don't assign it to 'transform.localRotation'.

Comment
Add comment · Show 15 · 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 csaurus · Oct 24, 2013 at 09:14 PM 0
Share

Well I had a go at your suggestion, and I'm obviously doing something wrong.

 zVector = targetVector - gun.transform.position;
             zVectorDistance = zVector.magnitude;
             
             yHeight = ($$anonymous$$ath3d.SignedDistancePlanePoint(gun.transform.up,gun.transform.position,target.transform.position));
             newTarget = new Vector3(target.position.x,yHeight,zVectorDistance);

Now this is completely wrong, as the turret ends up ai$$anonymous$$g completely off target.

What am I doing wrong?

avatar image robertbu · Oct 24, 2013 at 10:03 PM 0
Share

First, I'm assu$$anonymous$$g that 'targetVector' is the point on plane you calculated for the rotation of the turret. And to make this work without undue complication, the pivot of the gun and the turret should be in the same place. If so, you are mostly right. The final line needs to be:

 newTarget = new Vector3(0.0f,yHeight,zVectorDistance);

That is, you are putting the point directly in front of the local forward. And the calculated rotation is assigned to 'transform.localRotation' of the gun.

avatar image csaurus · Oct 25, 2013 at 07:58 AM 0
Share
 tempRotation = Quaternion.Slerp(gun.transform.localRotation, Quaternion.LookRotation(newTarget,hardpointPosition.transform.up), Time.deltaTime * turretTurnSpeed);
             angle = Quaternion.Angle(tempRotation,localRotation);
             if(angle <93)
             {
                 gun.transform.localRotation = tempRotation;
             }

That's what I'm using right now. The turret is Slerping properly between targets, but now the gun is stuck at a 45 degree angle, and won't aim up or down.

avatar image robertbu · Oct 25, 2013 at 02:17 PM 0
Share

Is it just the angle that is the problem? That is, without the '`if(angle <93)`', does the gun now aim correctly?

avatar image robertbu · Oct 26, 2013 at 07:37 AM 1
Share

I took a bit of time to code up an example. I wanted to make sure what I was telling you would work. Here is a package of my test project:

www.laughingloops.com/Turret.unitypackage

You can use the arrow keys to rotate the base to test other angles.

And here is the turret script. It took surprising few lines of code. It works just as I've indicated above. Note to avoid duplicate calculation, I've combined the turret and gun scripts.

 #pragma strict
 
 var target : Transform;
 var gun : Transform;
 var turretDegreesPerSecond : float = 45.0;
 var gunDegreesPerSecond : float = 45.0;
 
 var maxGunAngle = 45.0;
 
 private var qTurret : Quaternion;
 private var qGun : Quaternion;
 private var qGunStart : Quaternion;
 private var trans : Transform;
 
 function Start() {
     trans = transform;    
     qGunStart = gun.transform.localRotation;
 }
 
 function Update () {
     var distanceToPlane = Vector3.Dot(trans.up, target.position - trans.position);
     var planePoint = target.position - trans.up * distanceToPlane;
     
     qTurret = Quaternion.LookRotation(planePoint - trans.position, transform.up);
     transform.rotation = Quaternion.RotateTowards(transform.rotation, qTurret, turretDegreesPerSecond * Time.deltaTime);
     
     var v3 = Vector3(0.0, distanceToPlane, (planePoint - transform.position).magnitude);
     qGun = Quaternion.LookRotation(v3);
     
     if (Quaternion.Angle(qGunStart, qGun) <= maxGunAngle)
         gun.localRotation = Quaternion.RotateTowards(gun.localRotation, qGun, gunDegreesPerSecond * Time.deltaTime);
     else
         Debug.Log("Target beyond gun range");
 }


Show more comments

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

17 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

Related Questions

Extrapolating a new rotation from two existing rotations. 2 Answers

Quaternion Rotation Smooth 1 Answer

Rotation direction in coroutine 2 Answers

Rotating Rigidbodies 2 Answers

Turret on Tank rotating fine until I'm not flat on ground 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