How to use OnMouseUp in Unity? - unity3d

I have drag and shoot script in my unity game(like in angry birds).It works correctly if I quickly release the mouse button, but when I hold it for a long time and then release , the object falls to the cursor level and its velocity(which is calculated by object.position - dragStartPosition) become too much.What's wrong with it?
I have these methods:
private Vector3 startPositionOnDrag;
public float throwForce;
private Vector2 initVelocity;
public bool isMoving = false;
public Rigidbody2D rigidbody;
private void OnMouseDown()
{
startPositionOnDrag = new Vector3(transform.position.x, transform.position.y, 0);
}
private void OnMouseDrag()
{
if (!isMoving)
{
Vector3 mousePosVector = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 diff = startPositionOnDrag - mousePosVector;
if (diff.magnitude < 1.5f)
{
transform.position = new Vector3(mousePosVector.x, mousePosVector.y, 0);
}
else
{
float diffLength = diff.magnitude;
Vector3 targetPosition = startPositionOnDrag - ((startPositionOnDrag - mousePosVector) * 1.5f/diffLength);
transform.position = new Vector2(targetPosition.x, targetPosition.y);
}
}
}
private void OnMouseUp()
{
if (!isMoving)
{
Vector2 diff = startPositionOnDrag - transform.position; //smthg wrong in magnitude
Vector2 directionToMove = (startPositionOnDrag - transform.position).normalized; //correct
initVelocity = directionToMove * throwForce * Mathf.Sqrt(diff.magnitude);
rigidbody.velocity = initVelocity;
isMoving = true;
}
}

Related

How to move object with mouse with similar code like this touch script?

I have this code for android touch input and want exact code and functionality with mouse pointer movement with persepective camera
public class InputManager : MonoBehaviour
{
private Touch touch;
private float speedModifier;
private void Start()
{
speedModifier = 0.01f;
}
private void Update()
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
transform.position = new Vector3(
transform.position.x + touch.deltaPosition.x * speedModifier,
transform.position.y + touch.deltaPosition.y * speedModifier,
transform.position.z);
}
}
}
}
You can use
private Vector2 lastMousePosition;
private void OnMouseDown()
{
lastMousePosition = Input.mousePosition;
}
private void OnMouseDrag()
{
var deltaMousePosition = Input.mousePosition - lastMousePosition;
transform.position += deltaMousePosition * modifier;
lastMousePosition = Input.MousePosition;
}
Note though: This is fully depending on your display resolution as you directly apply the pixel space delta.
You might want to rather use a slightly different approach and use a mathematical plane and raycast to rather directly move in world space.
Something like e.g. this should do it
private Vector3 dragOffset;
private Plane dragPlane;
private Camera camera;
private void Awake ()
{
camera = Camera.main;
}
private void OnMouseDown()
{
var ray = camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out var hit) && hit.transform == transform)
{
dragOffset = hit.point - transform.position;
dragPlane = new Plane(-camera.forward, hit.point);
}
}
private void OnMouseDrag()
{
var ray = camera.ScreenPointToRay(Input.mousePosition);
if(dragPlane.Raycast(ray, out var distance))
{
transform.position = ray.GetPoint(distance) + dragOffset;
}
}

Jump like teleporting

I'm working on unity and am trying to give my player character a jump button however when he jump he teleport up not jumping
private float speed = 10f;
private bool canjump = false;
private Rigidbody rb;
private float jump =100f;
private float movementX;
private float movementy;
public bool isJumping;
private float jumpdecay =20f;
public float fallmultipler = 2.5f;
public float lowjumpmultiplier = 2f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get();
movementX = movementVector.x;
}
private void Update()
{
Vector3 movement = new Vector2(movementX, 0);
rb.velocity = movement * speed;
if (Input.GetKeyDown(KeyCode.Space))
{
canjump = true;
}
}
void OnTriggerEnter(Collider collision)
{
if(collision.gameObject.tag == "ground")
{
isJumping = false;
}
}
void OnTriggerExit(Collider collision)
{
isJumping = true;
}
private void FixedUpdate()
{
if (canjump & isJumping == false)
{
rb.velocity = Vector3.up * jump;
canjump = false;
}
}
It's happen because on Update you change your velocity including the y and then every frame your y axis of the velocity vector become 0.
to fix that you should save your y and replace after modify your velocity.
change inside your code in the update method this:
Vector3 movement = new Vector2(movementX, 0);
rb.velocity = movement * speed;
with this:
Vector3 movement = new Vector2(movementX, 0);
float currentVelocity = rb.velocity.y;
rb.velocity = movement * speed;
rb.velocity = new Vector3(rb.velocity.x, currentVelocity, rb.velocity.z);
if it's help you, please mark this answer as the good answer, if not please let me know and I will help you.
You are reseting the y velocity inside of update
Vector3 movement = new Vector2(movementX, 0);
rb.velocity = movement * speed;
Try someting like
rb.velocity = new Vector2(movementX * speed, rb.velocity.y)
rb.velocity.y returns current y velocity, because of that said velocity remains unchanged, allowing for the jump to work normally

How do I fix "error CS1955: Non-invocable member 'Vector2' cannot be used like a method." error in unity

This is my code the part below that has "
transform.localScale = Vector2.one;" and everything below is might have the problem so if you could help I would appreciate it.
{
[SerializeField] private float speed;
private Rigidbody2D body;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
body.velocity = new Vector2(Input.GetAxis("Horizontal") * speed, body.velocity.y);
//flip player when moving left-right
if (horizontalInput > 0.01f)
transform.localScale = Vector2.one;
else if (horizontalInput > -0.01f)
transform.localScale = Vector2(-1, 1, 1);
if (Input.GetKey(KeyCode.Space))
body.velocity = new Vector2(body.velocity.x, speed);
}
}

How to select an object to be picked up whenever the camera is pointed to that object?

I'm trying to pick up objects in unity. I have a gameObject called LookObject. Whenever the camera points to an object, the name of that object will be stored in LookObject, then when I press Space the object gets picked up. it is working but not completely. The issue I'm facing is that when I look at an object then look at another direction, the lookObject still shows the name of the object I was looking at (it doesn't update).
please see this image:
as shown in the image, the reticle is not pointing to the object. but it is still showing Cube as the Look Object.
Here is PlayerInteractions class:
GameObject[] targetObjects;
List<GameObject> targetObjectsList;
[Header("InteractableInfo")]
public float sphereCastRadius = 0.5f;
public int interactableLayerIndex;
private Vector3 raycastPos;
public GameObject lookObject;
private PhysicsObjects physicsObject;
private Camera mainCamera;
public GameObject winUI;
private InteractiveObjects interactiveObjects;
[Header("Pickup")]
[SerializeField] private Transform pickupParent;
public GameObject currentlyPickedUpObject;
private Rigidbody pickupRB;
[Header("ObjectFollow")]
[SerializeField] private float minSpeed = 0;
[SerializeField] private float maxSpeed = 300f;
[SerializeField] private float maxDistance = 8f;
private float currentSpeed = 0f;
private float currentDist = 0f;
[Header("Rotation")]
public float rotationSpeed = 100f;
// Quaternion lookRot;
[SerializeField] GameObject TargetsCanvas;
static bool strikeThrough = false;
private void Start()
{
mainCamera = Camera.main;
targetObjects = GameObject.FindGameObjectsWithTag("TargetObj");
targetObjectsList = new List<GameObject>();
foreach (var obj in targetObjects)
{
var mytext = CreateText(TargetsCanvas.transform);
mytext.text = "• Find The " + obj.name;
Debug.Log(""+ obj.name);
}
}
//A simple visualization of the point we're following in the scene view
private void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.DrawSphere(pickupParent.position, 0.5f);
}
void Update()
{
//Here we check if we're currently looking at an interactable object
raycastPos = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
{
lookObject = hit.collider.transform.gameObject;
}
//if we press the button of choice
if (Input.GetKeyDown(KeyCode.Space))
{
//and we're not holding anything
if (currentlyPickedUpObject == null)
{
//and we are looking an interactable object
if (lookObject != null )
{
PickUpObject();
if (!targetObjectsList.Contains(lookObject.gameObject))
{
targetObjectsList.Add(lookObject.gameObject);
if (targetObjectsList.Count == targetObjects.Length)
{
// Time.timeScale = 0f;
// winUI.SetActive(true);
// SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
// Time.timeScale = 1f;
}
}
}
}
//if we press the pickup button and have something, we drop it
else
{
BreakConnection();
}
}
}
private void FixedUpdate()
{
if (currentlyPickedUpObject != null)
{
currentDist = Vector3.Distance(pickupParent.position, pickupRB.position);
currentSpeed = Mathf.SmoothStep(minSpeed, maxSpeed, currentDist / maxDistance);
currentSpeed *= Time.fixedDeltaTime;
Vector3 direction = pickupParent.position - pickupRB.position;
pickupRB.velocity = direction.normalized * currentSpeed;
//Rotation//
// lookRot = Quaternion.LookRotation(mainCamera.transform.position - pickupRB.position);
// lookRot = Quaternion.Slerp(mainCamera.transform.rotation, lookRot, rotationSpeed * Time.fixedDeltaTime);
// pickupRB.MoveRotation(lookRot);
}
}
//Release the object
public void BreakConnection()
{
pickupRB.constraints = RigidbodyConstraints.None;
currentlyPickedUpObject = null;
lookObject = null;
physicsObject.pickedUp = false;
currentDist = 0;
}
public void PickUpObject()
{
physicsObject = lookObject.GetComponentInChildren<PhysicsObjects>();
currentlyPickedUpObject = lookObject;
pickupRB = currentlyPickedUpObject.GetComponent<Rigidbody>();
pickupRB.constraints = RigidbodyConstraints.FreezeRotation;
physicsObject.playerInteractions = this;
}
Here is the code attached to objects:
public float waitOnPickup = 0.2f;
public float breakForce = 35f;
[HideInInspector] public bool pickedUp = false;
[HideInInspector] public PlayerInteractions playerInteractions;
private void OnCollisionEnter(Collision collision)
{
if (pickedUp)
{
if (collision.relativeVelocity.magnitude > breakForce)
{
playerInteractions.BreakConnection();
}
}
}
//this is used to prevent the connection from breaking when you just picked up the object as it sometimes fires a collision with the ground or whatever it is touching
public IEnumerator PickUp()
{
yield return new WaitForSecondsRealtime(waitOnPickup);
pickedUp = true;
}
Here is an image of the object inspector:
how can I make it accurately showing the objects I'm looking at?
A simple fix for this would be to set lookObject to null if the SphereCast returns false since that would indicate you are no longer looking at a valid object. Simply adding else lookObject = null; to the end of the first if statement in your Update() method should do the trick.

How do I move a GameObject at the same speed as onMouseDrag?

I am trying click on a GameObject and move it at the same rate as the mouse. I am able to get the Object to move, but I have to do some crazy modifications in order for it to not vanish off the screen.
Note: My ultimate goal will be to do this for mobile, but am starting with the mouse.
public class ItemController : MonoBehaviour {
private Vector3 startPos;
private bool ObjectMouseDown = false;
void Update()
{
Debug.Log(Input.mousePosition + new Vector3(0,0,15));
}
void OnMouseDown()
{
startPos = transform.position;
ObjectMouseDown = true;
}
void OnMouseDrag()
{
if (ObjectMouseDown == true)
{
transform.position = Vector3.MoveTowards(transform.position, Input.mousePosition + new Vector3(0, 0, 5), Time.deltaTime * 2f);
// transform.position = Vector3.MoveTowards(transform.position, endPosition, speed * Time.deltaTime);
}
}
void OnMouseUp()
{
ObjectMouseDown = false;
}
}
Notice how I have to add a z-value of 15, so that the object doesn't float up out of the screen.
Any help would be awesome.
Input.mousePosition return the absolute pixel position on the screen and not world position. You need to use Camera.ScreenToWorldPoint something like this
Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.position.x, Input.position.y, 15);
transform.position = mouseWorldPos;
You can read more here https://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html