I have an object moving forward constantly, I want to make it move on the X axis by mouse dragging any part of the screen (swiping), so I tried this code but when first clicking on the screen the object move to the mouse X position (without dragging)! do you have any suggestions on how to make it move only when dragging?
The Script:
private bool dragging = false;
private float distance;
public Rigidbody Ball;
public float Speed = 100;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
Ball.velocity = transform.forward * Speed * Time.deltaTime;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
distance = Vector3.Distance(transform.position, Camera.main.transform.position);
dragging = true;
}
if(Input.GetMouseButtonUp(0))
{
dragging = false;
}
if (dragging)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 rayPoint = ray.GetPoint(distance);
transform.position = new Vector3(rayPoint.x, transform.position.y, transform.position.z);
}
}
For the continues movement you can use GetMouseButton which is true while the button stays pressed (in contrary to GetMouseButtonDown which is true only the first frame the button is pressed)
You said the script is attached to the same as the RigiBody component. In such a case you should never place an object using
transform.position = ...
but instead use RigidBody.MovePosition like
Ball.MovePosition(new Vector3( ... ));
Finally store the initial position on mouse down and than use it as a reference point:
Vector3 initialPosition;
void Update()
{
// called the first time mouse button is pressed
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
initialPosition = transform.position;
Vector3 rayPoint = ray.GetPoint(0);
// Not sure but this might get you a slightly better value for distance
distance = Vector3.Distance(transform.position, rayPoint );
}
// called while button stays pressed
if (Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 rayPoint = ray.GetPoint(distance);
Ball.MovePosition(initialPosition + new Vector3(rayPoint.x, 0, 0));
}
}
Also note that I'm not sure that
// Update is called once per frame
void FixedUpdate () {
Ball.velocity = transform.forward * Speed * Time.deltaTime;
}
is what you want to do. The usage of Time.deltaTime makes not much sense here in my eyes. You either want to set the velocity to a certain speed like
Ball.velocity = transform.forward * Speed;
or you want to change a position using Time.deltaTime to have a smooth movement like
Ball.MovePosition(transform.position + transform.forward * Speed * Time.deltaTime);
Related
I'm really new to coding and English isn't my main language, so forgive any dumb errors and my English.
I'm working on a movement system that moves the player to click point, everything on the script seems to work, but in the game tab the player doesn't move at all. I already read a lot of information about Vector3.MoveTowards(), but nothing worked for me.
Vector3 currentpos;
Vector3 targetpos;
bool ismoving = false;
public float speed = 10f;
void Update()
{
currentpos = transform.position;
move();
if (Input.GetMouseButtonDown(0))
{
click();
}
}
void click() //get the position of the click using a raycast//
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit))
{
targetpos = hit.point;
targetpos.y = 0f; //only whants to move the player in the x and z axis//
ismoving = true;
move();
}
}
void move()
{
if (ismoving==true)
{
if (Vector3.Distance(currentpos,targetpos)>0.1f) //if distance between current position and target position is greater than 0.1f player should move//
{
currentpos = Vector3.MoveTowards(currentpos, targetpos, speed * Time.deltaTime);
Debug.Log("Current Position is:" + currentpos + " and target position is" + targetpos);
}
if(Vector3.Distance(currentpos,targetpos)<0.1f)
{
ismoving = false;
}
}
}
In the console the current position and the target position are right but the player doesn't move.
Well, you are chaning the value of currentpos but never asign it back to transform.position e.g. here
currentpos = Vector3.MoveTowards(currentpos, targetpos, speed * Time.deltaTime);
transform.position = currentpos;
I am trying to move my camera to a clicked Gameobjects position with a specified offset. So the script should calculate the resulting position by the clicked gameobjects position, the actual camera position and a offset.
I have tried it with this code:
Vector3 distanceVector = transform.position - target.transform.position;
Vector3 distanceVectorNormalized = distanceVector.normalized;
targetPosition = (distanceVectorNormalized * preferredDistance);
But I am getting some really weird values. Here is the code I made for this:
public float moveSpeed = 0.1f;
private bool moving = false;
private GameObject target;
// The distance between the camera and the targets position
private float preferredDistance = 3;
// The position the camera will move to
private Vector3 targetPosition;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, 100) == false) return;
Debug.Log(hit.transform.gameObject.name);
target = hit.transform.gameObject;
... Here should be the calculations
moving = true;
}
if (moving)
{
transform.position = Vector3.Lerp(transform.position, targetPosition, moveSpeed);
transform.LookAt(target.transform.position);
var offsetX = Math.Abs(transform.position.x - targetPosition.x);
var offsetZ = Math.Abs(transform.position.z - targetPosition.z);
if (offsetX < .01
&& offsetZ < .01) moving = false;
}
}
Your normalized distanceVector acts as the direction of the camera to the object.
This direction should be normalized, which you do, so it can be multiplied by your preferredDistance. It then becomes the offset of the camera from the target.
The part where it goes wrong is that you set this normalized offset as the new camera position, while it should be added to it:
Vector3 distanceVector = transform.position - target.transform.position;
Vector3 distanceVectorNormalized = distanceVector.normalized;
targetPosition = target.transform.position + (distanceVectorNormalized * preferredDistance);
Note the difference in the last line.
I have a ball that have a continuous bouncing, and I want to move it left and right in the x Axis with the mouse, so it follow the mouse's X movement.
I made the script bellow, but the ball didn't move with mouse!
Ball Script:
private Vector3 pos;
public Camera cam;
public Rigidbody Ball;
public float Speed;
public static float GlobalGravity = -9.8f;
public float GravityScale = 1.0f;
bool isforce = false;
private void Start(){
Ball = GetComponent<Rigidbody>();
Ball.useGravity = false;
}
private void FixedUpdate(){
Vector3 gravity = GlobalGravity * GravityScale * Vector3.up;
Ball.AddForce(gravity, ForceMode.Acceleration);
}
void force (){
isforce = false;
Ball.AddForce(Vector3.up * Speed, ForceMode.Impulse);
}
private void Update(){
if (isforce == true){
force();
}
if (Input.GetMouseButton(1)){
Vector3 mousePos = Input.mousePosition;
Vector3 wantedPos = Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, transform.position.y, 10));
transform.position = wantedPos;
}
}
private void OnCollisionEnter(Collision collision){
isforce = true;
}
try this and let me know what happens. yours was set to right click, but i changed this one to left click, other than that i just sat the balls x to the raw x of the mouse input.
private void Update(){
if (isforce == true){
force();
}
if (Input.GetMouseButton(0)){
Vector3 mousePos = Input.mousePosition;
Vector3 wantedPos = transform.position;
wantedPos.x=Input.mousePosition.x;
transform.position = wantedPos;
}
}
When you use transform.position, the Unity Physics will no apply to the rigidBody. Find your mouse position relative to the ball and add Force in the X direction accordingly.
You have a couple of options depending on what it is you want.
Also as #Hamed answered, when using physics you don't want to update the transform directly but add force using the Rigidbody.
Force Constant relative to where the Mouse is
if (Input.GetMouseButton(0))
{
Vector2 force = Vector2.zero;
//Get the Balls current screenX position
float ballX = Camera.WorldToScreenPoint(Ball.transform.position).x;
//Check if Click was Left or Right of the Ball
if (ballX > Input.mousePosition.x)
{
//Click was Left of the Ball
force = new Vector2(-1f, 0f);
}
else if (ballX < Input.mousePosition.x)
{
//Click was Right of the Ball
force = new Vector2(1f, 0f);
}
//Adjust force amount to your suiting
Ball.Addforce(force * Time.deltaTime);
}
Force relative to the mouse movement
if (Input.GetMouseButton(0))
{
Vector2 force = Vector2.zero;
float mouseDelta = Input.GetAxis("Mouse X");
//Check if the Mouse is going Left or Right
if (mouseDelta < 0f)
{
//Click was Left of the Ball
force = new Vector2(-1f, 0f);
}
else if (mouseDelta > 0f)
{
//Click was Right of the Ball
force = new Vector2(1f, 0f);
}
// Update force relative to mouse movement
force = Mathf.Abs(mouseDelta) * force;
//Adjust force amount to your suiting
Ball.Addforce(force * Time.deltaTime)
}
Hastily written, look then write your own :)
I am trying to make a simple game where I am shooting a projectile when the user touches the screen, I first spawn 8 projectiles (sprites) and when the user touches the screen I would like the top projectile to fly in the touch direction. I was able to do this; However, every time I shoot, the projectile goes in the wrong direction, here is an image which will illustrate the issue.
Obviously the image is still here but the object will continue flying until it goes out of the screen and then gets destroyed.
Here is the code snippet that handles this
GameplayController.cs
if (Input.GetMouseButtonDown(0))
{
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
position = Camera.main.ScreenToWorldPoint(position);
GameObject target;
target = new GameObject();
target.transform.position = position;
Arrow comp = currentArrows[0].GetComponent<Arrow>();
comp.setTarget(target.transform);
comp.GetComponent<Arrow>().arrowSpeed = 12;
comp.GetComponent<Arrow>().shoot = true;
currentArrows.RemoveAt(0);
Destroy(target);
}
I know I am getting the mouse input here and not the phone touch and that's fine for me, later I will convert it to the touch input.
Arrow.cs
public bool shoot = false;
public float arrowSpeed = 0.0f;
public Vector3 myDir;
public float speed = 30.0f;
private Transform target;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(shoot)
{
transform.position += transform.right * arrowSpeed * Time.deltaTime;
}
}
public void setTarget(Transform targetTransform)
{
this.target = targetTransform;
Vector3 vectorToTarget = target.position - transform.position;
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 * speed);
}
private void OnBecameInvisible()
{
print("Disappeared");
Destroy(gameObject);
Gameplay.instance.isShooting = false;
}
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
I think that your problem is that you're getting the screen coordinates by click, not the world coordinates, which is actually two different things. In order to direct your projectile correctly you need to convert your screen coordinates to world like it's done here.
The next thing is how you move the projectile:
transform.position += transform.right * arrowSpeed * Time.deltaTime;
You're moving the projectile to the right and then rotating it somehow. Maybe you should try to move it with Vector3.Lerp, which will be easier and rotate it with Transform.LookAt.
I have a method that will rotate my object to the point my mouse just clicked on. However, my object only rotates as long as my mouse button is held down.
My main rotation method is this:
void RotateShip ()
{
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
Debug.Log (Input.mousePosition.ToString ());
Plane playerPlane = new Plane (Vector3.up, transform.position);
float hitdist = 0.0f;
if (playerPlane.Raycast (ray, out hitdist))
{
Vector3 targetPoint = ray.GetPoint (hitdist);
Quaternion targetRotation = Quaternion.LookRotation (targetPoint - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, speed * Time.deltaTime);
}
}
I call this method inside the FixedUpdate method and I've wrapped it inside the following if statement:
void FixedUpdate ()
{
// Generate a plane that intersects the transform's position with an upwards normal.
// Generate a ray from the cursor position
if (Input.GetMouseButton (0))
{
RotateShip ();
}
}
However, the object will still only rotate as long as my mouse button is held down. I want my object to continue to rotate to the point my mouse just clicked until it reaches that point.
How can I amend my code properly?
It's only rotating while your mouse is down because that's the only time you tell it to rotate. In your FixedUpdate (which Imtiaj rightfully pointed out should be Update), you're only calling RotateShip() while Input.GetMouseButton(0) is true. That means that you only rotate your ship while the button is pressed.
What you should do is take that mouse event and use it to set a target, then continuously rotate toward that target. For instance,
void Update() {
if (Input.GetMouseButtonDown (0)) //we only want to begin this process on the initial click, as Imtiaj noted
{
ChangeRotationTarget();
}
Quaternion targetRotation = Quaternion.LookRotation (this.targetPoint - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, speed * Time.deltaTime);
}
void ChangeRotationTarget()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane playerPlane = new Plane (Vector3.up, transform.position);
float hitdist = 0.0f;
if (playerPlane.Raycast (ray, out hitdist))
{
this.targetPoint = ray.GetPoint (hitdist);
}
}
So now instead of only doing the rotation while MouseButton(0) is down, we do the rotation continuously in the update and instead only set the target point when we click the mouse.