- Home /
How do I make my crosshair more accurate?
So basically I have a gun and i'm using raycasting to shoot. When i'm close to my target it goes fine, but when I go really far, it never hits the target. This is my current script for shooting:
public void CastRay()
{
RaycastHit Hit;
if(Physics.Raycast(transform.position,transform.forward,out Hit,Power))
{
if(Hit.transform.gameObject.tag == "target")
{
Destroy(Hit.transform.gameObject);
}
}
}
And this is what i'm using for the crosshair
myRay = new Ray(transform.position,transform.forward);
CrossHairPosition = Camera.main.WorldToScreenPoint(myRay.GetPoint(Power));
GUI.Label(new Rect(CrossHairPosition.x - (CrossHair.width / 2),CrossHairPosition.y - (CrossHair.height / 2),CrossHair.width,CrossHair.height),CrossHair); //Crosshair is 2D texture
What's wrong with this code ? When i go very far, it's not shooting in the crosshair anymore. Infact, it doesn't come even close to shooting in the crosshair.
I'm guessing you are shooting a projectile? If so, your projectile drops due to gravity between the time you fire it and the time it reaches your target. You will have to calculate that drop and adjust your aim.
No i'm not using projectiles. Look at the first block of code I posted, i'm using that for shooting. When the player clicks his mouse button it casts a ray. The ray goes as far as "Power" which is a variable that you can specify yourself. I just don't get why the crosshair isn't accurate at all.
Answer by robertbu · Mar 11, 2013 at 09:18 AM
I should have spotted it the first time. You are using GUI coordinates to display the crosshair, but you are calculating screen coordinates. You can convert between the two by:
CrossHairPosition.y = Screen.height - CrossHairPosition.y;
The bottom-left of the screen is (0,0) with screen coordinates. The top-left of the screen is (0,0) for GUI coordiantes.
Ohhh that explains why when I shoot and the recoil happens, ins$$anonymous$$d of going up the crosshair goes down. Thanks alot! Btw I tried using your code to convert it but it's now entirely off the screen. I put this before my code : CrossHairPosition.y = Screen.height - CrossHairPosition.y; CrossHairPosition.x = Screen.height - CrossHairPosition.x;
I managed to work it out with GUIUtility.ScreenToGUIPoint but the crosshair is still, for some reason, going down when I shoot and recoil while the gun is going up.
Here is your code merged with a bit of $$anonymous$$e since you did not provide all your script. Start with an empty scene. $$anonymous$$ake a cube and set its size to something like (.2, 0.2, 1.0). $$anonymous$$ake an empty game object to use as a spawn point and place it just in front (positive z) of the cube. Then make the spawn point a child of the cube. Attach this script to the spawn point.
Run it. When you click, it will put a sphere at the position used in the calculation. In the inspector, you can move the cube, rotate the cube, and change the Power.
What you will find this this code works as long as the ray does not hit something. The problem is that when it hits something, the calculation...
CrossHairPosition = Camera.main.WorldToScreenPoint(myRay.GetPoint(Power));
...is not accurate because the hit position calculate in CastRay() is not the same as the ray calculate for the OnGUI code to place the crosshair. The crosshair calculation always assumes the ray misses.
To fix the problem, you will have to use the same calculation, either by having them in the same file and saving the position in an instance variable (top of the file), or by using by casting the ray a second time in the code that places the crosshair. And even this is not a complete fix since there will be times when the crosshair will appear to jump, and times it will appear that the crosshair should hit something when, due to perspective, the gun is not really aligned with the object.
public class GunScript : $$anonymous$$onoBehaviour {
public Texture CrossHair;
public float Power = 10;
private Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
public void CastRay()
{
RaycastHit Hit;
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = scale;
if(Physics.Raycast(transform.position,transform.forward,out Hit,Power))
{
go.transform.position = Hit.point;
if(Hit.transform.gameObject.tag == "target")
{
Destroy(Hit.transform.gameObject);
}
}
else
go.transform.position = transform.position + transform.forward * Power;
}
// Update is called once per frame
void Update () {
if (Input.Get$$anonymous$$ouseButtonDown (0))
{
CastRay ();
Ray myRay = new Ray(transform.position,transform.forward);
Vector3 CrossHairPosition = Camera.main.WorldToScreenPoint(myRay.GetPoint(Power));
GUI.Label(new Rect(CrossHairPosition.x - (CrossHair.width / 2),CrossHairPosition.y - (CrossHair.height / 2),CrossHair.width,CrossHair.height),CrossHair); //Crosshair is 2D texture
}
}
void OnGUI()
{
Ray myRay = new Ray(transform.position,transform.forward);
Vector3 CrossHairPosition = Camera.main.WorldToScreenPoint(myRay.GetPoint(Power));
CrossHairPosition.y = Screen.height - CrossHairPosition.y;
GUI.Label(new Rect(CrossHairPosition.x - (CrossHair.width / 2),CrossHairPosition.y - (CrossHair.height / 2),CrossHair.width,CrossHair.height),CrossHair); //Crosshair is 2D texture
}
}
Thanks alot! I'm going to see what I can do to see if it'll fix.
Answer by Griffo · Mar 11, 2013 at 09:02 AM
I presume this is a FPS .. if so is your weapon (Gun) slightly off centre of the view, if it is and you are firing the ray cast from there you will never hit the target until you are close as it's not casting to the centre of the screen (where again I presume you have your crosshair) what I do is cast the ray from the centre of the camera so then it goes straight through the crosshair -
var ray : Ray = Camera.main.ViewportPointToRay (Vector3(0.5,0.5,0));
if (Physics.Raycast (ray, hit, 1000)){
if(Hit.transform.gameObject.tag == "target"){
Destroy(Hit.transform.gameObject);
}
}
Hope this helps ..
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Shooting with a locked camera position 1 Answer
Distribute terrain in zones 3 Answers
CS0116 "A namespace can only contain type and namespace declarations" 1 Answer
crosshair scrip not working 1 Answer