How to Drag and throw object forcefully in Unity2D - unity3d

I'm new in Unity 2D i want to drag & throw my game object forcefully. basically i have three game object and when i drag anyone off then to upward i should be throw forcefully on that direction.
can anyone tell me how to do it?
i have tried this code but when i'm going to click to drag my game object then it throws directly without dragging it.
here is my code
private Rigidbody2D rb;
private float jumpForce = 700f;
private bool jumpAllowed = false;
float deltaX, deltaY;
string button_name = "";
// Use this for initialization
private void Start ()
{
Debug.Log("Started");
rb = GetComponent<Rigidbody2D> ();
PhysicsMaterial2D mat = new PhysicsMaterial2D();
mat.bounciness = 0.75f;
mat.friction = 0.4f;
GetComponent<CircleCollider2D>().sharedMaterial = mat;
}
// Update is called once per frame
private void Update ()
{
Debug.Log("Update");
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
switch (touch.phase)
{
case TouchPhase.Began:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
{
deltaX = touchPos.x - transform.position.x;
deltaY = touchPos.y - transform.position.y;
jumpAllowed = true;
rb.freezeRotation = true;
rb.velocity = new Vector2(0, 0);
rb.gravityScale = 0;
GetComponent<Collider2D>().sharedMaterial = null;
}
break;
case TouchPhase.Moved:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos) && jumpAllowed)
{
rb.MovePosition(new Vector2(touchPos.x - deltaX, touchPos.y - deltaY));
}
break;
case TouchPhase.Ended:
jumpAllowed = false;
rb.freezeRotation = false;
rb.gravityScale = 2;
PhysicsMaterial2D mat = new PhysicsMaterial2D();
mat.bounciness = 0.75f;
mat.friction = 0.4f;
GetComponent<CircleCollider2D>().sharedMaterial = mat;
break;
}
}
}

First, there's one mistake
rb.MovePosition(new Vector2(touchPos.x - deltaX, touchPos.y - deltaY));
should be
rb.MovePosition(new Vector2(touchPos.x + deltaX, touchPos.y + deltaY));
There's also another issue, MovePosition doesn't affect the object velocity at all. If you stop using MovePosition, the object will just fall without keeping any energy from the previous movement.
You could simply store the previous position every movement, and do this on TouchPhase.Ended:
rb.velocity = (rb.position - prevPosition) / Time.deltaTime;
Simply put, this calculates the velocity that was required to accomplish the last movement, and apply it to the rigidbody.

Related

How to identify which object is going to be swipe in multiple objects in unity

I need some help to swipe object or we can say move object on which i have touched.
I have created code in which i'm able to drag only one button.
Suppose i touched on first button it should be active for swipe.
Here is my screen show.
I want to create code for every button for dragging that button on Swipe.
Here is my buttons
using UnityEngine;
public class SwipeJump : MonoBehaviour
{
private Vector2 startTouchPosition, endTouchPosition;
private Rigidbody2D rb;
private float jumpForce = 700f;
private bool jumpAllowed = false;
float deltaX, deltaY;
// Use this for initialization
private void Start ()
{
rb = GetComponent<Rigidbody2D> ();
#region newcode
PhysicsMaterial2D mat = new PhysicsMaterial2D();
//mat.bounciness = 0.75f;
//mat.friction = 0.4f;
GetComponent<CircleCollider2D>().sharedMaterial = mat;
#endregion
}
// Update is called once per frame
private void Update ()
{
//SwipeCheck ();
#region newcode
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
switch (touch.phase)
{
case TouchPhase.Began:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
{
deltaX = touchPos.x - transform.position.x;
deltaY = touchPos.y - transform.position.y;
jumpAllowed = true;
rb.freezeRotation = true;
rb.velocity = new Vector2(0, 0);
rb.gravityScale = 0;
GetComponent<Collider2D>().sharedMaterial = null;
}
break;
case TouchPhase.Moved:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos) && jumpAllowed)
{
rb.MovePosition(new Vector2(touchPos.x - deltaX, touchPos.y - deltaY));
}
break;
case TouchPhase.Ended:
jumpAllowed = false;
rb.freezeRotation = false;
rb.gravityScale = 2;
PhysicsMaterial2D mat = new PhysicsMaterial2D();
//mat.bounciness = 0.75f;
//mat.friction = 0.4f;
GetComponent<CircleCollider2D>().sharedMaterial = mat;
break;
}
}
#endregion
}
}

Frame-rate independent pushForce?

I'm working with a CharacterController and added the ability to push Rigidbodies. The problem is however that the pushing is frame-rate dependent. How would I be able to make it frame-rate independent? I have tried adding Time.deltatime, but this makes pushing not possible, I might be adding it wrong though.
Here's the code that adds force to rigidbodies;
void OnControllerColliderHit(ControllerColliderHit hit)
{
Rigidbody body = hit.collider.attachedRigidbody;
if (body == null || body.isKinematic)
return;
if (hit.moveDirection.y < -.3f)
return;
Vector3 pushDirection = new Vector3(hit.moveDirection.x, 0, hit.moveDirection.z);
body.velocity = pushForce * pushDirection;
}
As far as I know it has something to do with the last 2 lines of code.
Edit(The code for pushing):
public void PushStates() {
// Creating the raycast origin Vector3's
Vector3 forward = transform.TransformDirection(Vector3.forward) * distanceForPush;
Vector3 middle = controller.transform.position - new Vector3(0, -controller.height / 2, 0);
// Inspector bool
if (pushRay)
{
Debug.DrawRay(middle, forward, Color.cyan);
}
// Force the pushForce and movementSpeed to normal when the player is not pushing
pushForce = 0f;
movementSpeed = walkSpeed;
// Draws a raycast in front of the player to check if the object in front of the player is a pushable object
if (Physics.Raycast(middle, forward, out hit, distanceForPush))
{
if (InputManager.BButton() && playerIsInPushingTrigger)
{
PushableInfo();
playerIsPushing = true;
anim.SetBool("isPushing", true);
if (hit.collider.tag == "PushableLight")
{
pushForce = playerPushForceLight;
movementSpeed = pushSpeedLight;
}
else if (hit.collider.tag == "PushableHeavy")
{
pushForce = playerPushForceHeavy;
movementSpeed = pushSpeedHeavy;
}
// Checks the players speed now instead off movement. This is neccesary when the player is pushing a pushable into a collider.
// The player and pushable never stop moving because of force.
if (currentSpeed < 0.15f)
{
//Removes all remaining velocity, when the player stops pushing
pushableObjectRB.velocity = Vector3.zero;
pushableObjectRB.angularVelocity = Vector3.zero;
anim.SetFloat("pushSpeedAnim", 0f);
}
else
{
// Calls a rotation method
PushingRot();
if (hit.collider.tag == "PushableLight")
{
anim.SetFloat("pushSpeedAnim", pushSpeedAnimLight);
}
else if (hit.collider.tag == "PushableHeavy")
{
anim.SetFloat("pushSpeedAnim", pushSpeedAnimHeavy);
}
}
}
else
{
anim.SetBool("isPushing", false);
pushForce = 0f;
movementSpeed = walkSpeed;
playerIsPushing = false;
}
}
else
{
anim.SetBool("isPushing", false);
playerIsPushing = false;
}
// Setting the time it takes to rotate when pushing
AnimatorStateInfo stateInfo = anim.GetCurrentAnimatorStateInfo(0);
if (stateInfo.fullPathHash == pushStateHash)
{
turnSmoothTime = maxTurnSmoothTimePushing;
}
else
{
turnSmoothTime = 0.1f;
}
}
You were right, you need to multiply by Time.deltaTime which is the time elapsed since last rendered frame.
As this number is really small (has you have 60+ fps) you'll also need to increase the value (multiply it by 100, 1000...)

How to convert keyboard controls to touch screen in Unity

Complete newbie here. Using Unity C#. I'm looking at moving my PONG game from keyboard control to touch screen. Here is my working keyboard code:
// Player 1 => Controls left bat with W/S keys
public GameObject leftBat;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//Defualt speed of the bat to zero on every frame
leftBat.GetComponent<Rigidbody>().velocity = new Vector3(0f, 0f, 0f);
//If the player is pressing the W key...
if (Input.GetKey (KeyCode.W)) {
//Set the velocity to go up 1
leftBat.GetComponent<Rigidbody>().velocity = new Vector3(0f, 8f, 0f);
}
//If the player is pressing the S key...
else if (Input.GetKey (KeyCode.S)) {
//Set the velocity to go down 1 (up -1)
leftBat.GetComponent<Rigidbody>().velocity = new Vector3(0f, -8f, 0f);
}
}
I found this code and been playing around with it but to now avail.
using UnityEngine;
using System.Collections;
public class Player_Input_Controller : MonoBehaviour {
public GameObject leftBat;
public float paddleSpeed = 1f;
public float yU;
public float yD;
private Ray ray;
private RaycastHit rayCastHit;
private Vector3 playerPos = new Vector3(0, -9.5f, 0);
// Update is called once per frame
void Update () {
if (Input.GetMouseButton (0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out rayCastHit)){
Vector3 position = rayCastHit.point;
float yPos = position.y;
playerPos = new Vector3(Mathf.Clamp(yPos, yU, yD), -9.5f, 0f);
transform.position = playerPos;
}
}
}
}
Any one have a touchscreen Pong script I could use, or know how to edit this one?
Again, I'm really new and I'm sorry if I look like the Dummy in the class.
Thanks for any help provided. I REALLY appreciate it. This is the last hurdle in completing my game.
In my opinion, you do not need any raycasting. Because you are working in 2D and you are only concerned about the y value of Input.mousePosition. Therefore, you can calculate the extent of your screen using your camera's z value. If your camera is at (0, 0, -10) lets say your extents in the game will be -5 - BatOffset to 5+BatOffset in your world coordinates. Therefore, you somehow need a function to map Screen.height to your world coordinate extents as you can see from the image.
In conclusion you need to find Input.mousePosition.y divide it to Screen.height. This will give you the ratio where you touch or click. Then find the position in world space.
Note that: you can also use Input.touchPosition.y. Following script will work for you to do this operation:
public GameObject cam;
private Vector3 batPos;
private float minY;
private float maxY;
private int Res;
private float deltaY;
void Start () {
minY = cam.transform.position.z / 2 - gameObject.transform.localScale.y;
maxY = (-cam.transform.position.z / 2) + gameObject.transform.localScale.y;
deltaY = maxY - minY;
Debug.Log(minY + " " + maxY + " " + deltaY);
Res = Screen.height;
batPos = gameObject.transform.position;
}
void Update () {
if(Input.GetMouseButtonDown(0))
{
// we find the height we have to go up from minY
batPos.y =minY + Input.mousePosition.y / Res * deltaY;
gameObject.transform.position = batPos;
}
}
This works for me in the editor when you click on screen with mouse. You just have to change the parts Input.GetMouseButtonDown to Touch commands such as Touch.tapCount > 0. Also this script should be attached to the bat. Good luck!
Also You can use Orthographic camera and Orthographic camera size instead of cam.transformation.z
May be helpfull
create script. for example player.cs
public class PlayerController : MonoBehaviour
{
bool swipeRight = false;
bool swipeLeft = false;
bool touchBlock = true;
bool canTouchRight = true;
bool canTouchLeft = true;
void Update()
{
swipeLeft = Input.GetKeyDown("a") || Input.GetKeyDown(KeyCode.LeftArrow);
swipeRight = Input.GetKeyDown("d") || Input.GetKeyDown(KeyCode.RightArrow);
TouchControl();
if(swipeRight) //rightMove logic
else if(swipeLeft) //leftMove logic
}
void TouchControl()
{
if(Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began )
{
//Jump logic
}
else if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved && touchBlock == true)
{
touchBlock = false;
// Get movement of the finger since last frame
var touchDeltaPosition = Input.GetTouch(0).deltaPosition;
Debug.Log("touchDeltaPosition "+touchDeltaPosition);
if(touchDeltaPosition.x > 0 && canTouchRight == true)
{
//rightMove
swipeRight = true; canTouchRight = false;
Invoke("DisableSwipeRight",0.2f);
}
else if(touchDeltaPosition.x < 0 && canTouchLeft == true)
{
//leftMove
swipeLeft = true; canTouchLeft = false;
Invoke("DisableSwipeLeft",0.2f);
}
}
}
void DisableSwipeLeft()
{
swipeLeft = false;
touchBlock = true;
canTouchLeft = true;
}
void DisableSwipeRight()
{
swipeRight = false;
touchBlock = true;
canTouchRight = true;
}
}

Unity: How to limit the zooming out of the camera

Using Unity 2018.3
This camera script allows the user to zoom in and out and move the camera with touch around.
On Start() the script takes the cameras current position and saves it as the out of bounds limit. So if the player is zoomed in and moves the camera to the side, the camera will stop when it reaches the bounds limit.
My problem is that currently the user can zoom out all they want, causing the camera to get shaky as the script is trying to relocate the camera but it doesn't stop the user from increasing the orthographicSize.
How do I limit the user from zooming out passed the out of bound limit it got on Start()?
public class ControlCamera : MonoBehaviour
{
private Vector2?[] oldTouchPositions = {
null,
null
};
private Vector2 oldTouchVector;
private float oldTouchDistance;
private Vector3 bottomLeft;
private Vector3 topRight;
private float cameraMaxY;
private float cameraMinY;
private float cameraMaxX;
private float cameraMinX;
public float maxZoom;
public float minZoom;
private void Start()
{
// Set max camera bounds
topRight = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight, -transform.position.z));
bottomLeft = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(0, 0, -transform.position.z));
cameraMaxX = topRight.x;
cameraMaxY = topRight.y;
cameraMinX = bottomLeft.x;
cameraMinY = bottomLeft.y;
}
private void Update()
{
// No touches
if (Input.touchCount == 0)
{
oldTouchPositions[0] = null;
oldTouchPositions[1] = null;
}
// 1 Touch
else if (Input.touchCount == 1)
{
if (oldTouchPositions[0] == null || oldTouchPositions[1] != null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = null;
}
else
{
Vector2 newTouchPosition = Input.GetTouch(0).position;
transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] - newTouchPosition) * GetComponent<Camera>().orthographicSize / GetComponent<Camera>().pixelHeight * 2f));
oldTouchPositions[0] = newTouchPosition;
}
// 2 touches or more
} else {
if (oldTouchPositions[1] == null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = Input.GetTouch(1).position;
oldTouchVector = (Vector2)(oldTouchPositions[0] - oldTouchPositions[1]);
oldTouchDistance = oldTouchVector.magnitude;
} else {
Vector2 screen = new Vector2(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight);
Vector2[] newTouchPositions = {
Input.GetTouch(0).position,
Input.GetTouch(1).position
};
Vector2 newTouchVector = newTouchPositions[0] - newTouchPositions[1];
float newTouchDistance = newTouchVector.magnitude;
transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] + oldTouchPositions[1] - screen) * GetComponent<Camera>().orthographicSize / screen.y));
GetComponent<Camera>().orthographicSize *= oldTouchDistance / newTouchDistance;
transform.position -= transform.TransformDirection((newTouchPositions[0] + newTouchPositions[1] - screen) * GetComponent<Camera>().orthographicSize / screen.y);
oldTouchPositions[0] = newTouchPositions[0];
oldTouchPositions[1] = newTouchPositions[1];
oldTouchVector = newTouchVector;
oldTouchDistance = newTouchDistance;
// --------------------------------------------------------------->>
// Control Zoom In
if (GetComponent<Camera>().orthographicSize > minZoom)
{
//
}
// Control Zoom Out
if (GetComponent<Camera>().orthographicSize < maxZoom)
{
//
}
// --------------------------------------------------------------->>
}
}
// Check if camera is out-of-bounds, if so, move back in-bounds
topRight = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight, -transform.position.z));
bottomLeft = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(0, 0, -transform.position.z));
if (topRight.x > cameraMaxX)
{
transform.position = new Vector3(transform.position.x - (topRight.x - cameraMaxX), transform.position.y, transform.position.z);
}
if (topRight.y > cameraMaxY)
{
transform.position = new Vector3(transform.position.x, transform.position.y - (topRight.y - cameraMaxY), transform.position.z);
}
if (bottomLeft.x < cameraMinX)
{
transform.position = new Vector3(transform.position.x + (cameraMinX - bottomLeft.x), transform.position.y, transform.position.z);
}
if (bottomLeft.y < cameraMinY)
{
transform.position = new Vector3(transform.position.x, transform.position.y + (cameraMinY - bottomLeft.y), transform.position.z);
}
}
}
You should not use GetComponent repeatedly especially not in Update or any repeatedly called method as this creates a lot unnecessary overhead. Instead get it once
private Camera camera;
private void Awake()
{
camera = GetComponent<Camera>();
}
and reuse that reference -> Everywhere replace GetComponent<Camera>() width camera
If my understanding is correct, orthographicSize is half of the height of the camera in world units.
Since you already get topRight and bottomLeft in world coordinates you should be able to calculate an orthographicSize
maxZoom = (CameraMaxY - CameraMinY) / 2.0f;
however, if anyway you want the original zoom to be the max zoom you could also simply store the original zoom like
maxZoom = camera.orthographicSize;
And later you can simply clamp the value like
camera.orthographicSize = Mathf.Clamp(
camera.orthographicSize * oldTouchDistance / newTouchDistance,
minZoom,
maxZoom);
-> no need for extra if checks

unity | Create and destroy Jostick dynamically with touch

I want to make a jostick that created (Instatiated or whatever) in touch position(Input.getTouch(i).position) and destroyed when user doesn't touch the screen anymore. This is the source code below. Please give me an idea how to do it. Thank you.
using UnityEngine;
using System.Collections;
public class joy : MonoBehaviour
{
public GameObject joystick; //Self explanitory
public GameObject bg; //Background object for the joystick boundaries
public const float deadzone = 0f; //Deadzone for the joystick
public const float radius = 2.0f; //The radius that the joystick thumb is allowed to move from its origin
public Camera cam;
protected Collider joyCol;
protected int lastfingerid = -1; //Used for latching onto the finger
public Vector2 position = Vector2.zero;
void Awake ()
{
joyCol = bg.GetComponent<Collider>();
}
public void Disable ()
{
gameObject.active = false; //Turns off the joystick when called
}
public void ResetJoystick () //Called when the joystick should be moved back to it's original position (relative to parent object)
{
lastfingerid = -1;
joystick.transform.localPosition = Vector3.zero;
}
void Update ()
{
if (Input.touchCount == 0)
{
ResetJoystick (); //I would have figured this would be obvious? :P
}
else
{
for (int i=0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);
bool latchFinger = false;
if (touch.phase == TouchPhase.Began) //When you begin the touch, the code here gets called once
{
//Vector3 touchpos = Input.GetTouch(i).position;
//touchpos.z = 0.0f;
//Vector3 createpos = cam.ScreenToWorldPoint(touchpos);
Ray ray = cam.ScreenPointToRay (touch.position); //Creates a ray at the touch spot
RaycastHit hit; //Used for determining if something was hit
//joystick = (GameObject)Instantiate(Resources.Load("Type3/joystick"),createpos, Quaternion.identity);
//bg = (GameObject)Instantiate(Resources.Load("Type3/Bg"),createpos, Quaternion.identity);
if (joyCol.Raycast(ray,out hit,Mathf.Infinity)) //The ray hit something...
{
if (hit.collider == joyCol) //Apparently, that ray hit your joystick
{
latchFinger = true; //This turns on and sets off a chain reaction
}
}
}
if (latchFinger ) //Latch finger being true turns this code on
{
if ((lastfingerid == -1 || lastfingerid != touch.fingerId))
{
lastfingerid = touch.fingerId;
}
}
if (lastfingerid == touch.fingerId) //The real meat of the code
{
Vector3 sTW = cam.ScreenToWorldPoint (new Vector3 (touch.position.x, touch.position.y, 1)); //Transforms the screen touch coordinates into world coordinates to move our joystick
joystick.transform.position = sTW; //Hurr :O
joystick.transform.localPosition = new Vector3(joystick.transform.localPosition.x,joystick.transform.localPosition.y,0);
//float xClamp = Mathf.Clamp (joystick.transform.localPosition.x, xClampMin, xClampMax); //Limit movement to the boundaries
//float yClamp = Mathf.Clamp (joystick.transform.localPosition.y, yClampMin, yClampMax);
/*float distFromCenter = Mathf.Sqrt(joystick.transform.localPosition.x*joystick.transform.localPosition.x + joystick.transform.localPosition.y*joystick.transform.transform.localPosition.y);
float actualPercent = Mathf.Clamp01(distFromCenter/radius);
float percent = Mathf.Clamp01((distFromCenter - deadzone)/(radius - deadzone));
*/
joystick.transform.localPosition = Vector3.ClampMagnitude(joystick.transform.localPosition,radius);
//joystick.transform.localPosition = new Vector3 (xClamp, yClamp, joystick.transform.localPosition.z); //Finally, the joystick moves like it should with everything in place
if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
{
ResetJoystick ();
}
}
Ray touchray = cam.ScreenPointToRay (touch.position); //Creates a ray at the touch spot
//RaycastHit hit; //Used for determining if something was hit
Debug.DrawRay (touchray.origin, touchray.direction * 100, Color.yellow); //Delete this line. It's not important.
}
}
//set our position variables x and y values to the joysticks values but clamped to a percent value instead of world coords
position.x = joystick.transform.localPosition.x/radius;
position.y = joystick.transform.localPosition.y/radius;
if(position.magnitude < deadzone)
{
position.x = 0;
position.y = 0;
}
}
}