We are sure if you follow step by step then you will definitely succeed.
Step 1:Create Unity Blank Project and Design Scene like below image
Step 2:Go to : Edit->Project Settings->Physics and do change like below Image
Step 3: Create Below Object in your Scene
Step 4:Create Ball.cs and add it to BallObject Prefabe
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour
{
#region Private_Variables
// Use this for initialization
private bool isInFloor = false;
private Rigidbody rigid;
private bool isThrowed = false;
private Vector3 initialPosition;
private Quaternion initialRotation;
public Vector3 initialScale;
private IEnumerator jumpCoroutine;
private bool isRotate = false;
private Transform childBall;
private bool isCurve = false;
private float curveFactore = 0f;
private float throwPos = 0f;
private float windFactor = 1f;
private bool isWind = false;
private bool isNormalThrow = false;
private bool isRotateLeft = true;
private bool isParticleFollowBall = false;
public Camera cam;
public float objectScale = 1.0f;
#endregion
#region Public_Variables
#endregion
#region Unity_Callbacks
void Start ()
{
rigid = GetComponent ();
//initalize gradually jump coroutine
jumpCoroutine = GraduallyJumpCoroutine (0.3f);
childBall = transform.FindChild ("Ball");
StartCoroutine (jumpCoroutine);
// record initial scale, use this as a basis
initialScale = transform.localScale;
// if no specific camera, grab the default camera
if (cam == null)
cam = Camera.main;
}
void Update ()
{
if (!isThrowed) {
Plane plane = new Plane (cam.transform.forward, cam.transform.position);
float dist = plane.GetDistanceToPoint (transform.position);
transform.localScale = initialScale * dist * objectScale;
}
if (isRotate) {
if (isRotateLeft)
childBall.Rotate (Vector3.right * Time.deltaTime * 660);
else
childBall.Rotate (-Vector3.right * Time.deltaTime * 660);
}
}
void FixedUpdate ()
{
float dist = 0f;
if (ThrowBall.Instance.target) {
dist = (ThrowBall.Instance.target.position.z - transform.position.z);
}
if (isCurve && dist <= (throwPos - (throwPos / 9.5f))) {
if (!isWind)
StartCoroutine (wind (0.5f));
transform.Translate (Vector3.right * -curveFactore * windFactor * Time.deltaTime);
}
}
void OnEnable ()
{
initialPosition = transform.position;
}
void OnCollisionEnter (Collision colliderInfo)
{
if (isInFloor) {
if (colliderInfo.gameObject.CompareTag ("target")) {
isCurve = false;
}
}
if (!isInFloor) {
if (colliderInfo.gameObject.CompareTag ("floor")) {
isInFloor = true;
StartCoroutine (stop ());
}
if (colliderInfo.gameObject.CompareTag ("target")) {
isInFloor = true;
colliderInfo.gameObject.SetActive (false);
StartCoroutine (GotPokemonCoroutine (colliderInfo.gameObject));
}
}
}
#endregion
#region Private_Methods
private void SetIsThrowed (bool flag)
{
if (jumpCoroutine != null) {
StopCoroutine (jumpCoroutine);
jumpCoroutine = null;
}
isThrowed = flag;
//if object was getting throwing direction then don't rotate
if (ThrowBall.Instance.IsGettingDirection)
isRotate = false;
else
isRotate = true;
throwPos = (ThrowBall.Instance.target.position.z - transform.position.z);
}
public void ResetBall ()
{
isThrowed = false;
StopAllCoroutines ();
//ball move to initial position
StartCoroutine (MoveBackToInitialPositionCoroutine (0.3f));
}
private void SetCurve (float cFactore)
{
curveFactore = cFactore;
isCurve = true;
}
private void SetNormalThrow (float cFactore)
{
curveFactore = cFactore;
isNormalThrow = true;
}
#endregion
#region Public_Methods
#endregion
#region Properties
#endregion
#region Coroutine
IEnumerator GotPokemonCoroutine (GameObject collidedObject)
{
yield return new WaitForSeconds (0.5f);
childBall.gameObject.SetActive (false);
collidedObject.SetActive (true);
Destroy (gameObject);
}
IEnumerator wind (float t)
{
isWind = true;
float rate = 1.0f / t;
float i = 0f;
while (i<1.0f) {
i += rate * Time.deltaTime;
windFactor = Mathf.Lerp (1, 26, i);
yield return 0;
}
}
IEnumerator windReverse (float t)
{
isWind = true;
float rate = 1.0f / t;
float i = 0f;
while (i<1.0f) {
i += rate * Time.deltaTime;
windFactor = Mathf.Lerp (26, 0, i);
//Debug.Log("reverse:"+windFactor);
yield return 0;
}
//isWind=false;
}
IEnumerator stop ()
{
isRotate = false;
yield return new WaitForSeconds (0.5f);
Destroy (gameObject);
}
IEnumerator GraduallyJumpCoroutine (float tm)
{
while (!isThrowed) {
yield return new WaitForSeconds (0.5f);
transform.position = initialPosition;
if (ThrowBall.Instance.IsGameStart) {
isRotateLeft = !isRotateLeft;
isRotate = true;
float i = 0f;
float rate = 1.0f / tm;
Vector3 from = initialPosition;
Vector3 to = new Vector3 (from.x, from.y + 0.3f, from.z);
while (i<1.0f) {
i += rate * Time.deltaTime;
transform.position = Vector3.Lerp (from, to, i);
//transform.localScale = Vector3.Lerp (fromScale, toScale, i);
yield return 0f;
}
i = 0f;
rate = 1.0f / (tm / 0.7f);
Vector3 bump = from;
bump.y -= 0.05f;
while (i<1.0f) {
i += rate * Time.deltaTime;
transform.position = Vector3.Lerp (to, bump, i);
// transform.localScale = Vector3.Lerp (toScale, fromScale, i);
yield return 0f;
}
isRotate = false;
i = 0f;
rate = 1.0f / (tm / 1.1f);
while (i<1.0f) {
i += rate * Time.deltaTime;
transform.position = Vector3.Lerp (bump, from, i);
yield return 0f;
}
}
}
}
IEnumerator MoveBackToInitialPositionCoroutine (float tm)
{
float i = 0f;
float rate = 1.0f / tm;
Vector3 from = transform.position;
Vector3 to = initialPosition;
while (i<1.0f) {
i += rate * Time.deltaTime;
transform.position = Vector3.Lerp (from, to, i);
yield return 0f;
}
transform.position = initialPosition;
childBall.localRotation = Quaternion.identity;
isRotate = false;
//initalize gradually jump coroutine
jumpCoroutine = GraduallyJumpCoroutine (0.3f);
StartCoroutine (jumpCoroutine);
}
#endregion
#region RPC
#endregion
}
Step 5: Create TrowBall.cs and add it to BallThrower gameobject
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ThrowBall : MonoBehaviour
{
#region Private_Variables
private static ThrowBall throwPaperInstance;
private float factor = 230.0f;
private float startTime;
public Vector3 startPos;
private GameObject currentBall;
private bool isGettingDirection = false;
private bool isGameStart = true;
public bool isCurveThrow = false;
private Vector3 lastPos;
private Vector3 lastPokeBallPosition = Vector3.zero;
private bool isStartRoate = false;
List ballPos = new List ();
List ballTime = new List ();
// Use this for initialization
float lastAngel = 0f;
public int angleDirection = 0;
float rotationSpeed = 2f;
float totalX = 0f, totalY = 0f;
int dLeft = 0, dRight = 0;
#endregion
#region Public_Variables
public Vector3 minThrow;
public Vector3 maxThrow;
public GameObject ball;
private Transform currentBallChild;
private float dist;
private Vector3 v3Offset;
private Plane plane;
private bool ObjectMouseDown = false;
public GameObject linkedObject;
public Transform target;
public ParticleSystem curveParticle;
#endregion
#region Unity_Callbacks
void Awake ()
{
throwPaperInstance = this;
}
void Start ()
{
StartCoroutine (GetBallCoroutine ());
}
void Update ()
{
if (currentBall) {
transform.position = currentBall.transform.position;
}
if (currentBall && isGettingDirection) {
//Debug.Log ("M:" + Input.mousePosition);
transform.position = currentBall.transform.position;
float angle = 0f;
if (currentBallChild != null) {
Vector3 mouse_pos = Input.mousePosition;
Vector3 player_pos = Camera.main.WorldToScreenPoint (currentBallChild.localPosition);
mouse_pos.x = mouse_pos.x - player_pos.x;
mouse_pos.y = mouse_pos.y - player_pos.y;
angle = Mathf.Atan2 (mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg;
}
if (Vector3.Distance (currentBall.transform.position, lastPokeBallPosition) > 0f) {
if (!isStartRoate) {
Invoke ("ResetPoint", 0.01f);
} else {
Vector3 dir = (currentBall.transform.position - lastPokeBallPosition);
if (dir.x > dir.y) {
totalX += 0.12f;
} else {
if (dir.x != dir.y) {
totalY += 0.12f;
}
}
if (totalX >= 2 && totalY >= 2) {
isCurveThrow = true;
curveParticle.gameObject.SetActive (true);
if (curveParticle.isStopped) {
curveParticle.Play ();
}
curveParticle.transform.position = currentBall.transform.position;
}
}
isStartRoate = true;
if (angle > 0) {
if (lastAngel >= angle) {
dRight++;
} else {
dLeft++;
}
} else {
if (lastAngel >= angle) {
dRight++;
} else {
dLeft++;
}
}
if (dLeft < dRight) {
angleDirection = 1;
if (currentBallChild != null)
currentBallChild.transform.Rotate (new Vector3 (0, 0, 40f));
} else {
angleDirection = -1;
if (currentBallChild != null)
currentBallChild.transform.Rotate (new Vector3 (0, 0, -40f));
}
} else {
if (isStartRoate == true) {
StartCoroutine (StopRotation (angleDirection, 0.5f));
}
}
lastAngel = angle;
lastPokeBallPosition = currentBall.transform.position;
}
}
private void ResetPoint ()
{
if (!isStartRoate) {
totalX = 0f;
totalY = 0f;
dLeft = 0;
dRight = 0;
isCurveThrow = false;
startPos = currentBall.transform.position;
ballPos.Clear ();
ballTime.Clear ();
ballTime.Add (Time.time);
ballPos.Add (currentBall.transform.position);
curveParticle.Stop ();
curveParticle.gameObject.SetActive (false);
ThrowBall.Instance.isCurveThrow = false;
}
}
IEnumerator rotate (Quaternion from, Quaternion to, float t)
{
float rate = 1.0f / t;
float i = 0f;
while (i<1.0f) {
i += rate * Time.deltaTime;
currentBallChild.localRotation = Quaternion.Lerp (from, to, i);
yield return 0;
}
}
IEnumerator StopRotation (int direction, float t)
{
isStartRoate = false;
float rate = 1.0f / t;
float i = 0f;
while (i<1.0f) {
i += rate * Time.deltaTime;
if (!isStartRoate) {
if (direction == 1) {
if (currentBallChild != null)
currentBallChild.transform.Rotate (new Vector3 (0, 0, 40f) * (Mathf.Lerp (rotationSpeed * totalX, 0, i)) * Time.deltaTime);
} else {
if (currentBallChild != null)
currentBallChild.transform.Rotate (new Vector3 (0, 0, -40f) * (Mathf.Lerp (rotationSpeed * totalX, 0, i)) * Time.deltaTime);
}
}
yield return 0;
}
if (!isStartRoate) {
totalX = 0f;
totalY = 0f;
dLeft = 0;
dRight = 0;
isCurveThrow = false;
rotationSpeed = 100f;
curveParticle.Stop ();
curveParticle.gameObject.SetActive (false);
}
}
void OnMouseDown ()
{
if (currentBall == null)
return;
plane.SetNormalAndPosition (Camera.main.transform.forward, currentBall.transform.position);
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
float dist;
plane.Raycast (ray, out dist);
v3Offset = currentBall.transform.position - ray.GetPoint (dist);
ObjectMouseDown = true;
if (!currentBall || !isGameStart)
return;
ballPos.Clear ();
ballTime.Clear ();
ballTime.Add (Time.time);
ballPos.Add (currentBall.transform.position);
totalX = 0f;
totalY = 0f;
dLeft = 0;
dRight = 0;
isCurveThrow = false;
isGettingDirection = true;
currentBall.SendMessage ("SetIsThrowed", true, SendMessageOptions.RequireReceiver);
currentBallChild = currentBall.transform.FindChild ("Ball");
StartCoroutine (GettingDirection ());
}
IEnumerator GettingDirection ()
{
while (isGettingDirection) {
startTime = Time.time;
lastPos = startPos;
startPos = Camera.main.WorldToScreenPoint (currentBall.transform.position);
startPos.z = currentBall.transform.position.z - Camera.main.transform.position.z;
startPos = Camera.main.ScreenToWorldPoint (startPos);
yield return new WaitForSeconds (0.01f);
}
}
void OnMouseDrag ()
{
if (ObjectMouseDown == true) {
if (!currentBall)
return;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
float dist;
plane.Raycast (ray, out dist);
Vector3 v3Pos = ray.GetPoint (dist);
v3Pos.z = currentBall.transform.position.z;
v3Offset.z = 0;
currentBall.transform.position = v3Pos + v3Offset;
if (ballPos.Count > 0) {
if (ballPos.Count <= 4) {
if (Vector3.Distance (currentBall.transform.position, ballPos [ballPos.Count - 1]) >= 0.01f) {
ballTime.Add (Time.time);
ballPos.Add (currentBall.transform.position);
}
} else {
if (Vector3.Distance (currentBall.transform.position, ballPos [ballPos.Count - 1]) >= 0.01f) {
ballTime.RemoveAt (0);
ballPos.RemoveAt (0);
ballTime.Add (Time.time);
ballPos.Add (currentBall.transform.position);
}
}
} else {
ballPos.Add (currentBall.transform.position);
}
if (linkedObject != null) {
linkedObject.transform.position = v3Pos + v3Offset;
}
}
}
void OnMouseOut ()
{
ObjectMouseDown = false;
}
void OnMouseUp ()
{
curveParticle.Stop ();
curveParticle.gameObject.SetActive (false);
isGettingDirection = false;
if (!currentBall || !isGameStart)
return;
var endPos = Input.mousePosition;
endPos.z = currentBall.transform.position.z - Camera.main.transform.position.z;
endPos = Camera.main.ScreenToWorldPoint (endPos);
int ballPositionIndex = ballPos.Count - 2;
if (ballPositionIndex < 0)
ballPositionIndex = 0;
Vector3 force = currentBall.transform.position - ballPos [ballPositionIndex];
if (Vector3.Distance (lastPos, startPos) <= 0.0f) {
currentBall.SendMessage ("ResetBall", SendMessageOptions.RequireReceiver);
return;
}
//if downside
if (currentBall.transform.position.y <= ballPos [ballPositionIndex].y) {
currentBall.SendMessage ("ResetBall", SendMessageOptions.RequireReceiver);
return;
}
//if not swipe
if (force.magnitude < 0.02f) {
currentBall.SendMessage ("ResetBall", SendMessageOptions.RequireReceiver);
return;
}
force.z = force.magnitude;
force /= (Time.time - ballTime [ballPositionIndex]);
force.y /= 2f;
force.x /= 2f;
force.x = Mathf.Clamp (force.x, minThrow.x, maxThrow.x);
force.y = Mathf.Clamp (force.y, minThrow.y, maxThrow.y);
force.z = Mathf.Clamp (force.z, minThrow.z, maxThrow.z);
//send message ball was thrown
currentBall.SendMessage ("SetIsThrowed", true, SendMessageOptions.RequireReceiver);
if (isCurveThrow) {
force.z -= 0.1f;
if (angleDirection == 1) {
if (force.z < 2.3f)
force.z = 2.3f;
currentBall.SendMessage ("SetCurve", -0.2);
} else {
if (force.z < 2.3f)
force.z = 2.3f;
currentBall.SendMessage ("SetCurve", 0.2);
}
}
//get rigidbody
Rigidbody ballRigidbody = currentBall.GetComponent ();
//enable collider
currentBall.GetComponent ().enabled = true;
ballRigidbody.useGravity = true;
ballRigidbody.AddForce (force * factor);
StartCoroutine (GetBallCoroutine ());
currentBall = null;
}
#endregion
#region Private_Methods
#endregion
#region Public_Methods
public void GetNewBall ()
{
if (currentBall != null)
Destroy (currentBall);
currentBall = Instantiate (ball, ball.transform.position, Quaternion.identity) as GameObject;
//disable collider
currentBall.GetComponent ().enabled = false;
}
#endregion
#region Properties
///
/// Gets the instance.
///
/// The instance.
public static ThrowBall Instance {
get {
return throwPaperInstance;
}
}
///
/// Gets or sets a value indicating whether this instance is getting direction.
///
/// true if this instance is getting direction; otherwise, false.
public bool IsGettingDirection {
get {
return isGettingDirection;
}set {
isGettingDirection = value;
}
}
///
/// Gets or sets a value indicating whether this instance is game start.
///
/// true if this instance is game start; otherwise, false.
public bool IsGameStart {
get {
return isGameStart;
}set {
isGameStart = value;
}
}
#endregion
#region Coroutine
IEnumerator GetBallCoroutine ()
{
yield return new WaitForSeconds (2.0f);
if (currentBall != null)
Destroy (currentBall);
currentBall = Instantiate (ball, ball.transform.position, Quaternion.identity) as GameObject;
//disable collider
currentBall.GetComponent ().enabled = false;
}
#endregion
#region RPC
#endregion
}