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
2
Question by save · May 14, 2011 at 12:32 PM · guipointercompass

Get a (GUI) 2d-arrow to turn to a specific position in 3d-space (similar to a compass)

I've been fiddling with this for a couple of days now, trying out both GUI-skins and 3d-objects but can't seem to get it working properly. I've tried out this solution http://forum.unity3d.com/threads/43967-compass-on-GUI-rotate-with-camera! but it doesn't really apply to what I'm trying to achieve.

So what I'm trying to do is an arrow as GUI that moves around a pivot in the center of the screen, looking at new waypoints. The directions can be on all axises as the player is a flying object (which can roll, turn and elevate in all angles) but the arrow should always remain flat towards the camera but rotate around its z-axis towards the active waypoint. When the object is close enough in angle (when the player looks directly at it) it's supposed to fade out. The big problem is to get the arrow to look at the object with the correct rotation and still remain flat to the camera.

This could also be used as a damage direction notifier (where the bullet came from and hit the player) for instance in an FPS, showing hits as a clock around a pivot centered to the screen. How would you solve such a thing? I've been looking into WorldToScreenPoint and angles, but can't figure it out - the more I dig the more confused I get.

alt text

I've gone completely blind here, a little help would be much appreciated!

Edit: This is what I've come up with so far:

var cam : Camera; private var targetPos : Vector3; private var screenMiddle : Vector3; private var angle : float = 0.0;

function Update() { targetPos = cam.WorldToScreenPoint (CheckpointScript.nextCheckpoint.transform.position); screenMiddle = Vector3(Screen.width/2, Screen.height/2, 0); angle = Mathf.Atan2(targetPos.x-screenMiddle.x, targetPos.y-screenMiddle.y) * 180 / Mathf.PI; print(angle); }

This prints out the angle between the object and the target (which is set in the CheckpointScript). My problem is to set the eulerAngles so the arrow only rotates on one axis (to remain flat towards the camera). Besides from having a blonde moment here, what am I supposed to do?

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

5 Replies

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

Answer by save · May 15, 2011 at 09:21 PM

Working with rotations can be really tricky especially when you have to work with 2d to 3d coordinates. If someone want to implement this here's a quick version:

var cam : Camera; //Camera to use var target : Transform; //Target to point at (you could set this to any gameObject dynamically) private var targetPos : Vector3; //Target position on screen private var screenMiddle : Vector3; //Middle of the screen

function Update() { //Get the targets position on screen into a Vector3 targetPos = cam.WorldToScreenPoint (target.transform.position); //Get the middle of the screen into a Vector3 screenMiddle = Vector3(Screen.width/2, Screen.height/2, 0); //Compute the angle from screenMiddle to targetPos var tarAngle = (Mathf.Atan2(targetPos.x-screenMiddle.x,Screen.height-targetPos.y-screenMiddle.y) * Mathf.Rad2Deg)+90; if (tarAngle < 0) tarAngle +=360;

 //Calculate the angle from the camera to the target
 var targetDir = target.transform.position - cam.transform.position;
 var forward = cam.transform.forward;
 var angle = Vector3.Angle(targetDir, forward);

 //If the angle exceeds 90deg inverse the rotation to point correctly
 if(angle&lt;90){
     transform.localRotation = Quaternion.Euler(-tarAngle,90,270);
 } else {
     transform.localRotation = Quaternion.Euler(tarAngle,270,90);
 }

}

The GUI in 3d-space has to be put relative to the camera at all times (child to main camera or a camera only seeing the GUI-element rendered on top of the main camera). Preferably the last mentioned as you mostly wouldn't want the GUI to fall behind objects in 3d-space. Big thanks to The_r0nin and the tarAngle computation.

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 The_r0nin · May 15, 2011 at 11:18 PM 0
Share

You're welcome! Glad I could help...

avatar image Aishwarya_Garg · Dec 24, 2014 at 12:34 PM 0
Share

where this script should be applied?

avatar image
1

Answer by The_r0nin · May 14, 2011 at 05:42 PM

Here's how I make an airplane rotate based on the direction of the mouse pointer from the center of the screen. This should be able to be modified to do what you want (use a WorldToScreenPoint to get your point, or just use the direction based on subtracting Vector3s):

screenVec = Vector3(Input.mousePosition.x - Global.sCenter.x, Global.sHeight - Input.mousePosition.y - Global.sCenter.y, 0);

 tarAngle= (Mathf.Atan2(screenVec.y,screenVec.x) * Mathf.Rad2Deg)+90;

if (tarAngle < 0) tarAngle +=360;

 if (tarAngle != 0) transform.RotateAround(transform.position,transform.forward, -tarAngle);

Global.sCenter is the screen center pixel coordinates. I simply find the angle between the mouse pointer and the center of the screen (using Atan2) and then roll the target using RotateAround the z-axis of the transform. You could roll your object around its z-axis using the relative x & y coordinate difference...

Comment
Add comment · Show 4 · 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 save · May 14, 2011 at 07:08 PM 0
Share

Thanks r0nin, pushes in the right direction. But this really beats me, I have modified it a bit to fit my code:

targetPos = cam.WorldToScreenPoint (target.position); screenVec = Vector3(targetPos.x - Screen.width/2, Screen.height - targetPos.y - Screen.height/2, 0); var tarAngle = ($$anonymous$$athf.Atan2(screenVec.y,screenVec.x) * $$anonymous$$athf.Rad2Deg)+90;

But what I don't understand is how to rotate the arrow (remaining flat) while pointing towards tarAngle, I've tried with setting the eulers but everything just winds up wrong. It would help so much if I could see a code example of that, if you have the time

avatar image save · May 14, 2011 at 10:36 PM 0
Share

If someone could just point out how I could rotate the arrow (which is in 3d space and set to a gui-camera) according to the angle variable in my first post I'd appreciate it a bunch!

avatar image save · May 15, 2011 at 08:56 PM 0
Share

Direction is solved, get back soon with an answer, thanks r0nin!

avatar image Psyco92 · Feb 06, 2014 at 11:50 AM 0
Share

Did you ever find out how to set the rotation of a GUITexture?

avatar image
0

Answer by Antony-Blackett · May 14, 2011 at 01:50 PM

If you use a 3D arrow and place it in front of the camera you can use the Transform.LookAt() function to set its facing direction. If you use the camera's up vector is should keep the arrow's up vector the same as the camera's up vector.

void Update()
{
    arrowObject.transform.LookAt( waypoint.transform, cam.transform.up );
}
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 save · May 14, 2011 at 02:11 PM 0
Share

Thanks for the fast answer. This solution does unfortunately not work as the arrow still rotates around all degrees. I'll update my problem with an image describing it better hopefully.

avatar image
0

Answer by arckex · Aug 04, 2015 at 08:49 PM

I projected the distance of my target onto a point roughly the same distance away but in front of my camera, and then found the angle from that projected point's up vector required to make it rotate and point towards the target.

 Vector3 up = targetTransform.up;
 float dist = Vector3.Magnitude(targetTransform.position - camera.position);
 Vector3 over = targetTransform.position - (camera.position + camera.forward * dist);
 float ang = Vector3.Angle(up, over);
 if (over.x < 0)
   this.transform.localRotation = Quaternion.Euler(0, 0, ang);
 else
   this.transform.localRotation = Quaternion.Euler(0, 0, -ang);
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 Cherno · Aug 04, 2015 at 09:05 PM

Here's a sccript I found online, it allows to to rotate any GUI element around a pivot; I have used it as a player marker myself.

 using UnityEngine;
 
 [ExecuteInEditMode()] 
 public class RotatableGuiItem : MonoBehaviour
 {
     public Texture2D texture = null;
     public float angle = 0;
     public Vector2 size = new Vector2(128, 128);
     
     //this will overwrite the items position
     public AlignmentScreenpoint ScreenpointToAlign = AlignmentScreenpoint.TopLeft;
     public Vector2 relativePosition = new Vector2(0, 0);
     
     Vector2 pos = new Vector2(0, 0);
     
     Rect rect;
     Vector2 pivot;
     
     void Start() 
     {
         UpdateSettings();
     }
     
     public void UpdateSettings()
     {
         Vector2 cornerPos = new Vector2(0, 0);
         
         //overwrite the items position
         switch (ScreenpointToAlign)
         {
         case AlignmentScreenpoint.TopLeft:
             cornerPos =new Vector2(0, 0);
             break;
         case AlignmentScreenpoint.TopMiddle:
             cornerPos =new Vector2(Screen.width/2, 0);
             break;
         case AlignmentScreenpoint.TopRight:
             cornerPos = new Vector2(Screen.width, 0);
             break;
         case AlignmentScreenpoint.LeftMiddle:
             cornerPos = new Vector2(0, Screen.height / 2);
             break;
         case AlignmentScreenpoint.RightMiddle:
             cornerPos = new Vector2(Screen.width, Screen.height / 2);
             break;
         case AlignmentScreenpoint.BottomLeft:
             cornerPos = new Vector2(0, Screen.height);
             break;
         case AlignmentScreenpoint.BottomMiddle:
             cornerPos = new Vector2(Screen.width/2, Screen.height);
             break;
         case AlignmentScreenpoint.BottomRight:
             cornerPos = new Vector2(Screen.width, Screen.height);
             break;
         default:
             break;
         }
         
         pos = cornerPos + relativePosition;
         rect = new Rect(pos.x - size.x * 0.5f, pos.y - size.y * 0.5f, size.x, size.y);
         pivot = new Vector2(rect.xMin + rect.width * 0.5f, rect.yMin + rect.height * 0.5f);
     }
     
     void OnGUI() {
 
         GUI.depth = 1;
 
         if (Application.isEditor)
         {
             UpdateSettings();
         }
         Matrix4x4 matrixBackup = GUI.matrix;
         GUIUtility.RotateAroundPivot(angle, pivot);
         GUI.DrawTexture(rect, texture);
         GUI.matrix = matrixBackup;
     }
     
     public enum AlignmentScreenpoint {
         TopLeft, TopMiddle, TopRight,
         LeftMiddle, RightMiddle,
         BottomLeft, BottomMiddle, BottomRight
     }
 }
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

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

How to make a 2D Horizontal Compass? 1 Answer

compass GUI jumps at angle 180. 0 Answers

ExecuteEvents.Execute makes game crash 0 Answers

Can I set a specific Pointer for the EventTrigger on Buttons for example? 0 Answers

EventTrigger runtime added callbacks to OnPointerClick/OnPointerUp/OnPointerDown don't work. 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