- Home /
Sniper scope zoom if crosshair is not in the middle of the screen
Hi, As you could understand I'm working on FPS game and I need to have a look into sniper scope but the thing is that my crosshair can be anywhere in the screen which makes some troubles for sniper aiming.
Here is my view before the sniper aim.
And my view after.
What I'm doing is decreasing camera's field of view but I get the unneeded offset (as you can see on the screenshot).
Could you please help me to figure out how to calculate new camera position or what do I need to do in this situation?
var aimTransform = weapon.transform.Find("aim_pos");
mainCamera.transform.position = aimTransform.position;
//mainCamera.transform.rotation = aimTransform.rotation;
//TODO: calculate "offset" to stay point at the same object as before zoom in
// distance to first hit
// mainCamera.ScreenPointToRay(new Vector3
var position = new Vector3(crosshairPosition.x, Screen.height - crosshairPosition.y, 0);
Ray rCast = mainCamera.ScreenPointToRay(position);
//Debug.LogWarning("Ray param = " + rCast);
Debug.DrawLine(rCast.origin, rCast.origin + rCast.direction * 10000, Color.yellow,600);
RaycastHit hitInfo;
bool wasHit = Physics.Raycast(rCast, out hitInfo);
float distance;
if (wasHit)
{
Debug.Log(string.Format("Hit {0} distance = {1}", hitInfo.collider.name, hitInfo.distance));
distance = hitInfo.distance;
}
else
{
Debug.LogWarning("Not hit. take farClipPlane");
distance = mainCamera.farClipPlane;
}
Vector3 wp1 = mainCamera.ScreenToWorldPoint(new Vector3(crosshairPosition.x, crosshairPosition.y, distance));
Debug.Log(wp1);
mainCamera.fieldOfView = zoomInFow;
Vector3 wp2 = mainCamera.ScreenToWorldPoint(new Vector3(crosshairPosition.x, crosshairPosition.y, distance));
Debug.Log("new " + wp2);
var worldOffsetX = wp1.x - wp2.x;
var worldOffsetY = wp1.y - wp2.y;
var worldOffsetZ = wp1.z - wp2.z;
Debug.LogWarning(string.Format("World offset x={0} y={1}", worldOffsetX, worldOffsetY));
mainCamera.transform.localPosition = new Vector3(mainCamera.transform.localPosition.x + worldOffsetX, mainCamera.transform.localPosition.y + worldOffsetY, mainCamera.transform.localPosition.z);
Thank you, Ihor.
Answer by segment · Feb 06, 2014 at 09:32 AM
Thank you vulgarknight.
I came out with this soltion.
public void AimAtView()
{
isSniperMode = true;
sniper_scope.SetActive(true);
mainCamera.fieldOfView = zoomInFow;
double chnX = crosshairPosition.x / mainCamera.pixelWidth;
double chnY = (mainCamera.pixelHeight - crosshairPosition.y) / mainCamera.pixelHeight;
double angY0 = (cameraFov) * (0.5f - chnY);
double angY = (zoomInFow ) * (0.5f - chnY);
double angX0 = cameraFov * mainCamera.aspect * (0.5f - chnX);
double angX = zoomInFow * mainCamera.aspect * (0.5f - chnX);
mainCamera.transform.localRotation = Quaternion.Euler((float)(angY0 - angY), - (float)(angX0 - angX), 0);
WeaponLookAtCrosshair();
updateSniperScope();
}
If it works, it works! I think you may be able to save some time by using RayCasts, but there's no point in rewriting it, right?
Thanks for posting this. I just needed exactly this solution for a non-centered crosshair myself.
Answer by vulgarknight · Feb 05, 2014 at 05:12 PM
I would first cast a ray from the cross hair to the 3d space that you are looking at. Next I would tell the camera to align itself in that direction. After that you should just be able to decrease the FOV and get the right effect.
Your answer
Follow this Question
Related Questions
Lerping Field Of View is buggy 1 Answer
Sniper Zoom Effect 0 Answers
Steam Vr and Camera Target Textures 0 Answers
How do I make a camera's view a texture(screen) 1 Answer
How to bring reticles in different situations to the center of the camera? 0 Answers