Unity, how to get Camera angle Width - c#

I'm making game that must set target number on all enemy on screen.
I FAIL TO FIND function like IsInsideCameraView(gameObject)
Now I'm trying to scan area that camera looks.
For this, I need Camera angle width, angle hight.
As described in this emage (My reputation is not enough to show image directly)
My question is similer to this question, How to get angles value of perspective camera in Three.js? but for Unity.
If you know
HOW TO CALCULATE CAMERA WIDTH&HEIGHT (following screen size when unity starts)or
IS THERE GOOD FUNTIONS LIKE IsInsideCameraView(Camera, gameObject)
any answers will be welcomed.

[Untested. Javascript] You can use renderer.isVisible to determine if the object is within the camera frustum.

I FAIL TO FIND function like IsInsideCameraView(gameObject)
You can use:
object.Renderer.isVisible
...to check if the object is visible in any camera.
To test for a specific camera, use:
Vector3 screenPos = camera.WorldToScreenPoint(target.position);
Then check if X and Y coordinates are between (0,0) and Screen.width, Screen.height.
HOW TO CALCULATE CAMERA WIDTH&HEIGHT
That's what Camera.pixelWidth and Camera.pixelHeight are for or you can use Screen.width, Screen.height for cameras that represent the entire screen.
Anyway, that's arguably a XY problem, refer to the beginning of my answer for direct solution.
Tell me more
Is target in view frustum?

Related

Grappling hook ray cast direction problems in Unity

Hey team I'm currently working on a 3rd person game where I would like to fire grappling hooks from the player to a point that is offset from the center of the camera.
I have a screen overlay canvas with Ui images for crosshairs. When the left shift is held down the crosshairs move outward from center along the x axis and return to center once shift is released, a bit like crosshair spread in games except I want to trigger the spread via the shift key. These crosshairs are meant to dictate the location the anchors of the grappling hook land, originating from the player and hitting whatever object is directly forward of the crosshairs. (imagine attack on titan ODM gear if you've seen it). I am looking for a way to ray cast from the player to the point forward of these crosshairs while they're offset from the center.
So far I have the grappling system set up and working but am having trouble with the direction parameter when I use the crosshair spread. It separates fine but where the hooks land in relation to the cross hairs are obviously out as I'm trying to use angle calculations at the moment instead of what is forward of these reticles.
I'm basically wondering if it is possible to use these screen overlay UI images to cast forward from or if there's a better way to accomplish the same thing. I have my doubts because they're screen overlay so I imagine their coordinates wont be attached to the camera as they appear.
Thanks in advance for your help.
What I would do is determine the location of the reticleson the screen, then (as Aybe suggested) use ScreenPointToRay or ViewportToRay (depending on if it's easier to get a pixel position or a fractional position of each reticle) to Physics.Raycast that ray from the camera into the scene to find where the rays collide. At this point, you have two world positions the player seems to want to shoot the hooks.:
Vector3 hookTarget1;
Vector3 hookTarget2;
So, now you actually have to fire the hooks - but as you know the hooks aren't being shot from the camera, they are being shot from the player, and they maybe offset by a bit. Let's call the originating points (which may have the same value):
Vector3 hookOrigin1;
Vector3 hookOrigin2;
So, then you can create Rays that originate from the hook origins and point at the targets:
Ray hookShot1 = new Ray(hookOrigin1, hookTarget1 - hookOrigin1);
Ray hookShot2 = new Ray(hookOrigin2, hookTarget2 - hookOrigin2);
Using these rays, you can do another Physics.Raycast if you would like, to confirm that there aren't any trees or other obstacles that are between the player and the target location - and if there are, that may be where the anchor should actually sink:
Vector3 anchorPoint1;
Vector3 anchorPoint2;
The segment between the origin of these rays and these anchor points would be appropriate for rendering the cable, calculating physics for how to move the player, as well as checking for collisions with world geometry that might cause the anchor to release.

Display complete object from camera with specific rotation in unity C#

I have different kind of objects with variable dimensions and placed at different position in a scene. I want to focus/display each object with the camera with a hard code rotation (north rotation). Like with specific camera rotation I want to focus the object that it completely show to the camera and center of the screen. For this reason, I have write this code snippet that
1
Get the position behind the specific focus object using
TransformPoint
Provide the elevation using the largest extent of the bound so that it display maximum area of the object.
Assign the position and the fixed rotation
Vector3 dest = destination.transform.TransformPoint(0, 0, behindPositionDistance);// GetBehindPosition(destination.transform, behindPositionDistance, elevation);
Debug.Log(dest);
float eleveMax = Mathf.Max(destination.GetComponent<MeshRenderer>().bounds.extents.x, destination.GetComponent<MeshRenderer>().bounds.extents.z);
dest = new Vector3(dest.x, eleveMax, dest.z);
camera.transform.position = dest;
camera.transform.rotation = lookNorth;
But the problem is, it is not accurately working with all objects as every object is at different position and dimension. I want to focus the full object using the camera but without changing the rotation.
Maybe create an empty gameobject as a child of your objects. Use that as your Camera position at runtime.
If you can use an orthographic camera, you can set the camera's orthographicSize dynamically based on the size of the bounds of the GameObject. This is probably the easiest solution.
If you need a perspective camera, you can get the Planes or corners of the camera frustum via GeometryUtility.CalculateFrustumPlanes(Camera.main) or Camera.CalculateFrustumCorners and use the results from either to manually test that your Bounds is entirely inside.
With a perspective camera, you could also compute the necessary distance from the object based on the size of the object's bounds and the FOV of the camera. If I'm not mistaken, this would be something along the lines of distance = 0.5 * size / tan(0.5 * fov), but the function doesn't have to be precise; it just needs to work for your camera. Alternatively, you could keep distance constant and compute FOV from the size of the object, although I wouldn't recommend that because frequent FOV changes sound disorienting for the viewer; my point is that there are many options.

What Happens When Setting transform.up in Unity

What happens when I set the transform.up value in unity. Specifically could you explain this video in the link below
https://youtu.be/_XdqA3xbP2A
I know it changes what the object is looking at. But, does it look at a position, or how does it
work? What happens when I change the direct transform.up? I can’t seem to find a good explanation. Why does the vector in the video make a direction that is facing the mouse, why not use the mousePosition itself instead of subtracting?
Aside from that could you also explain what is going on in the video?
Thanks in advance!
Basically, when you move an object, you take its position and rotation as reference, so if you increment +1 on the Y position of an object and this object is rotated, you'll increment on that direction.
but with Vector3.up, you use the world space as reference, so
i want to give you a full answers here, but i would have to enter with some math, simplifying, the transform.up is the direction which the sprite is pointing, he gets the direction saying this:
"mousePosition.y" (GREEN) is the position Y of the mouse, and "mousePosition.x" (RED) is the X position of the mouse, with this two values, you have a coordinate, or a direction (Blue traced line), which unity transforms to quaternions and apply the value to your rotation (this in 2d). you want to use the Vector3 which uses a world space reference, because if you use a local reference, would happen something like this
and you would get the wrong direction.
Transform object automatically calculates a quaternion rotation using this up Vector like from default Vector3.up to new transform up vector.

Unity - Camera ScreenToWorldPoint returning odd values

The main camera's output is set to a render texture, which is applied to a material, which is applied to a quad that's scaled up to 128x72. The secondary camera is set to only see what is rendered to the child quad, who has the material with the render texture on it.
However Camera.main.ScreenToWorldPoint(Input.mousePosition) is returning values that aren't even close to the GameObject. I.E. The GameObject is instantiated at (0, 0, 0), and hovering over it shows the mouse at (307, 174). Moving the Rotating Object to the right edge of the screen will only return an x position of 64 (half of the 128px wide quad) so I'm not sure where the 300+ is coming from. Not sure if the quad/camera set up is responsible for this.
EDIT: Using a single orthographic camera, all properties the same except for using a render texture, instead of the setup I have now results in accurate ScreenToWorldPoint output.
The Input.mousePosition property will only return the x and y axis of the mouse position in pixels.
ScreenToWorldPoint requires the z axis too which Input.mousePosition doesn't provide. The z-axis value supposed to be the nearClipPlane of the camera. It will give you a position that's right in front of the camera.
Depending on the size of the 3D object you want to instantiate where mouse button is pressed, you will need to apply an offset to it to make it totally visible to the screen. For a simple cube created in Unity, an offset of 2 is fine. Anything bigger than that, you will need to increase the offset.
Below is a complete example of how to properly use ScreenToWorldPoint with Camera.nearClipPlane and an offset to instantiate a 3D object where mouse is clicked:
public GameObject prefab;
public float offset = 2f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Camera cam = Camera.main;
Vector2 mousePos = Vector3.zero;
mousePos.x = Input.mousePosition.x;
mousePos.y = Input.mousePosition.y;
Vector3 worldPoint = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, cam.nearClipPlane + offset));
Instantiate(prefab, worldPoint, Quaternion.identity);
}
}
You may not be calling the Camera.ScreenToWorldPoint method correctly. In particular, the z position of the screen position parameter that's passed to this method should be defined as world units from the camera. See the Unity documentation on Camera.ScreenToWorldPoint.
Instead of Camera.main.ScreenToWorldPoint(Input.mousePosition), I think this is the correct way to call Camera.ScreenToWorldPoint:
var cameraPosition = Camera.main.transform.position;
// assuming `transform` is the transform "Virtual Screen Quad"...
float zWorldDistanceFromCamera = transform.position.z - cameraPosition.z;
var screenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, zWorldDistanceFromCamera);
var worldPoint = Camera.main.ScreenToWorldPoint(screenPoint);
Debug.LogFormat("mousePosition: {0} | zWorldDistanceFromCamera: {1} | worldPoint: {2}",
Input.mousePosition,
zWorldDistanceFromCamera,
worldPoint.ToString("F3"));
(If this isn't working, could you update your question or reply to this post with a comment with details showing the values that are logged at each step?)
I was just struggling with this problem and this question helped me find the answer, so thank you for posting it!
The issue has nothing to do with the z axis or how you're calling Camera.ScreenToWorldPoint. The issue is that the camera you're calling it on is rendering to a RenderTexture, and the dimensions of the RT don't match the dimensions of your game window. I wasn't able to find the implementation of the method in the reference source, but whatever it's doing is dependent on the resolution of the RenderTexture.
To test this, click the stats button in the game window to display the game window's screen size. The coordinates you get will match the ratio between that and the RenderTexture resolution.
Solutions:
Don't call this method on a camera targeting a rendertexture, either target the screen (none) or create a child camera that matches the position of the camera you need
Match the RT resolution to the screen. Obviously this may have performance implications, or cause issues if the screen size changes.
Don't use Camera.ScreenToWorldPoint. Depending on the use case, using a raycast may be simpler or more reliable.
Since using a default camera was returning the correct values, I simply added another one to detect the mouse position independent of the render texture/quad setup.

c# XNA 4.0 Camera zoom and sprite resizing

Inside my project, I have a sprite being draw of a box. I have the camera zoom out when clicking a key. When I zoom out, I want my box to scale it's dimensions so it stays consistent even though the camera has zoomed out and "shrunk" it.
I have tried multiplying the object's dimensions by 10% which seems to be the viewpoint's adjustment when zooming out, but that doesn't seem to work. Now this may sound dumb, but would scaling the sprite in the draw function also change the sprite's dimensions?
Let's say the box is 64x64 pixels. I zoom out 10% and scale the sprite. Does the sprite still have the boundaries as 64x64 or is the up-scaling also changing it's dimensions?
Scaling using SpriteBatch.Draw()s scale argument will just draw the sprite smaller/bigger, i.e. a 64x64 one will appear as 7x7 pixels (the outer pixels being alpha blended if enabled). However there are no size properties on the sprite, if you have your own rectangle, position variables for the sprite SpriteBatch.Draw() of course will not change those.
An alternative is draw the sprite in 3D space then everything is scaled when you move your camera, so the sprite will appear smaller though it will still be a 64x64 sprite.
How to draw a sprite in 3D space? Here is a good tutorial http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2/Point_sprites.php. (You will need to take time to learn about using 3D viewports, camera's etc, see here: http://msdn.microsoft.com/en-us/library/bb197901.aspx)/
To change sprite dimensions you need to change Rectangle parameter for SpriteBatch.Draw. To calculate zoom on rectange:
Rectangle scaledRect = new Rectangle(originalRectangle.X, originalRectangle.Y, (int)(originalRectangle.Width*zoom), (int)(originalRectangle.Height*zoom)); // where zoom default is 1.0f
When drawing use:
spriteBatch.Draw(Texture, scaledRect, Color.White);
Now I'm sorry to assume it, but without knowing why you doing what you doing - I think you doing something wrong.
You should use camera transformation to zoom out/in. It is done like that:
var transform = Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0))* // camera position
Matrix.CreateRotationZ(_rotation)* // camera rotation, default 0
Matrix.CreateScale(new Vector3(Zoom, Zoom, 1))* // Zoom default 1
Matrix.CreateTranslation(
new Vector3(
Device.Viewport.Width*0.5f,
Device.Viewport.Height*0.5f, 0)); // Device from DeviceManager, center camera to given position
SpriteBatch.Begin( // SpriteBatch variable
SpriteSortMode.BackToFront, // Sprite sort mode - not related
BlendState.NonPremultiplied, // BelndState - not related
null,
null,
null,
null,
transformation); // set camera tranformation
It will change how sprites are displayed inside sprite batch, however - now you also must account for different mouse coordinates (if you using mouse input). To do that you must transform mouse position to transformed world matrix:
// mouse position, your tranformation matrix
public Vector2 ViewToWorld(Vector2 pos, Matrix transform)
{
return Vector2.Transform(pos, Matrix.Invert(transform));
}
I used the code without direct access to test it, so if something will not work - feel free to ask.
This is not answer to your question directly, if you could provide reason why you want re-size sprite when zooming instead of zooming camera - maybe I could better answer your question, also you should fallow markmnl link to understand world transformations and why you seem to need it in this situation.

Categories