• 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 Nitrosocke · Jul 24, 2014 at 03:33 PM · c#guicrosshair

How to make the Crosshair follow delayed

Hi guys, I've run trough several posts and other questions here but can find me a helpful answer. What I trying to achieve is that the crosshair follows the camera with a little delay.

Example Video: Youtube

I want it to be like that HUD and not animated. I don't need the walking shake since my Player wont walk in my game.

Here is my Code so far:

 using UnityEngine;
 using System.Collections;
 
 public class DynamicGUI : MonoBehaviour {
 
     public float speed = 0.5F;
     public float centerSpeed = 0.0001F;
     public Transform camera;
     public Texture crosshair;
 
     private float slowX;
     private float slowY;
     private float lastX;
     private float lastY;
     private float offsetX;
     private float offsetY;
     private float xValue = 0.0F;
     private float yValue = 0.0F;
 
 
     // Use this for initialization
     void Start () {
     
     }
     
     // Update is called once per frame
     void Update () {
 
         offsetX = Input.GetAxis ("Mouse X") * Time.deltaTime;
         offsetY = Input.GetAxis ("Mouse Y") * Time.deltaTime;
 
         lastX = camera.rotation.x;
         lastY = camera.rotation.y;
 
         slowX = Mathf.SmoothDamp(-offsetX, 0,  ref xValue, centerSpeed);
         slowY = Mathf.SmoothDamp(-offsetY, 0,  ref yValue, centerSpeed);
     
     }
     void OnGUI (){
         GUI.DrawTexture (new Rect(Screen.width/2 + slowX * Screen.width, Screen.height/2 + slowY * Screen.height, 16, 16), crosshair);
         GUILayout.Label("SlowX: " + slowX);
         GUILayout.Label("SlowY: " + slowY);
         GUILayout.Label("Last X: " + lastX);
         GUILayout.Label("Last Y: " + lastY);
         GUILayout.Label("Offset X: " + offsetX);
         GUILayout.Label("Offset Y: " + offsetY);
     }
 }
 

So I got it to center a bit slower but I cant get it smooth and more delayed. Maybe I'm stuck within a method which cant be used for this. I hope you can help me out at this. I am familiar with java and C#.

Best regards Nitrosocke

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

1 Reply

· Add your reply
  • Sort: 
avatar image
Best Answer

Answer by robertbu · Jul 24, 2014 at 05:04 PM

The first approach that comes to mind is to track the world position some distance in front of the camera, and then Lerp() from that world position (translated to screen coordinates) to the center of the screen. Not sure it is any better approach than the one you are doing, but here is a bit of example code:

 using UnityEngine;
 using System.Collections;
 
 public class Bug25b : MonoBehaviour {
     
     public Texture crosshair;
     public Camera camera;
     public float speed = 7.0f;
     public float maxDrift = 1.25f;
     
     private Vector3 lastPos;
     private Rect rect;
     private Vector3 center = new Vector3(0.5f, 0.5f, 10.0f);
     
     void Start() {
         if (camera == null) {
             camera = Camera.main;
         }
         lastPos = camera.ViewportToWorldPoint (new Vector3(0.5f, 0.5f, 10.0f));
         rect = new Rect(0,0,crosshair.width,crosshair.height);
     }
     
     void OnGUI() {
         if (Event.current.type == EventType.Repaint) {
             Vector3 centerPos = camera.ViewportToWorldPoint (center);
             
             // Clamping code
             Vector3 v = lastPos - centerPos;
             v = Vector3.ClampMagnitude (v, maxDrift);
             lastPos = centerPos + v;
             
             Vector3 lastScreenPos = camera.WorldToScreenPoint(lastPos);
             lastScreenPos.y = Screen.height - lastScreenPos.y;
             rect.center = Vector3.Lerp (lastScreenPos, new Vector3(Screen.width/2, Screen.height/2, 0), Time.deltaTime * speed);
             lastPos = rect.center;
             lastPos.y = Screen.height - lastPos.y;
             lastPos.z = 10.0f;
             lastPos = camera.ScreenToWorldPoint(lastPos);
         }
         
         GUI.DrawTexture(rect, crosshair);
     }
 }
Comment

People who like this

0 Show 6 · 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 Nitrosocke · Jul 24, 2014 at 09:25 PM 0
Share

Hi Robert, I've tried your code and it seem to work. Yet I played a bit with it to fit my needs. I tried to clamp the X and Y values of the offset but with no luck so far. here is my code:

 using UnityEngine;
 using System.Collections;
 
 public class RayTest : MonoBehaviour {
     
     public Texture crosshair;
     public Camera camera;
     public float speed = 7.0f;
     public float max = 1.0f;
     
     private Vector3 lastPos;
     private Rect rect;
     private Vector2 center;
     private float maxOffsetX;
     private float maxOffsetY;
     
     void Start() {
         if (camera == null) {
             camera = Camera.main;
         }
         lastPos = camera.ViewportToWorldPoint (new Vector3(0.7f, 0.7f, 10.0f));
         rect = new Rect(0,0,crosshair.width,crosshair.height);
         maxOffsetX = Screen.width / 2 + max;
         maxOffsetY = Screen.height / 2 + max;
     }
 
     void OnGUI() {
         if (Event.current.type == EventType.Repaint) {
             Vector3 lastScreenPos = camera.WorldToScreenPoint(lastPos);
             lastPos.x = Mathf.Clamp(lastPos.x, -maxOffsetX, maxOffsetX);
             lastPos.y = Mathf.Clamp(lastPos.y, -maxOffsetY, maxOffsetY);
             rect.center = Vector3.Lerp (lastScreenPos, new Vector3(Screen.width/2, Screen.height/2, 0), Time.deltaTime * speed);
             lastPos = rect.center;
             lastPos.z = 10.0f;
             lastPos = camera.ScreenToWorldPoint(lastPos);
         }
         
         GUI.DrawTexture(rect, crosshair);
     }
 }

I tried to clamp the lastScreenPos value as well but didn't worked either. May you help me with this last issue, I would be very grateful :) Thank you for you effort so far!

avatar image robertbu · Jul 24, 2014 at 09:38 PM 0
Share

Just to understand your criteria, are you trying to keep the crosshair from drifting too far from the center or are you trying to solve some other probelm? Is is okay to restrict the crosshair to a circle rather than a square from the center of the screen?

avatar image Nitrosocke · Jul 25, 2014 at 12:56 AM 0
Share

Ya that's exactly what I want. A circle might be better anyways, i just used the separated x and y values to use the Clamp function.

avatar image robertbu · Jul 25, 2014 at 01:56 AM 0
Share

I edited my example above to have a maxDrift parameter. This is the maximum amount of drift the lastPos can be from the center of the screen in world space 10 units from the camera. The 10 units used in the code is arbitrary. By doing the calculation in world space, the code should work even if you use it on multiple different devices with different resolutions.

avatar image Nitrosocke · Jul 25, 2014 at 03:38 PM 0
Share

Thank you again Robert, there is just one more thing I found:

the x movement seems to be inverted. When I rotate the Camera on the x axis the crosshair jumps in the opposite direction. I tried to convert the Vector3 value like this:

 private static Vector3 Conv(Vector3 w)
     {
         return new Vector3(-w.x, w.y, w.z);    
     }

And in the GUI function:

 rect.center = Vector3.Lerp (Conv (lastScreenPos), new Vector3(Screen.width/2, Screen.height/2, 0), Time.deltaTime * speed);

But it didn't work for me. Do you have any Idea how to fix this. Everything else seem to work like charm.

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.

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

2 People are following this question.

avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Snapping Issue 2 Answers

Distribute terrain in zones 3 Answers

compiler errors when building for android 2 Answers

How to get the width + height of a RectTransform controlled by a Grid Layout Group? 3 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