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 Tehnique · Jul 07, 2013 at 06:32 PM · vector3turret

Angle of 2 Vector3 on one axis

Hey there!

So this is my situation: I have a classic turret made out of a turretBase (that rotates on Y only) and a turretBody (that rotates on X only) which is a child of the turretBase. The turret is attached to a ship that rotates on all axis.

When I select a target, I want the base to rotate towards it on Y and the body to rotate towards the target on X. I need to do all this using angles, and transform.RotateAround, because I am also imposing limits on the turret (so it does not shoot through the ship).

So my idea for the base was to find the angle between base.forward and the target direction (which is target.position - turretBase.position). The problem is that this angle has to be only in XZ plane (so an Y angle). What I did was this:

 var targetDirection = target.position - turretBase.position;
             
             targetDirection.y = turretBase.forward.y;
             yAngleToTarget = Vector3.Angle(turretBase.forward, targetDirection);

Well, as expected, that angle is not only on Y, so I can't use it.

So my question is: having 2 Vector3s, how do I get the Y angle between them, relative to the first vector?

Thanks in advance!

PS: I also tried this:

 var targetDirection = target.position - turretBase.position;
 var angleOnY = Mathf.Asin(Vector3.Cross(targetDirection, turretBase.forward).y) * Mathf.Rad2Deg;

and it works great at times, problem is it often causes an "!IsFinite(outDistanceAlongView)" error. Probably division by 0, somewhere, though I can't be sure.

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

Answer by Owen-Reynolds · Jul 07, 2013 at 08:22 PM

One note: V3.Angle can't tell left from right.

Sometimes easier to put everything in the turret's local coords. This assumes turretBase has +z pointing the way it shoots:

 V3 targDir = targPos - myPos; // your same code
 targDir = turretBase.InverseTransformDirection(targDir);

 targDir.y = 0; // if you want to get the Y-angle

The hardest part is realizing that targDir is now using the turret's red/green/blue arrows (with the base as 000.) V3.Angle(V3.forward, targDir gives the spin around the turrets local green up arrow, AND, can just check if(targDir.x<0) to get left/right.

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
6

Answer by glitchers · Oct 11, 2016 at 03:55 PM

I found this solutions to be locked in a range of -90°-90° so here's my solution:

 var targetDirection = targetPosition - turretTransform.position;

 targetDirection = turretTransform.InverseTransformDirection(targetDirection);

 var angleOnY = Mathf.Atan2( targetDirection.z, targetDirection.x ) * Mathf.Rad2Deg;

 // You may have to +/- 90 to the last angle but this works for me in 360°.
 // I use it for directional hit markers in my shooter for turning 3d into 2d screen space

Hope that helps someone as this is the page I found on Google.

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 Ronildson · Oct 03, 2017 at 11:37 PM 1
Share

You've helped me greatly! I was struggling to get the absolute angles of multiple objects relative to the player on a single axis and this was the answer. Thank you!

avatar image
0

Answer by aldonaletto · Jul 07, 2013 at 07:57 PM

The vectors must be normalized for Vector3.Cross to return a value equal to the sine of the angle. Since turretBase.forward already is a normalized vector, you only have to normalize targetDirection :

 var targetDirection = target.position - turretBase.position;
 var angleOnY = Mathf.Asin(Vector3.Cross(targetDirection.normalized, turretBase.forward).y) * Mathf.Rad2Deg;

This returns a signed angle about the axis Y; if you use Cross().x, the angle returned is about the axis X, and so on.

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 Tehnique · Jul 08, 2013 at 06:15 PM 0
Share

I tried this, and it seems to stop the error I was getting previously. However, it does not solve my problem...all angles seem to be correct, yet, somehow, the turret is pointing the wrong way. I tried debugging and I couldn't find the error, yet.

Here is the method I use:

 float CalculateRotationForBase(Transform target)
     {
         //set default position if target is null; rotation sign & rotation angle. 180 is the base forward position.
         float relativeAngleOfTarget = 180;
         int rotationSign = 1;
         float rotation = BaseRotationSpeedAngle;
         bool targetInDeadZone = false;
         
         //if target is not null, calculate relative angle (local for base) of target.
         if(target != null)
         {
             var targetDirection = target.position - turretBase.position;
             
             var angleOnY = $$anonymous$$athf.Asin(Vector3.Cross(targetDirection.normalized, -turretBase.forward).y) * $$anonymous$$athf.Rad2Deg;
 
             relativeAngleOfTarget = 180 + angleOnY;
         }
         
         //calculate relative angle (local for base) of current base position.
         var currentInEuler = turretBase.localEulerAngles.y;
         
         //if target is in the dead zone, calculate which dead zone edge is closer to target.
         if(relativeAngleOfTarget <= baseArcAngleStart)
         {
             relativeAngleOfTarget = baseArcAngleStart;
             targetInDeadZone = true;
         }
         else if(relativeAngleOfTarget >= baseArcAngleEnd)
         {
             relativeAngleOfTarget = baseArcAngleEnd;
             targetInDeadZone = true;
         }
         
         //calculate spin direction.
         if(relativeAngleOfTarget < currentInEuler)
         {
             rotationSign = -1;
         }
         
         //calculate angle between target and base.
         var alpha = $$anonymous$$athf.Abs((360 - relativeAngleOfTarget) - (360 - currentInEuler));
 
         //reduce roatation speed if turret is locked on target OR it is at the edge of the dead zone. This reduces jump oscilation.
         baseIsAtEdgeOfDeadZone = targetInDeadZone && alpha < baseBuffer;
         if(isLockedOnTarget || baseIsAtEdgeOfDeadZone)// || bodyIsAtEdgeOfDeadZone)
         {
             rotation = alpha;
         }
         
         //if there is no target, and turret is in default position stop shaking.
         if(alpha < baseBuffer)
         {
             if(target == null)
             {
                 rotation = 0;
             }
             else if(!isLockedOnTarget)
             {
                 rotation = alpha;
             }
         }
         
         //calculate final rotation.
         rotation = rotation * rotationSign;
 
         return rotation;        
     }

The method takes the target transform, and should return the angle to rotate on Y. I use it like this:

 void RotateBase (Transform target)
     {
         var angleToRotate = CalculateRotationForBase(target);
         
         var verticalAxisDown = turretBase.TransformDirection(Vector3.down);
         turretBase.RotateAround(turretBase.position, verticalAxisDown, angleToRotate * Time.deltaTime);
 }
avatar image Tehnique · Jul 08, 2013 at 06:49 PM 0
Share

Here is a screenshot of the behavior I am getting. The red line is the target direction, and the green one is the turretBase forward. As you see, the error in ai$$anonymous$$g varies with the turret-to-target angle.

Don't think this helps a lot, but maybe you spot something.

alt text

untitled.jpg (211.7 kB)

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

20 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

Related Questions

How can I rotate a tank's turret back to the starting turret position? 2 Answers

Angle between Ray and Normal 1 Answer

Rotating Turret Base and Barrel 3 Answers

Mesuring distance through script 2 Answers

3D nested Turret Prefab Rotation 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