- Home /
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
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);
}
}
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 : $$anonymous$$onoBehaviour {
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 = $$anonymous$$athf.Clamp(lastPos.x, -maxOffsetX, maxOffsetX);
lastPos.y = $$anonymous$$athf.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. $$anonymous$$ay you help me with this last issue, I would be very grateful :) Thank you for you effort so far!
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?
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.
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.
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.
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Multiple Cars not working 1 Answer
Snapping Issue 2 Answers
Help with GUI Currency 1 Answer