- Home /
Solving Index Out of Bounds on Input.GetTouch(0) in an if statement
Hi everyone, hope you can help me with this.
I've been trying to script a simple game where a player throws 3D Junk into a rubbish bin using swipe gestures on a touch device.
I'm getting an error "Index out of Bounds on line 74 of the following script.
"ArgumentException: Index out of bounds. ShootFINAL.FixedUpdate () (at Assets/Scripts/ShootFINAL.cs:74) " can someone explain what the problem is? Its probably something simple!
using UnityEngine;
using System.Collections;
/* Contained Logic:
* Touch Detection
* Shot Detection/restrictions
* Swipe debugging(disabled)
*
* Author: Conall Ó
*/
public class ShootFINAL : MonoBehaviour {
private Vector3 touchStart;
private Vector3 touchEnd;
private GameObject lineRenderer;
public GameObject cokecan;
private GameObject cokecanClone;
public Vector3 ballPos;
private bool throwable = true;
public GameObject availableShotsGO;
private int availableShots = 10;
public GameObject gameOver;
public float restartDelay = 4f;
float restartTimer;
private bool restarting = false;
// Use this for initialization
void Start()
{
/* Increase vertical Gravity */
Physics.gravity = new Vector3(0, -25, 0);
}
void OnGUI () // ignore this debugging stuff.
{
foreach (Touch touch in Input.touches) {
string message = "";
message += "Finger ID: " + touch.fingerId + "\n";
message += "Phase: " + touch.phase.ToString () + "\n";
message += "TapCount: " + touch.tapCount + "\n";
message += "Pos X: " + touch.position.x + "\n";
message += "Pos Y: " + touch.position.y + "\n";
message += "Input.TouchCount: " +Input.touchCount + "\n";
int num = touch.fingerId;
GUI.Label (new Rect (0 + 130 * num, 0, 120, 100), message);
}
}
void FixedUpdate () {
if (Input.touchCount > 0) {
// if there is a touch, then execute.
Debug.Log ("Touchcount >0 detected");
if (throwable == true) {
throwable = false; //set the ball to "thrown" so we can't throw two at the same time
availableShots--; // decrement number of shots left
availableShotsGO.GetComponent<GUIText> ().text = availableShots.ToString (); // Add the shots remaning as text to our GUI.
Debug.Log ("Shot Detected");
}
}
if (Input.GetTouch(0).phase == TouchPhase.Began) {
touchStart = Input.GetTouch(0).position;
}
if (Input.GetTouch(0).phase == TouchPhase.Ended || Input.GetTouch(0).phase == TouchPhase.Canceled) {
touchEnd = Input.GetTouch(0).position;
DoInput ();
}
if (Input.GetButtonDown ("Fire1")) {
touchStart = Input.mousePosition;
}
if (Input.GetButtonUp ("Fire1")) {
touchEnd = Input.mousePosition;
DoInput ();
}
}
void Update()
{
if (Input.touchCount > 0)
Debug.Log ("Touches detected: " + Input.touchCount);
/* Check if out of shots / Game over */
if (availableShots <= 0) {
Application.LoadLevel("GameOver");
if (restartTimer >= restartDelay) {
Application.LoadLevel (Application.loadedLevel);
restarting = false;
}
}
}
void DoInput()
{
Vector3 p1 = new Vector3();
Vector3 p2 = new Vector3();
touchStart.z = Camera.main.nearClipPlane+.1f; //push it a little past the clip plane for camera, just to make sure its visible on screen
touchEnd.z = Camera.main.nearClipPlane+.1f;
p1 = Camera.main.ScreenToWorldPoint(touchStart);
p2 = Camera.main.ScreenToWorldPoint(touchEnd);
// CreateLine(p1,p2); - Swipe Debugging line creation on input - SWIPE DEBUGGING
CreateLine (p1, p2);
Vector3 v = p2-p1;
if (throwable == true) {
cokecanClone = Instantiate (cokecan, ballPos, transform.rotation) as GameObject;
cokecanClone.GetComponent<Rigidbody> ().AddForce (v.x * 100, v.y * 120, v.y * 300, ForceMode.Impulse);
throwable = false;
}
}
// SWIPE DEBUGGING
//creates an ugly purple line from pos1 to pos2 in worldspace
void CreateLine(Vector3 p1, Vector3 p2)
{
Destroy(lineRenderer);
lineRenderer = new GameObject();
lineRenderer.name = "LineRenderer";
LineRenderer lr = (LineRenderer)lineRenderer.AddComponent(typeof(LineRenderer));
lr.SetVertexCount(2);
lr.SetWidth(0.001f, 0.001f);
lr.SetPosition(0, p1);
lr.SetPosition(1, p2);
}
void restart()
{
Application.LoadLevel(Application.loadedLevel);
}
}
You should not be using FixedUpdate. That's only for physics, and it will sometimes miss events such as TouchPhase.Began/GetButtonDown, since those are true for one frame only, and FixedUpdate doesn't run every frame.
I want my method to be called every fixed framerate frame....
I guess i'l have to split my code up a bit more
What method? I can't see anything which should be in FixedUpdate. Just use Update.
Answer by Conall O · May 11, 2015 at 11:14 PM
yeah, nevermind, I moved everything to update, ive solved this by rewriting from scratch :)
Answer by hbalint1 · May 08, 2015 at 08:28 PM
Change this:
Touch t = Input.touches[0];
to
Touch t = Input.GetTouch(0);
EDIT:
this part of your code:
if (Input.touchCount == 0
means that "if there aren't any touch". I don't think you want that. change it to:
if (Input.touchCount > 0
it complains the index is now out of bounds, what's going on here?
what line is this error on? anyway this part of your code: if (Input.touchCount == 0
means that "if there aren't any touch". I don't think you want that. change it to > 0
@hbalint1:
You should add this comment to your answer since that's the actual problem ^^. It doesn't really matter if you use Input.touches or Input.GetTouch. Input.touches probably has a bit more overhead as it creates a temp array.
updated the question, I meant to have >0 in it earlier, oops !