Hi everyone,I need to click and drag a game object and when I release the game object it should go back to the original position with a wiggle effect like a bended rubber.
I know how to make the click and drag and bring it back to original state on releasing all I need is to get the wiggle effect due to elasticity and inertia with damping and the wiggle strength should depend on the stretch distance.Can anyone guide me through the scripting of this.
Below is the illustration which shows I want.
Whole new script, simpler but the concept remains.
It is known that elastic forces are of the type F = -k*x. But an ideal elastic force would never stop its movement so I added a perturbation that would slow down speed depending on its value. Right now its working and it´s very fun to see. Enjoy!
using UnityEngine;
using System.Collections;
public class Draggable : MonoBehaviour{
private Vector3 origin;
private float forceConstant = 200;
private bool returning = false;
private float precision = 0.1f;
private void Start(){
origin = transform.position;
}
private void Update(){
if (Input.GetMouseButton(0)){
transform.position = new Vector3(5*Input.mousePosition.x/Screen.width, 5*Input.mousePosition.y/Screen.width, 0);
}
if (Input.GetMouseButtonUp(0)){
returning = true;
rigidbody.constraints = RigidbodyConstraints.None;
}
if (returning){
rigidbody.AddForce (forceConstant*(origin - transform.position));
rigidbody.velocity *= 0.9f;
if (rigidbody.velocity.magnitude < precision &&
Vector3.Distance(transform.position, origin) < precision){
rigidbody.constraints = RigidbodyConstraints.FreezeAll;
returning = false;
}
}
}
}
(Hopefully) Last edit: as you don´t seem to believe me I have uploaded a [18687-draggable.unitypackage.zip|18687] with the script and a scene showing it. Just load, play and click. It works WELL, it only needs to improve the mouse input part, but your question wasn´t about it so I just implemented a fast solution.
Grixen
3
Somehow for me it became a nontrivial task.
Fully functional c# addition with smooth drag. For further users.
private Vector3 origin;
private float forceConstant = 20;
private bool returning = false;
private float precision = 0.1f;
public float speed = 9.0f;
private Vector3 targetPos;
private void Start(){
origin = transform.position;
}
private void Update(){
if (Input.GetMouseButton (0)) {
float distance = transform.position.z - Camera.main.transform.position.z;
targetPos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, distance);
targetPos = Camera.main.ScreenToWorldPoint (targetPos);
transform.position = Vector3.MoveTowards (transform.position, targetPos, speed * Time.deltaTime);
// transform.position = new Vector3 (Input.mousePosition.x / Screen.width, Input.mousePosition.y / Screen.width, 0);
}
if (Input.GetMouseButtonUp(0)){
returning = true;
GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
}
if (returning){
GetComponent<Rigidbody>().AddForce (forceConstant*(origin - transform.position));
GetComponent<Rigidbody>().velocity *= 0.9f;
if (GetComponent<Rigidbody>().velocity.magnitude < precision &&
Vector3.Distance(transform.position, origin) < precision){
GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
returning = false;
}
}
}
}
@sethuraj, the follow code works.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class dragScript : MonoBehaviour {
private Vector3 screenPoint;
private Vector3 offset;
public Transform cube;
public float speed;
Vector3 startPosition;
public bool CUbeReleased;
public Vector3 dir;
public Vector3 curPosition;
public float value = 8.0f;
void Start()
{
startPosition = transform.position;
}
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
void OnMouseDrag()
{
Vector3 curScreenPoint = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
curPosition = Camera.main.ScreenToWorldPoint (curScreenPoint) + offset;
transform.position = curPosition;
}
void OnMouseUp()
{
CUbeReleased = true;
}
void Update() {
if (CUbeReleased == true && Vector3.Distance(this.transform.position,cube.transform.position) > 0.3f) {
dir = cube.transform.position - this.transform.position;
dir.Normalize ();
this.gameObject.GetComponent<Rigidbody> ().AddForce (dir * (Mathf.Sin (dir.sqrMagnitude)*value));
//if (this.gameObject.GetComponent<Rigidbody> ().velocity.magnitude < 1.0f && Vector3.Distance(this.transform.position,cube.transform.position) < 0.2f) {
// value = 0.1f;
//}
Debug.Log (Mathf.Abs(Vector3.Distance(this.transform.position,cube.transform.position)));
}
}
}
Why not use a Tween asset, like DOTween?