How to Implement Slingshot In Unity

How to Implement Slingshot In Unity

A slingshot is normally a small hand-powered projectile weapon. The classic form consists of a Y-shaped frame held in the off hand, with two natural-rubber strips attached to the uprights. In this tutorial, we will see how to make a slingshot in Unity.

Prerequisites:

1

Unity 5 or higher.

2

In this tutorial, we will use Unity 5.6.3.

This tutorial covers following topics:

1

Slingshot setup

2

Shoot ball

#1

Slingshot setup

The first step is to set the camera projection to orthographic and its positions to (0 f,1f,-10f).

To make a slingshot in Unity, first, we need to make its two rubber strips that hold the ball.We will make these strips using Line Renderer in Unity. The Line Renderer is a component in Unity that takes an array of two or more points in 3D space and draws a straight line between each one.

Create an empty gameobject and name it “Left Line”. Add Line Renderer component to it from AddComponent -> Effects -> Line Renderer. Create anther empty gameobject and name it “Right Line” and add Line Renderer to it. Now you can see pink color lines in your Game view.

As a slingshot requires to drag a ball or any object from its drag point to throw, we need to create a drag point from where we can drag a ball to throw. Create an empty gameobject and name it “ObjectHolder”. Add a BoxColloder to it.To make this dragPoint dragable we need to write some code. Create a new script and name it “DragObject” and add the following lines of code in it :

using System.Collections;

using System.Collections.Generic;

using UnityEngine;



public class DragObject : MonoBehaviour {

Vector3 screenPoint;

Vector3 offset;

Vector3 scanPos;



Transform trans;



void Start()

{
trans = this.transform;

scanPos = trans.position;

}
void Update()

{

}
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(scanPos);



offset = scanPos - 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);

Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;

trans.position = curPosition;

float posX = Mathf.Clamp (trans.position.x,-1.4f,1.4f);

float posY = Mathf.Clamp (trans.position.y,-3f,-2.36f);

		

trans.position = new Vector3 (posX,posY,curPosition.z);

}
void OnMouseUp()
{
trans.position = scanPos;

}
Slingshot in Unity

Attach this script to the “ObjectHolder” gameobject and hit play. You can drag the sphere with the mouse.

Now we need to adjust the lines with our drag point position. Set the position of “ObjectHolder” to (0f,-2.36f,4f).

To make line adjustable with drag point, we need to define the anchors from where to stretch the line to the drag point position.

Create an empty game object and name it “Left Anchor”.Set its position to ( -0.9f, -2.28f ,4.9f).

Create another empty gameobject  and name it “Right Anchor”. Set its position to ( -0.9f, -2.28f ,4.9f).

Now create a script called SlingShotManager and following lines of code in it :

using System.Collections;

using System.Collections.Generic;

using UnityEngine;



public class SlingShotManager : MonoBehaviour {

public Transform leftAnchor;

public Transform rightAnchor;



public Transform ObjectHolder;



public LineRenderer[] lines;



public static SlingShotManager instance;

void Awake()

{
instance = this;

}

// Use this for initialization

void Start ()
{
lines [0].SetPosition (0, leftAnchor.position);
lines [1].SetPosition (0,rightAnchor.position);
}

// Update is called once per frame

void Update ()

{
for (int i = 0; i < lines.Length; i++) {
			
  lines [i].SetPosition (1,ObjectHolder.position);

}
}

}
Slingshot in Unity

Create an empty game object and name it “SlingShot”. Set its position to (0f,-3.27f,5f) and attach this script to the ”SlingShot” and hit play. Drag the “ObjectHolder”, and you can see the lines are adjusting to the drag point.

#2

Shoot Ball

Now create a sphere and name it “Ball”.

Set its position to (0, -2.366f, 4.189f) and rotation to (0 ,0 ,0) and scale(0.3,0.3,0.3) . To throw a ball, we need to manage some physics value according to the input and also need to manage the direction of the ball to throw. Create an empty gameobject and name it “aimer” as a child of “ObjectHolder” and set its position to (0,-0.031f,1.81f). It will be used for aiming of the ball to throw. Add Rigidbody component to the “Ball”. Also, we need to display the path of the ball to shoot. Create a sphere and name it “Point”. Create a Material name it “path mat” and set its shader to Unlit/Color and choose the color of your choice. Assign this material to the point gameobject. Create the total number of points you want to display in the path.

Update the script “SlingShotManager” with the following lines of code :

using System.Collections;

using System.Collections.Generic;

using UnityEngine;



public class SlingShotManager : MonoBehaviour {



public GameObject ball;

public Transform leftAnchor;

public Transform rightAnchor;



public Transform ObjectHolder;



public Transform aimer;



public LineRenderer[] lines;



public static SlingShotManager instance;

void Awake()

{
instance = this;
}


// Use this for initialization


void Start ()
{
lines [0].SetPosition (0, leftAnchor.position);
lines [1].SetPosition (0,rightAnchor.position);
setPath (true);
}

// Update is called once per frame


void Update ()
	{

for (int i = 0; i < lines.Length; i++) {
	
lines [i].SetPosition (1,ObjectHolder.position);
}
}
public GameObject[] points;



public void setPath(bool b)
{
float yPos = (aimer.up.y * 50) / points.Length;

float val = yPos;

for (int i = 0; i < points.Length; i++) {

points [i].SetActive (b);

points [i].transform.parent = aimer;

points [i].transform.localPosition = new Vector3 (0,val,-0.8f);
val += yPos;
}
}

public float speed;

public void throwBall()
{

ObjectHolder.GetComponent<Collider> ().enabled = false;

GameObject clone = Instantiate (ball,ball.transform.position,Quaternion.identity)as GameObject;

clone.SetActive (true);
clone.GetComponent<Rigidbody> ().AddForce (aimer.up*speed,ForceMode.Impulse);
Destroy (clone,3f);

}

}
Slingshot in Unity

Now we need to adjust path according to the “ObjectHolder” so update the script “DragObject” with following lines of code:

using System.Collections;

using System.Collections.Generic;

using UnityEngine;



public class DragObject : MonoBehaviour {

Vector3 screenPoint;
Vector3 offset;

Vector3 scanPos;



Transform trans;

void Start()

{
	trans = this.transform;

	scanPos = trans.position;



	_sensitivity = 40f;

	_rotation = Vector3.zero;
	
}
void Update()
{
	SetDirection ();

}
void OnMouseDown()

{

	// rotating flag
	_isRotating = true;



	// store mouse
	_mouseReference = trans.position;



	screenPoint = Camera.main.WorldToScreenPoint(scanPos);

	offset = scanPos - Camera.main.ScreenToWorldPoint(
	new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));



	SlingShotManager.instance.aimer.eulerAngles = new Vector3 (0,0,0);

	SlingShotManager.instance.setPath (true);

}
void OnMouseDrag()

{
	Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);


	Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;

	trans.position = curPosition;



	float posX = Mathf.Clamp (trans.position.x,-1.4f,1.4f);

	float posY = Mathf.Clamp (trans.position.y,-3f,-2.36f);



	trans.position = new Vector3 (posX,posY,curPosition.z);

}
void OnMouseUp()

{
	// rotating flag

	_isRotating = false;
	
	trans.position = scanPos;



	SlingShotManager.instance.throwBall ();
	Invoke ("ResetDirection",1f);
}
void ResetDirection()

{
	SlingShotManager.instance.aimer.eulerAngles = new Vector3 (0,0,0);
	SlingShotManager.instance.setPath (false);
	SlingShotManager.instance.ObjectHolder.GetComponent<Collider> ().enabled = true;
}

private float _sensitivity;

private Vector3 _mouseReference;

private Vector3 _mouseOffset;

private Vector3 _rotation;

private bool _isRotating;



void SetDirection()

{
	if(_isRotating)
	{

		// offset

		_mouseOffset = (trans.position - _mouseReference);



		// apply rotation

		_rotation.z = (_mouseOffset.x) * _sensitivity;



		// rotate
		SlingShotManager.instance.aimer.Rotate (_rotation);



		// store mouse
	
		_mouseReference = trans.position;

	}
}

}
Slingshot in Unity

Hit play and you can see the path is adjusting as you drag the “Object holder”.

You can set the Materials to all the gameobjects, so they look good. Create a material and name it “Line Mat” set its shader to “Unlit/Color” .Give the color of your choice and add this material to “Left Line” and “Right Line”.  Create a material and name it “Ball Mat” and add it in “Ball”.  Add a component sprite Renderer to ObjectHolder game object and assign the sprite “Object Holder” to it. Also, add component Sprite Renderer to “SlingShot” game object and assign the sprite “Sling Shot” to it. Both sprites are in the demo project.

Now can see the SlingShot of your selected color with the ball. Hit play and throw the ball with the slingshot.

Final output:

Slingshot Output
Ketan Jogadiya
Ketan is a Unity3D game developer at Nimblechapps, a Unity 2D/3D game development company based in India. He is passionate about new technologies in mobile games. He is game developer by day and writer by night.
  • Chintan Shroff

    Hi, this is great but how can i make the ball travel in z axis as well?
    Thanks
    Chintan