My camera casts a ray to the centre of the screen and I have an object that looks at that direction. The problem is, I made it such that certain keys rotate the camera, so there's a new centre, and the ray from the camera moves too but the object doesn't look at the new direction
Here's my code:
void Update (){
int x = Screen.width / 2;
int y = Screen.height / 2;
//Get centre of screen from camera
Ray ray = Camera.main.ScreenPointToRay (new Vector3 (x, y));
Debug.DrawRay (ray.origin, ray.direction * 1000, new Color (1f, 0.922f, 0.016f, 1f));
//Set object direction
object.transform.LookAt (ray.direction);
}
I'd really appreciate some help with this, thank you!
I found a solution. Instead of looking at ray direction, I got a point from the ray using GetPoint and made the object look at that. It's working fine now.
Well the ray would be starting from the camera and going towards the middle of the screen. So if you wanted the object to look at the camera every Update, the direction would be wrong, but also what if the object wasn't in the center of the screen? If I'm misinterpreting your question, please comment and explain further. I think a better way to get the forward direction of the camera would be to use Camera.main.transform.forward, and you could put that in a Physics.Raycast as well. To have something always look at the camera you could try object.transform.LookAt(Camera.main.transform.position, -Vector3.Up);.
Edit: Also, if you mean the have the object look the same direction as the camera, you could always try object.transform.forward = Camera.main.transform.forward, or keep up with object.transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward, Transform.up);
Alright new idea:
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
RaycastHit hit;
if(Physics.Raycast(ray, out hit))
{
Vector3 point = hit.point;
object.transform.LookAt(point, Vector3.Up);
}
Related
I try to make a Drag and Drop function in Unity3D.
How it should work:
I have an Object on a ground and i want to be able to just drag it around the ground.
I only want to change the x and the z position.
Sadly no Tutorial could help me out with this problem.
I tried raycasting and it worked to 'select' the Object but i could not change the position.
I managed to write a script to show me the mouse position in world Space but it isnt working really.
Can someone help me out with this and explain me how the code works?
What steps do i need to do so it works?
You can use raycast here and use the hit point as you position when dragging.
void MoveObject()
{
RaycastHit hit;
float movetarget;
//startPoint = hit.point;
ray = GetComponent<Camera> ().ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 100, Color.yellow);
if (Physics.Raycast(ray, out hit))
{
movetarget = hit.distance;
if (activated == false)
{
wall = Instantiate(prefab, hit.point, prefab.transform.rotation);
activated = true;
}
startPoint = hit.point;
}
wall.transform.position = hit.point;
}
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;
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;
I've the point of origin readily available where my mouse is on screen like so,
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Now imagine a cube. Anywhere you click on this cube, a line is drawn from the edge clicked on, through the object, and stops at the other end. Orientation, vertical or horizontal, is determined by which side is clicked on, one of the 4 sides, or top or bottom.
How does one determine the distance (from one edge of a mesh to the other), and orientation (vertical or horizontal)?
Thoughts?
Only idea I have so far is to use collision detection and using CollisionEnter as the start point and somehow draw a line that reaches the opposite end of the mesh and using CollisionExit to determine the destination (or exit) point. Then doing some calculation to determine the distance between the Enter and Exit methods.
The only way I can think of approaching this would be to cast a ray back in the other direction....
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//offset the ray, keeping it along the XZ plane of the hit
Vector3 offsetDirection = -hit.normal;
offsetDirection.y = 0;
//offset a long way, minimum thickness of the object
ray.origin = hit.point + offsetDirection * 100;
//point the ray back at the first hit point
ray.direction = (hit.point - ray.origin).normalized;
//raycast all, because there might be other objects in the way
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach (RaycastHit h in hits)
{
if (h.collider == hit.collider)
{
h.point; //this is the point you're interested in
}
}
}
This offsets the ray to a new location so that it retains the same XZ coordinates of the original hit, so the resulting endpoints form a line that is perpendicular with the world / scene Y axis. To do this we use the camera's Forward direction (as we want to get a point farther away from the view point). If we wanted to get a point for a line that is perpendicular to the hit surface (parallel to the surface normal) we could create an offset using the hit.normal instead.
You will probably want to put a layermask or maxdist parameter into the two raycast methods (so it checks fewer things and is faster), but that's on you.
Original code: which finds the two endpoints of a "single" ray cast through the object.
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//offset the ray along its own direction by A LOT
//at a minimum, this would be the maximum thickness of any object we care about,
//PLUS the distance away from the camera that it is
ray.origin += ray.direction * 100;
//reverse the direction of the ray so it points towards the camera
ray.direction *= -1;
//raycast all, because there might be other objects in the way
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach(RaycastHit h in hits)
{
if(h.collider == hit.collider)
{
h.point; //this is the point you're interested in
}
}
}
So I'm trying to make the gun on the turret of my tank point towards the center of the screen just like in World of tanks where you have a crosshair for where the gun is pointing and the crosshair for the center of the screen.
The problem is that the gun crosshair which is a UI image in world space parented to the gun, doesn't exactly line up with the center of the screen which is the big crosshair in the image [enter image description here][1].
edit: so this works but how can I change it to the x axis?
public class CenterCursor : MonoBehaviour
{
// speed is the rate at which the object will rotate
public float speed;
void FixedUpdate()
{
// Generate a plane that intersects the transform's position with an upwards normal.
Plane playerPlane = new Plane(Vector3.up, transform.position);
// Generate a ray from the cursor position
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Determine the point where the cursor ray intersects the plane.
// This will be the point that the object must look towards to be looking at the mouse.
// Raycasting to a Plane object only gives us a distance, so we'll have to take the distance,
// then find the point along that ray that meets that distance. This will be the point
// to look at.
float hitdist = 0.0f;
// If the ray is parallel to the plane, Raycast will return false.
if (playerPlane.Raycast(ray, out hitdist))
{
// Get the point along the ray that hits the calculated distance.
Vector3 targetPoint = ray.GetPoint(hitdist);
// Determine the target rotation. This is the rotation if the transform looks at the target point.
Quaternion targetRotation = Quaternion.LookRotation( targetPoint - transform.position);
// Smoothly rotate towards the target point.
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
}
}
You can also try putting your turret object as a child of camera object...