Mouse input and z-axis - c#

void OnMouseDrag() {
float distance = transform.position.z - Camera.main.transform.position.z;
Vector3 pos = Input.mousePosition;
pos.z = distance;
Vector3 mousePosition = new Vector3(pos.x, pos.y, pos.z);
Vector3 objPosition = Camera.main.ScreenToWorldPoint(mousePosition);
transform.position = objPosition;
}
This is the code snippet help me to move the object on mouse drag. It is moving object on mouse drag in x axis while z axis movement is not working correctly using mouse. I basically want to move the object on x and z-Axis using mouse Input.
What is wrong how can i get z position from the mouse input in order to move the object on z axis correctly.

When you casting ray to your object it is being calculated multiple times so it returns your ball position when its not being move a real deal you can try something like this
void OnMouseDrag() {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 10, Color.yellow);
Debug.Log(ray);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Camera.main.farClipPlane))
{
if (hit.transform.gameObject.name == "CameraElasticPoint")
{
return;
}
else{
transform.position = new Vector3(hit.point.x,hit.transform.position.y+1, hit.point.z);
hitPoint = Input.mousePosition;
}
}
}
what it will do it will ignore your objects and works only on other hit info which would be your floor or any other surface you are trying to drag your object along and it will drag your object on X and Z axis taking the Y position of the Floor so it will always remain on top of the floor or any other surface collider on
let me know if it works
Good day

I would recommend going through the Unity Tutorial here:
http://unity3d.com/learn/tutorials/projects/survival-shooter-project
It might give you some ideas on how to solve the problem of x/z plane movement with the mouse.

No. screenpointtoray is very unnecessary here, you just need to say that pos.z is equal to pos.x....
like so...
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - dragOrigin);
pos.z = pos.x;
Vector3 move = new Vector3(0, pos.y * dragSpeed, pos.z * -dragSpeed);
always a pleasure x

Related

How to move objects to the z and y coordinates of the mouse in Unity 3D

I'm trying to make the orange box follow my mouse. But with my current script, it only goes about a quarter of a unit towards the direction of my mouse, then stops. I am completely stuck & lost
using UnityEngine.EventSystems;
using UnityEngine;
public class drag : MonoBehaviour
{
private void Update()
{
Vector2 mousePos = Input.mousePosition;
Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, Camera.main.nearClipPlane));
transform.position = new Vector3(transform.position.x, worldPos.y, worldPos.z);
}
}
Any help? This is for a game jam, I've got around 48 more hours to finish. Thanks!
Here you go:
private void Update()
{
// Get the mouse position
Vector3 mousePos = Input.mousePosition;
// Set the z component of the mouse position to the absolute distance between the camera's z and the object's z.
mousePos.z = Mathf.Abs(Camera.main.transform.position.z - transform.position.z);
// Determine the world position of the mouse pointer
Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
// Update the position of the object
transform.position = worldPos;
}

Obstacle Avoidance

I'm trying to implement obstacle avoidance within steering behaviors for a university project.
When I run the project, the AI agent seems to get confused and 'spaz' out moving from left to right very quickly and still doesn't avoid obstacles correctly.
I'm trying to cast a box in front of the agent so that when that box collides with an obstacle, it'll steer away from it and continue to move wander.
Here is the code for the Obstacle Avoidance
public Vector3 ObstalceAvoidance()
{
//Cast a ray from the centre of the agent, in it's forward direction
Ray ray = new Ray(transform.position, transform.forward);
//Name a raycastHit
RaycastHit hitInfo;
//Set avoidanceForce to ZERO for all axis
Vector3 avoidanceForce = Vector3.zero;
//Calculate the 'Avoidance Force'
if(Physics.BoxCast(transform.forward, new Vector3(2.5f, 2.5f, 20.0f), transform.forward, out hitInfo, transform.rotation, maxDistance))
{
if(Vector3.Angle(hitInfo.normal, transform.up) > floorAngle)
{
//Reflect the Vector
avoidanceForce = Vector3.Reflect(agent.velocity, hitInfo.normal);
//Calculate the dot product between the Force and Velocity
if (Vector3.Dot(avoidanceForce, agent.velocity) < -0.9f)
{
//Transform Right
avoidanceForce = transform.right;
}
}
}
if(avoidanceForce != Vector3.zero)
{
//Calculate desired velocity
desiredVelocity = (avoidanceForce).normalized * agent.maxSpeed;
//Calculate the steering Force
steeringForce = desiredVelocity - agent.velocity;
oldSteeringForce = steeringForce;
forceTimer = 0;
}
else
{
steeringForce = Vector3.zero;
}
return steeringForce;
}

Move 2D object at constant speed and turn towards touch point

I've been trying for a while to get a 2D player to work kind of like a bullet that is always moving forward (forward being in this case the local X axis for the GameObject, as that's the way that the character is facing) and only changes direction when you touch a point on the screen, in which case it should smoothly start turning towards that point.
One problem I have is that I can't manage to keep the character moving smoothly at a constant speed in the last direction it was facing before, and the other problem that I'm finding is that the character is turning around the wrong axis and instead of rotating based on the Z axis, it's always rotating on the Y axis, which makes the sprite become invisible to the camera.
Here's the code that I have right now:
Vector3 lastTouchPoint;
private void Start()
{
lastTouchPoint = transform.position;
}
void Update()
{
if (Input.touchCount > 0)
{
// The screen has been touched so store the touch
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved)
{
// If the finger is on the screen, move the object smoothly to the touch position
lastTouchPoint = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
}
}
transform.position = Vector3.Lerp(transform.position, lastTouchPoint, Time.deltaTime);
//Rotate towards point
Vector3 targetDir = lastTouchPoint - transform.position;
transform.LookAt(lastTouchPoint);
}
Thanks in advance!
keep the character moving smoothly at a constant speed
You probably didn't understand what Lerp actually is: This interpolates between the two positions on the given factor where 0 means fully the first position, 1 means fully the last position and e.g. 0.5f would mean in the center between both positions.
This results in faster speeds if the positions are further apart and becomes slower and slower the smaller the distance between both positions becomes. In some cases especially with a factor that small as in your case the object might even never actually reach the target position.
Using this with a dynamic factor of Time.deltaTime makes no sense as this value changes every frame and jitters somewhere around 0,017 (assumin 60 FPS).
You could rather use Vector3.MoveTowards with a fixed constant speed
// set via the Inspector
public float speedInUnitsPerSecond = 1;
...
transform.position = Vector3.MoveTowards(transform.position, lastTouchPoint, Time.deltaTime * speedInUnitsPerSecond);
if you want to keep moving but stop once the touched position is reached.
If you rather wanted to continue moving in the according direction no matter what you could rather store the direction instead of a position and use a straight forward Transform.Translate
// set via the Inspector
public float speedInUnitsPerSecond = 1;
private Vector2 lastDirection;
privtae void Update()
{
...
// If the finger is on the screen, move the object smoothly to the touch position
var touchPosition = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
lastDirection = (touchPosition - transform.position).normalized;
...
// move with constant speed in the last direction
transform.Translate(lastDirection * Time.deltaTime * speedInUnitsPerSecond);
...
}
the character is turning around the wrong axis and instead of rotating based on the Z axis, it's always rotating on the Y axis
Note that Transform.LookAt has an optional second parameterworldUp which by default is Vector3.up so a rotation around the global Y axis!
Since you rather want a rotation around the Z axis you should pass
transform.LookAt(lastTouchPoint, Vector3.forward);
I don't know your setup ofcourse but also note that
LookAt
Rotates the transform so the forward vector points at worldPosition.
As you describe it it is also possible that you don't want the objects forward vector to point towards the target position but actually rather the objects right (X) vector!
You can do this by rather simply directly setting the transform.right like e.g.
transform.right = (lastTouchPoint - transform.position).normalized;
or
transform.right = lastDirection;
Btw it would actually be enough to set this rotation only once, namely the moment it changes so in
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved)
{
// If the finger is on the screen, move the object smoothly to the touch position
lastTouchPoint = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
transform.right = (lastTouchPoint - transform.position).normalized;
}
or
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved)
{
// If the finger is on the screen, move the object smoothly to the touch position
var touchPosition = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
lastDirection = (touchPosition - transform.position).normalized;
transform.right = lastDirection;
}
I ended up finding the answer to my own problem using code to rotate smoothly from another post. Here's the code:
Vector3 lastTouchPoint;
Vector3 direction;
Vector3 vectorToTarget;
//Character controller variables
public float moveSpeed = 5f;
public float angularSpeed = 3f;
private void Start()
{
lastTouchPoint = transform.position;
}
void Update()
{
if (Input.touchCount > 0)
{
// The screen has been touched so store the touch
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
// If the finger is on the screen, move the object smoothly to the touch position
lastTouchPoint = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
direction = lastTouchPoint - transform.position;
vectorToTarget = lastTouchPoint - transform.position;
}
}
transform.position += direction.normalized * moveSpeed * Time.deltaTime;
float angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * angularSpeed);
}

How to rotate the position of an object based on mouse position?

I'm using this code at the moment to rotate a tank turret object towards the mouse position:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
Physics.Raycast(ray, out hit, range);
Vector3 dir = hit.point - transform.position;
Quaternion lookRotation = Quaternion.LookRotation(dir);
Vector3 rotation = lookRotation.eulerAngles;
transform.rotation = Quaternion.Euler(0f, rotation.y, 0f);
Is there any way to create a rotation even when the ray doesn't hit any object, (pointing the mouse where there is no object initiated) (hit is false)? Also is there a better approach for a better solution?
Thanks.
Basically, I just get the position of the mouse on screen, compare it to the target object, convert that to degrees, and rotate the object around the wanted axis (Y for topDown 3D space, Z for 2D).
void RotateTowards()
{
var mouse = Input.mousePosition;
var screenPoint = Camera.main.WorldToScreenPoint(tankTransform.localPosition);
var offset = new Vector2(mouse.x - screenPoint.x, mouse.y - screenPoint.y);
var angle = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, angle, 0);
}

Unity enemy ai always firing bullets high over the player

Got an issue where the enemy will fire at the player, but always seems to go high or to the side of the player even when the player is stationary and isn't moving. Am I doing something wrong in my code which creates this wild issue or is it just a random annoying bug?
Using the same script for the player albeit it under a different name works, which leads me to believe the issue lies within the fire point. Under the player's script I fire like so:
// Get the place the player has clicked
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Holds information regarding the mouseclick
RaycastHit hitInfo;
// Now work out if we fire or not
if (Physics.Raycast(ray, out hitInfo))
{
if(hitInfo.distance < maxRange)
{
FireAtPoint(hitInfo.point);
Whereas in the enemy script it is just done through the player's position.
// Holds information regarding the mouseclick
RaycastHit hitInfo;
// Now work out if we fire or not
if (Physics.Raycast(player.transform.position,transform.forward, out hitInfo))
{
Is this underlying issue in the Physics.Raycast call then?
Rest of code for reference:
//More above this but doesn't influence the firing
if (Physics.Raycast(player.transform.position,transform.position, out hitInfo))
{
if (hitInfo.distance < maxRange)
{
FireAtPoint(hitInfo.point);
}
}
private void FireAtPoint(Vector3 point)
{
// Get the velocity to fire out at
var velocity = FiringVelocity(point, angle);
Rigidbody rg = Instantiate(bulletPrefab.gameObject, firePoint.position, firePoint.rotation).GetComponent<Rigidbody>();
EnemyBulletController newProjectile = rg.GetComponent<EnemyBulletController>();
newProjectile.speed = velocity;
}
private Vector3 FiringVelocity(Vector3 destination, float angle)
{
// Get the direction of the mouse click from the player, then get the height differential.
Vector3 direction = destination - transform.position;
float height = direction.y;
height = 0;
// Get the distance in a float of the vector3
float distance = direction.magnitude;
// Turn the firing angle into radians for calculations, then work out any height differential
float AngleRadians = angle * Mathf.Deg2Rad;
direction.y = distance * Mathf.Tan(AngleRadians);
distance += height / Mathf.Tan(AngleRadians);
// Calculate the velocity magnitude
float velocity = Mathf.Sqrt(distance * Physics.gravity.magnitude / Mathf.Sin(2 * AngleRadians));
// Return the normalized vector to fire at.
return velocity * direction.normalized;
}
Picture for reference:
Your equation for computing the velocity looks doubtful. Let's re-derive it:
The equations of free-fall motion under constant gravity are:
After rearranging by substituting the first into the second, we find an expression for the firing velocity:
This is different to what you have, as you are missing the h/d term; said term also gives a constraint on the allowed values of θ:
(Basically means that if you fire directly at the target the bullet would never reach due to gravity)
There are many other problems with your code; just to list three:
Why set height to zero?
Why add a correction to distance? The correction has no physical interpretation.
The fix suggested by #BasillePerrnoud
Amended code:
private Vector3 FiringVelocity(Vector3 destination, float angle)
{
Vector3 direction = destination - transform.position;
float height = direction.y;
float distance = Mathf.Sqrt(direction.x * direction.x + direction.z * direction.z); // *horizontal* distance
float radians = angle * Mathf.Deg2Rad;
float hOverd = height / distance;
float tanAngle = Mathf.Tan(radians);
if (tanAngle <= hOverd)
// throw an exception or return an error code, because no solution exists for v
float cosAngle = Mathf.Cos(radians);
direction.Y = distance / cosAngle;
float velocity = Mathf.Sqrt((distance * Physics.gravity.magnitude) /
(2 * cosAngle * cosAngle * (tanAngle - hOverd)));
return velocity * direction.normalized;
}
I think you use Raycast wrongly. According to the doc, the second argument is the direction, not the destination:
if (Physics.Raycast(player.transform.position,transform.position, out hitInfo))
Should be
if (Physics.Raycast(transform.position, player.transform.position -
transform.position, out hitInfo))
That would explain why it is not firing at the right moment and why the direction is not accurate (since hitInfo is wrong)

Categories