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
0
Question by KaWiz · Jun 18, 2015 at 06:20 AM · angleturrettank

Make two sets of objects have same angle between them

For those of you that have played Battlefield 1942, what I'm trying to build is the tank turret-to-body rotation indicator (at the bottom): http://www.realtimerendering.com/erich/bf1942/tankvstank_001.jpg

For those of you that haven't, I'm trying to show on the GUI what the angular difference is between the camera's Forward and the "body" Forward, in a 2D space of course. What I have so far is:

 if(turret) {
 Vector2 reducedVectorTurret = new Vector2(transform.forward.x, transform.forward.z);
 Vector2 reducedVectorBody = new Vector2(playerBody.transform.forward.x, playerBody.transform.forward.z);
 
 float angleDifference = Vector2.Angle (reducedVectorCam, reducedVectorBody);
 }

but I'm stumped as to where to go from there. I know using Vector2.Angle won't work since the angle will always be positive, which won't let me set the RectTransform.rotation on the UI indicator correctly since it doesn't discern between left and right. I did some research on similar questions and it seems the Mathf.Atan2 function is involved but couldn't find any cases close enough to mine to figure it out.

Thanks for taking the time to read this, and I hope I've been clear enough!

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 KaWiz · Jun 18, 2015 at 01:40 AM 0
Share

I made a little diagram to help explain what I'm trying to do even further:

alt text

avatar image KayelGee · Jun 18, 2015 at 02:25 PM 0
Share

It's pretty easy. Take the rotation of your turret, subtract the rotation of the body. Add rotation to 2D body. Done.

I'll write a longer explanation when I get home so I don't make any + - errors.

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Hellium · Jun 18, 2015 at 02:43 PM

The following code returns the signed angle between two Vector3 considering the normal of the surface (here Vector3.up I suppose) :

 float SignedAngleBetween( Vector3 a, Vector3 b, Vector3 n )
 {
     float angle = Vector3.Angle( a, b );
     float sign  = Mathf.Sign( Vector3.Dot( n, Vector3.Cross( a, b ) ) );
     return angle * sign;
 }

See this manual page to understand the mathematics principles involved :

http://docs.unity3d.com/Manual/UnderstandingVectorArithmetic.html

To be quick : Cross product between two vectors will return a third vector so that it's perpendicular to the two others and the three vectors make an "direct basis" (using the left hand rule because Unity uses a left-handed coordinate system)

Left hand rule

The dot operation will help determining if the vector calculated just above, and the normal are "in the same direction". If yes, the angle between a and b is positive (anti clockwise).

With this angle, you will be able to rotate your 2D tank

 tankBody.GetComponent<RectTransform>().rotation = Quaternion.Euler( 0, 0, signedAngle ) ;


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 KaWiz · Jun 18, 2015 at 07:05 PM

Ended up figuring it out myself. I'm not sure if it's the most elegant solution, but it's 10 lines and works:

 if(turret) {
 //reduce 3D vectors to 2D since Y is irrelevant
 reducedVectorTurret = new Vector2(transform.forward.x, transform.forward.z);
 reducedVectorBody = new Vector2(playerBody.transform.forward.x, playerBody.transform.forward.z);
 
 //calculate angular difference
 angleDifference = Vector2.Angle (reducedVectorTurret, reducedVectorBody);
 
 //x is + or - depending on whether angle is to left or right
 //turretIcon is always pointing Vector2.up, so just apply the
 //earlier angular difference to bodyIcon Z rotation directly every frame
 if(transform.InverseTransformDirection(playerBody.transform.forward).x < 0)
 bodyIcon.eulerAngles = new Vector3(0, 0, angleDifference);
 else
 bodyIcon.eulerAngles = new Vector3(0, 0, -angleDifference);
 }

I have a feeling there's a way to do this using InverseTransformDirection alone and not calculating the angular difference separately, but working with 2D vectors is much easier to understand and being able to plug the angleDifference into eulerAngles.z directly is a nice touch.

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 KaWiz · Jun 18, 2015 at 02:11 PM 0
Share

this code is a little janky when looking straight up or down because of how rotations work, but the turret's Y is clamped so that's not even possible. at least i didn't have to implement trig functions i barely understand :D

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Borderlands 2 style vehicle driving! 1 Answer

Rotate on Z axis 2 Answers

3D Turret Rotation 0 Answers

How to make the turret on your tank turn 0 Answers

Can't Ignore a Layer when raycat 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