• 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
Question by UnityAccnt · Apr 04, 2019 at 09:48 AM · rotationquaternionaxisanglesvectors

Rotating tank barrel on X axis while the parent Turret rotates on Y axis

I've been trying to get this to work for two days, most posts say to put x and z to zero but that causes the barrel to keep looking at the same spot regardless of the parent object rotating on the Y. I'm exhausted and frustrated that I haven't been able to solve it. All the commented code is everything I've already tried. Let me know if you need any additional information. The turret rotates correctly but the barrel keeps rotating on its own y and z when it should only move up and down (on the x axis) to look at the target.

 public Transform target;
 public Transform barrel;
 public float turretSpeed;
 public Vector3 positionOffset;
 // Start is called before the first frame update
 void Start()
 {
     
 }

 // Update is called once per frame
 void Update()
 {
     //Move Turret
     Vector3 turretVectorToTarget = target.position - (transform.position - positionOffset);
     turretVectorToTarget.y = 0;
     Quaternion turretVectorToQuaternion = Quaternion.LookRotation(turretVectorToTarget);
     float step = turretSpeed * Time.deltaTime;
     transform.rotation =  Quaternion.RotateTowards(transform.rotation, turretVectorToQuaternion, step);

     //Debug.Log("TurretVector(" + turretVectorToTarget.x + ", " + turretVectorToTarget.y + ", " + turretVectorToTarget.z + ")");
     Debug.DrawRay(transform.position, turretVectorToTarget, Color.red);

     //Move Barrel
     //if (transform.rotation == turretVectorToQuaternion)
     //{
         //Vector3 test = target.transform.position - new Vector3(transform.position.x, barrel.transform.position.y, transform.position.z);

         Vector3 barrelVectorToTarget = target.position - (barrel.transform.position - positionOffset);
         //Vector3 barrelVectorToTargetLevel = target.position - (barrel.transform.position - positionOffset);
         //barrelVectorToTargetLevel.y = 0;
        //float AngleIWantToRotateBy = Vector3.Angle(barrelVectorToTargetLevel, barrelVectorToTarget);

         //Debug.Log("Angle Size: " + AngleIWantToRotateBy);
         //Angle between the two
         //float sign = Mathf.Sign(barrelVectorToTarget.y - barrelVectorToTargetLevel.y);
         //float angleBetween = Vector3.Angle(barrelVectorToTarget, barrel.transform.forward) * sign;

         //barrel.transform.rotation = Quaternion.Euler(angleBetween, 0, 0);

         //Setting these to zero will result in the barrel pointing directly up or down
         //barrelVectorToTarget.x = 0;
         //barrelVectorToTarget.z = 0;

         //Get the rotation that matches the vector
         Quaternion barrelVectorToQuaternion = Quaternion.LookRotation(barrelVectorToTarget);

     barrel.transform.rotation = Quaternion.Euler(barrelVectorToTarget);
     //barrel.localEulerAngles = new Vector3(barrel.localEulerAngles.x, 0, 0);

     //barrel.transform.rotation = Quaternion.Euler(angleBetween, 0, 0);//
     //barrel.transform.rotation = Quaternion.RotateTowards(barrel.transform.rotation, barrelVectorToQuaternion, step);
     Debug.Log("BarrelVector(" + barrelVectorToTarget.x + ", " + barrelVectorToTarget.y + ", " + barrelVectorToTarget.z + ")");
     Debug.Log("BarrelVectorQuaternion(" + barrelVectorToQuaternion.x + ", " + barrelVectorToQuaternion.y + ", " + barrelVectorToQuaternion.z + ", " + barrelVectorToQuaternion.w + ")");

     Debug.DrawRay(barrel.transform.position, barrelVectorToTarget, Color.blue);
         //Debug.DrawRay(barrel.transform.position, barrelVectorToTargetLevel, Color.cyan);
     //}
Comment

People who like this

0 Show 0
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

Answer by metalted · Apr 04, 2019 at 12:32 PM

So if I get this right, you have a turret that rotates on the y-axis, so just turns around on the playing field and a barrel that is attached to this that should only change an angle for up and down. Quaternions are tricky. Can you do it with transform.LookAt()? That way you can easily check if your target positioning is alright.


If you want to use transform.LookAt() for just one plane, you need to have the other axis at a constant value. Your turret will only rotate in the XZ-plane and will not look at the Y, that's what the barrel is for. So this example can be used for your turret:

 //This will be transforms of course, but just for the example:
 Vector3 targetPosition = new Vector3(2, 2, 2);
 Vector3 turretPosition = new Vector3(0, 0, 0);
 
 /*This means the target is floating in the air, 2x2 units away.
 You want the turret to ignore the fact that it is floating and only look at the 2x2 units away. As if the target was at 2,0,2.  Notice that the 0 is the same as the turretPosition. So the target will be at: */
 
 Vector3 turretTargetPosition = new Vector3(targetPosition.x, turretPosition.y, targetPosition.z);
 
 /*Now because the turret is already looking in the right direction, you can just use a simple lookAt for the barrel. The barrel and turrets forward direction will always be the same. The difference is that the barrel can move up while the turret won't*/
 
 turret.transform.LookAt(turretTargetPosition);
 barrel.transform.LookAt(targetPosition);
 
 /* Because its a barrel you want it to rotate at the end, where it is attached to the turret. So you need to add another empty gameobject in your turret that acts as the pivot point. It will be positioned at local 0,0,0. This gameobject will point its forward direction towards the target, so your barrel will be a child of this object and needs to be attached in the forward direction also. The above two lines of code becomes:*/
 
 turret.transform.LookAt(turretTargetPosition);
 barrelPivot.transform.LookAt(targetPosition);
 

Because this is a simpler way of doing it, it's easier to understand if something goes wrong. When you got the lookAt down, you can start changing the lookAt function into some nice smooth lerping quaternion stuff. Also I see you tried to set the eulerAngles, this is not forbidden but is not recommended.


If you don't want to use the pure code quaternions, you could use the lookAt transforms as your target rotation. You just hide them, or use empty gameObjects. Those will look at the objects directly while you lerp your real barrel and turret towards those rotations. Just an idea. Sometimes using an extra object in your game will save you a lot of lines of code.

Comment

People who like this

0 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 UnityAccnt · Apr 05, 2019 at 02:20 AM 0
Share

Now I cant figure out how to clamp the barrel, yet another day wasted.... :(

     //Move Barrel
     /*
      * Only rotate the barrel up and down if the turret is looking at the player,
      * even though the barrel can still rotate on all axis the y and z will already
      * be aligned as a result of the turrets rotatation
      * so the barrel will effectively only rotate on the x axis
      */
     if (transform.rotation == turretVectorToQuaternion)
     {
         //Get the direction from the barrel to the target
         Vector3 targetDir = target.transform.position - (barrel.transform.position - positionOffset);
         //targetDir.y = barrel.transform.rotation.y;

         //Convert the vector to a rotation in degrees
         Vector3 rotation = Quaternion.LookRotation(targetDir).eulerAngles;

         Debug.Log("BarrelX " + barrel.transform.localEulerAngles);
         Debug.Log("RotationX " + rotation.x);

         //Clamp rotation.x so that the barrel can only go so high and so low
         float newXRotation = Mathf.Clamp(rotation.x , maxVerticalRotation, minVerticalRotation);

         Debug.Log("newXRotation " + newXRotation);

         //Create a new Quaternion using the clamped rotation for the x value
         Quaternion newRotation = Quaternion.Euler(new Vector3( newXRotation, rotation.y, rotation.z));

         //Rotate the barrel to look at the target
         barrel.transform.rotation = Quaternion.Lerp(barrel.transform.rotation, newRotation, step);
         currentVerticalRotation = newXRotation;

         //Show the vector
         Debug.DrawRay(barrel.transform.position, targetDir, Color.blue);
     }
avatar image

Answer by UnityAccnt · Apr 05, 2019 at 02:05 AM

Thank you for your response. One of the variations I tried in order to rotate the barrel correctly was //Move Barrel /* * Only rotate the barrel up and down if the turret is looking at the player, * even though the barrel can still rotate on all axis the y and z will already * be aligned as a result of the turrets rotatation */ if (transform.rotation == turretVectorToQuaternion) { //Get the direction from the barrel to the target Vector3 targetDir = target.transform.position - (barrel.transform.position - positionOffset); //targetDir.y = barrel.transform.rotation.y; //Convert the vector to a quaternion rotation Quaternion rotation = Quaternion.LookRotation(targetDir); //Rotate the barrel to look at the target barrel.transform.rotation = Quaternion.Lerp(barrel.transform.rotation, rotation, step); //Show the vector Debug.DrawRay(barrel.transform.position, targetDir, Color.blue); } and it seems to give the same result as what you provided, but the barrel is still able to rotate around the other axes if the target is directly above. So I guess the solution now would be to clamp the barrel so it can't look directly up or down? However, I'm not sure how to clamp it correctly. Sorry for not providing more information about my problem in the original post.

Comment

People who like this

0 Show 0 · 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

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

136 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 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 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 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

Rotation like in editor 2 Answers

How to rotate object based on another rotation. 1 Answer

How Do I accurately rotate a player 180 degrees about the Z axis? 1 Answer

Duplicating rotation with axis constraints 1 Answer

Rotate object on one axis with slerp 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