Find out camera world width and height? - c#

So here is my problem in a nutshell:
I want to know how spawn an object in the middle of the screen, which means I want find the screen's width and height values in World units.
Camera Position: 0,23,-10
Camera Rotation: 60,0,0
So I have tried this:
Vector3 screenWorldSize = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, -10));
// In the Update function
If(Input.GetKeyDown(Keycode.P))
{
GameObject tempObject = Instantiate(gamePrefab);
tempObject.transform.position = new Vector3(screenWorldSize.x, 1.5f, 10f);
}
But the tempObject position is not correct (Not in the middle), So I tried to Debug.Log(screenWorldSize) and I get this result (-10.3, 28.8, -20.0)
I tried using Camera.main.ViewPortToWorldPoint() with (0,0,-10) and (1,0,-10) and I got almost the same result.
Here is an image of the scene..
Is there something that I don't understand?
How to get the screen edges in World points?

Very simple. You don't need the width and height at all, you just need the direction.
// this is a vector matching the camera's direction
Vector3 cameraDirection = Camera.main.transform.rotation * Vector3.forward;
// this is the camera position
Vector3 cameraPosition = Camera.main.transform.position;
If you want to just create the object a certain distance from the camera, you can do this to get its position
Vector3 position = cameraPosition + cameraDirection * distance;
If you want to spawn the object on another object pointed at by the camera, you need this:
RaycastHit hit;
if (Physics.Raycast(cameraPosition, cameraDirection, out hit))
{
Vector3 position = hit.point;
[..]
}

Related

GetPoint() in Ray but with Padding and Angle

This might be an odd question, but as fairly new to Unity I don't know how to go about my problem, but I find the Ray() class as one of the most useful classes for all kinds of work. Anyhow, to compute a given point of a Ray it's easy to call .GetPoint(distance). - But is there a way to do a call like .GetPoint(distance, padding, angle)?
For instance, given the (3D) Ray from a to b
a--c----b
|
d
A call to .GetPoint(3) would return c, and a call to the wanted/new method .GetPoint(3, 2, 0) should return d. Further, calling .GetPoint(3, 2, 90) should return d when it's behind (or above) c.
I guess I should have paid more attention in math class...
If you don't mind Unity finding an arbitrary starting point, you can use Vector3.OrthoNormalize to get a starting point for you.
Then, you can use Quaternion.AngleAxis to rotate the point around the ray's direction (you have to offset the ray to/from the origin for the rotation operation).
Vector3 GetPaddedPoint(Ray ray, float distance, float padding, float angleInDegrees)
{
Vector3 rayDirection = ray.direction;
Vector3 startingOrtho;
Vector3.OrthoNormalize(ref rayDirection, ref startingOrtho);
// Find some point padding from ray at distance from origin
Vector3 axisPoint = ray.GetPoint(distance);
Vector3 startingPoint = padding * startingOrtho+ axisPoint;
// Find where startingPoint would be if the origin of the ray was at the origin
Vector offsetPoint = startingPoint - ray.origin;
// Rotate the offsetPoint around ray direction using Quaternion
Quaternion rotation = Quaternion.AngleAxis(angleInDegrees, rayDirection);
Vector3 rotatedOffsetPoint = rotation * offsetPoint;
// Add back in the ray's origin
return rotatedOffsetPoint + ray.origin;
}
If you find that you prefer a particular kind of direction for a starting point, you can pass in a startingOrtho. Keep the OrthoNormalize call to ensure that it startingOrtho becomes orthogonal to the ray and normalized if it isn't already.
Vector3 GetPaddedPoint(Ray ray, float distance, float padding, float angleInDegrees, Vector3 startingOrtho)
{
Vector3 rayDirection = ray.direction;
Vector3.OrthoNormalize(ref rayDirection, ref startingOrtho);
// Find some point padding from ray at distance from origin
Vector3 axisPoint = ray.GetPoint(distance);
Vector3 startingPoint = padding * startingOrtho+ axisPoint;
// Find where startingPoint would be if the origin of the ray was at the origin
Vector offsetPoint = startingPoint - ray.origin;
// Rotate the offsetPoint around ray direction using Quaternion
Quaternion rotation = Quaternion.AngleAxis(angleInDegrees, rayDirection);
Vector3 rotatedOffsetPoint = rotation * offsetPoint;
// Add back in the ray's origin
return rotatedOffsetPoint + ray.origin;
}

How do you shoot bullets at Mouses position

I recently started developing my very first top down 2d game. My problem is not knowing exactly how to get the bullet to go where the mouse is facing at the time of the activation of the bullet. I have a face mouse function as seen here
void faceMouse()
{
Vector3 mousePosition = Input.mousePosition;
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
Vector2 direction = new Vector2(
mousePosition.x - transform.position.x,
mousePosition.y - transform.position.y);
transform.up = direction;
}
However, I am not sure how to incorporate that if at all to be able to shoot at the location of my mouse. Thanks in advance!
You could try Quaternion.LookRotation() which creates a rotation based on a forward and upward vector (Documentation). Then you need to assing that rotation to your object. I use it something like this:
cursorPos = mainCamera.ScreenToWorldPoint(Input.mousePosition);
var forwardDirection = transform.position - cursorPos;
//Vector3.forward because is the z axis which is up/down in 2D
Quaternion playerRotation = Quaternion.LookRotation(forwardDirection, Vector3.forward);
transform.rotation = playerRotation;

Player rotation and camera rotation

i want the player to look into the direction, the camera is looking.
The camera follows the player (3rd person game style).
I've tried it with
transform.localRotation = new Quaternion(transform.localRotation.x,
cameraMain.transform.localRotation.y,
transform.localRotation.z,
transform.localRotation.w);
but it doesn't work.
Sometimes the player starts rotating the other direction.
the following code will make the object (specified in the parameter) face in the direction of where the main camera is looking:
public void lookInDirectionOfCamera(Transform object) {
RayCastHit hit;
if (Physics.raycast(cameraMain.transform.position, cameraMain.transform.forward, out hit)) {
object.forward = hit.point - object.position;
}else { //if the raycast didnt hit anything, make the object face 100 units in front of the camera
Vector3 point = Camera.main.transform.position + Camera.main.transform.forward * 100;
object.forward = point - object.position;
}
}
This will make the player face the point that is forward to the camera. If you just want them to have the same rotation in the y-axis don't use Quaternions!
Instead, you can just do it with Euler angles:
transform.eulerAngles = new Vector3(transform.eulerAngles.x,
cameraMain.transform.eulerAngles.y,
transform.eulerAngles.y);
The reason not to use transform.localRotation is because that is a Quaternion. The y component in a Quaternion is not the same as the y-axis in a Euler angle (what you are used to seeing), Quaternions are very confusing so you should almost never set individual values in them. If you want to edit them only use the built-in methods.
Get the direction the camera is looking with cameraMain.transform.forward, make a copy with a y value of zero, then use Quaternion.SetLookRotation to look in that direction with the global up direction.:
Vector3 cameraDirection = cameraMain.transform.forward;
Vector3 characterLookDirection = new Vector3(cameraDirection.x,
0f,
cameraDirection.z);
Quaternion newRotation = new Quaternion();
newRotation.SetLookRotation(characterLookDirection, Vector3.up);
transform.rotation = newRotation;

How to move the camera on x- and z-axis so that viewpoint targets (0,0,0)?

I meanwhile found a solution, but I'd really like a code review. Perhaps there is an easier solution. I updated the script at the end of my question.
I have a camera in my scene with a specific position and rotation. I want to move the camera on the x- and z-axis so that it targets (0,0,0).
I have the position vector posVector of the camera object and the displacement vector dirVector, which is the viewing direction. Now at some point, posVector + dirVector will intersection the ground plane. This currently is (x,0,z) but I like to move the camera on the x- and z-axis so that this is (0,0,0). So I really need to know x and z.
I tried multiple things, but I still have trouble wrapping my head around vectors and intersections.
using UnityEngine;
[ExecuteInEditMode]
public class DebugHelper : MonoBehaviour {
public Camera mainCamera;
// This DebugHelper script runs in EditMode and will help me visualize vectors and also move the camera to where I want it to be.
private void Update()
{
Vector3 posVector = mainCamera.transform.position;
Vector3 dirVector = mainCamera.transform.rotation * Vector3.forward;
// Find scalar for dirVector that displaces posVector.y to 0
// posVector + dirVector * scalar = (x,0,z)
float scalar = Mathf.Abs(posVector.y / dirVector.y);
// Get the position vector of the current camera target at y=0.
Vector3 y0TargetVector = posVector + dirVector * scalar;
// Subtract the y0TargetVector from the posVector to move it back to zero. This works because y0TargetVector.y is 0 and therefore the height is the same.
mainCamera.transform.position -= y0TargetVector ;
Debug.DrawRay(posVector, dirVector * scalar, new Color(0, 1, 0));
}
}

XNA: get Vector3 from Matrix

I thought I understood matrix math well enough, but apparently I'm clueless
Here's the setup:
I have an object at [0,0,0] in world space. I have a camera class controlled by mouse movements to rotate and zoom around the object such that it always looks at it. Here is how I calculate my viewMatrix from the camera:
public Matrix viewMatrix {
get {
return
Matrix.CreateFromAxisAngle(Vector3.Up, rotAngle)
* Matrix.CreateFromAxisAngle(Vector3.Left, pitchAngle)
* Matrix.CreateTranslation(0, 0, distance)
;
}
}
I need to be able to get the position of the camera in world space so I can get its distance from the box--particularly its distance from each face of the box. How can I get the camera's xyz position in world space coords?
I've tried:
// all of these only return [0, 0, distance];
Vector3 pos = Vector3.Transform(Vector3.Zero, viewMatrix);
Vector3 pos = viewMatrix.Translation;
Vector3 pos = new Vector3(viewMatrix.M41, viewMatrix.M42, viewMatrix.M43);
It seems like the rotation information is being lost somehow. The strange thing is that the viewMatrix code works perfectly for positioning the camera!
or to simplify slightly:
Vector3 pos = Matrix.Invert(view).Translation;
Once again, I figure out the problem within seconds of posting the question:
I needed to invert the view matrix. The rotation info was being lost because it plays no part in the distance calculation until the view matrix is inverted. The rotation was at the wrong "end" of the transformation.
Vector3 pos = Vector3.Transform(Vector3.Zero, Matrix.Invert(viewMatrix));

Categories