I am trying to move (fire) a sphere in the direction of a mouse click. But when I click, the sphere moves in unpredictable directions.
My code for adding the force to move the sphere:
if (Input.GetMouseButtonDown(0)){
RaycastHit hit;
/**
* We r using raycasting to detect mouse click on plane
* */
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit)){
newPosition = hit.point;
this.GetComponent<Rigidbody>().AddForce( (newPosition).normalized * 25, ForceMode.Impulse );
}
}
You've supplied an incorrect argument for Rigidbody.AddForce(). The vector you supply for the first argument should not be the position you want the force to point towards - it should be the direction of the force, multiplied by the magnitude.
In this case, you can calculate the direction of the force by subtracting the current position of the object from the target position:
Vector3 forceDir = newPosition - transform.position;
this.GetComponent<Rigidbody>().AddForce( forceDir.normalized * 25, ForceMode.Impulse );
Hope this helps! Let me know if you have any questions.
Related
I am trying to make a gun in Unity that shoots a Raycast with a Line. (in 2d) I am using the player position as the origin and the mouse position as the direction. This works perfectly when there is a collision detection, but when there is not a collision, I have to find the direction and calculate the end point manually, because I still want the line to render if the player misses their shot. Here is my code to find this end point:
//finding the position of Mouse in worldspace
Vector3 mousePos = CameraController.mouseToWorld(Input.mousePosition);
mousePos.z = 0;
//Calculating whether or not the raycast is a hit
RaycastHit2D Ray = Physics2D.Raycast(Player.transform.position,mousePos,distance);
if(Ray.collider != null)
{
PassTheHit(Ray, Ray.collider.gameObject.name);
point = Ray.point;
}
else
{
//Calculating the farthest point on the line. this does not work.
point = (transform.position - mousePos).normalized;
point *= -1 * (distance / 2);
point.z = 0f;
}
Particularly note the else{} statement. The calculation to find the point does not work. It is waaaay too long and does not shoot in the right direction.
Any help is greatly appreciated.
Either way you are using your Physics2D.Raycast wrong. It expects a
Start position
and a direction
you are passing in a second position.
What you rather want to do is using the direction
Vector2 mousePos = CameraController.mouseToWorld(Input.mousePosition);
Vector2 direction = ((Vector2)(mousePos - transform.position)).normalized;
which then you can use for both things
RaycastHit2D Ray = Physics2D.Raycast(Player.transform.position, /*here*/ direction, distance);
if(Ray.collider != null)
{
PassTheHit(Ray, Ray.collider.gameObject.name);
point = Ray.point;
}
else
{
point = transform.position + /*and here*/ direction * distance;
}
Sidenote: Avoid to give a RaycastHit2D the name Ray as there is a type that is called Ray so it is misleading ;)
I am trying to learn how to Raycast in Unity2D.
Here is my code:
Ray ray;
void Update()
{
ray = new Ray(transform.position, Input.mousePosition);
Debug.DrawRay(transform.position,Input.mousePosition);
}
This results in strange behavior.
transform.position is the Vector3 of the player object.
I want to shoot a ray from the Player Object through the Mouse Position.
However, this does not seem to work.
The line is drawn, but behaves weirdly. It does not point toward it at all. It's hard to accurately describe its behavior as anything except erratic.
What am I doing wrong?
I think there may be something wrong with putting in Input.mousePosition and directions in general. I would be very thankful for any help you can give.
Note: I am using Unity 2D.
When you use Input.mousePosition you get a Vector2 which represents the position of the mouse relative to the camera. This means the X and Y you get are actually the X and Y of the position of the mouse on the screen.
These coordinates are not world coordinates.
For example if you were to draw a ray from transform.position of a player standing at 0,0,0 to the mouse position of 500, 250 you would get a gigantic and seemingly randomly pointing ray.
To convert from where the mouse is on the screen(Screen Coordinates) to what it's pointing to in-game(World Coordinates) you can use Camera.ScreenToWorldPoint.
For example
Ray ray;
void Update()
{
// get the mouse screen pos
Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
// convert it
Vector3 worldMousePosition = Camera.Main.ScreenToWorldPoint(mousePosition);
ray = new Ray(transform.position, );
Debug.DrawRay(transform.position, worldMousePosition);
}
I'm trying to add dashing to the player in a Diablo-esque game I'm working on, and it "works" where you can dash towards your cursor.
if (isDashing)
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100, movementMask))
{
motor.MoveToPoint(hit.point);
motor.speed = 150;
}
}
I get the mouse position, then move to that position with enormous velocity. MoveToPoint() function uses NavMeshAgent's SetDestination(point) function and this again "works" but the problem is naturally there isn't a limit to how far you can dash. You can have the mouse way over at the end of the screen and the character will still dash there.
I figured I should be using a Vector3 to define the limits of the dash, but I can't quite nail it down. I get the direction below and then apply the magnitude, but it does not work how I imagined it would.
if (Physics.Raycast(ray, out hit, 100, movementMask))
{
float mag = (hit.point - transform.position).magnitude;
if (mag < dashLength)
{
Vector3 dir = (hit.point - transform.position).normalized;
Vector3 newVector = dir * (dashLength - mag);
motor.MoveToPoint(newVector);
}
else
motor.MoveToPoint(hit.point);
motor.agent.speed = 150;
}
Any help would be appreciated
The main issue here is that you are treating a movement vector like a position. You want to start a the current transform.position and ADD the movement vector you calculated.
Further instead of extracting and checking the magnitude you can simply use Vector3.ClampMagnitude to keep the direction but make sure that the magnitude is not greater than your dashLength like e.g.
if (Physics.Raycast(ray, out hit, 100, movementMask))
{
// Calculate the difference only once
var movement = hit.point - transform.position;
// Make sure that delta has a maximum magnitude of dashLength
movement = Vector3.ClampMagnitude(delta, dashLength);
// MoveToPoint expects a position not only the movement vector
// so you start at your current position and add the movement
var newPosition = transform.position + movement;
motor.MoveToPoint(newPosition);
motor.agent.speed = 150;
}
Here is the video
I'm trying to hover the player over the cursor, but it doesn't work exactly, here's the code:
var playerPlane = new Plane(Vector3.up, transform.position);
// Generate a ray from the cursor position
var 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.
var targetPoint = ray.GetPoint(hitdist);
// Determine the target rotation. This is the rotation if the transform looks at the target point.
var targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
// Smoothly rotate towards the target point.
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
}
Here is the player hierarchy
The player and his scripts:(further child objects)
mesh
the same mesh that changes position depending on the rotation of its parent
I am trying to make an enemy in my game that can see the light coming from the flashlight of the player. I am doing this by raycasting from the origin of the flashlight towards 5 directions: the middle of the light beam, and the top, bottom, left and right end of the light. Something like this:
I use the following update function in the flashlight of the player:
void Update () {
float angle = GetComponent<Light>().spotAngle;
if (Physics.Raycast (transform.position, transform.forward, out hitMiddle)){
hitMiddlePosition = hitMiddle.transform.position;
}
if (Physics.Raycast (transform.position, Quaternion.AngleAxis(-angle, transform.up) * transform.forward, out hitDown)){
hitDownPosition = hitDown.transform.position;
}
if (Physics.Raycast (transform.position, Quaternion.AngleAxis(angle,transform.up) * transform.forward, out hitUp)){
hitUpPosition = hitUp.transform.position;
}
if (Physics.Raycast (transform.position, Quaternion.AngleAxis (angle,transform.right) * transform.forward, out hitRight)){
hitRightPosition = hitRight.transform.position;
}
if (Physics.Raycast (transform.position, Quaternion.AngleAxis (-angle, transform.right) * transform.forward, out hitLeft)){
hitLeftPosition = hitLeft.transform.position;
}
}
This code is supposed to track the location of each of the hits. However, the locations never seem to correspond to the locations the light beam is hitting. The locations usually are identical in all directions (Vector3(-87.77855, 0, 87.83269)) and do not change when the player is moving. Looking in different directions sometimes changes one of the values.
I tried a lot of different ways of the direction for the raycasts, but I am still not very confident the rays are being cast in the direction I intended.
Any tips?
Many thanks!
I found the answer, and it was (of course) very trivial.
The problem was that hit.transform.position gave the position of the object that was hit, not the position of the actual intersect location.
Changing this to hit.point resolved the problem. It now works as designed.