- Home /
Problem with the touch control
Hello,
The game I'm developing is a 2D shoot em up and I'm making a script to control a spaceship but it gives me some errors!
The scripts works like that: When you touch the left side of the screen (button A) the spaceship goes up, and when you touch the right side (button B) the spaceship goes down. If you don't touch the screen, the spaceship just advance normally.
Here's the situation. I hold the A button and the ship goes up, then I hold the B button without releasing A button and the ship goes down. When I release A button the ship still continues going down because I'm already holding B button. Then (and the problem goes now) when I hold A button again the ship don't go up.
I think that the problem comes from the amount of times that the screen gets touched (TouchCount).
Here is a little sketch to make it more clear. Red button is for showing that the button is hold!
I will be very glad if someone wants to give me some advice.
Thanks!
using UnityEngine; using System.Collections;
public class ShipControl: MonoBehaviour {
public float Speed = 8.0f;
private Transform MyTransform;
private enum Position
{
Up, Down, Center
} ;
private Position ShipPosition = Position.Center;
private float ValueY;
private Touch Touch1;
private int tapCount;
private int i;
// Start para inicializar.
void Start ()
{
MyTransform = transform;
}
void Update () {
if(ShipPosition == Position.Center)
{
MyTransform.Translate(new Vector2(Speed, 0) * Time.deltaTime);
}
else
{
MyTransform.Translate(new Vector2(Speed, ValueY) * Time.deltaTime);
}
ControlFly();
}
void ControlFly()
{
if(Input.touchCount > 0)
{
for(i = 0; i < Input.touchCount; i++)
{
Touch1 = Input.GetTouch(i);
}
if((Touch1.phase == TouchPhase.Ended || Touch1.phase == TouchPhase.Canceled))
{
iTween.RotateTo(gameObject, iTween.Hash("z", 0, "time", 0.3f, "easetype", "easeinoutsine"));
ShipPosition = Position.Center;
}
if(Touch1.position.x < Screen.width/2)
{
if((Touch1.phase == TouchPhase.Stationary) || (Touch1.phase == TouchPhase.Moved))
{
ShipPosition = Position.Up;
iTween.RotateTo(gameObject, iTween.Hash("z", 15, "time", 0.3f, "easetype", "easeinoutsine"));
ValueY = 10;
}
}
else
{
if(Touch1.position.x >Screen.width/2)
{
if((Touch1.phase == TouchPhase.Stationary) || (Touch1.phase == TouchPhase.Moved))
{
ShipPosition = Position.Down;
iTween.RotateTo(gameObject, iTween.Hash("z", -15, "time", 0.3f, "easetype", "easeinoutsine"));
ValueY = -10;
}
}
}
}
}
}
Just a question: If you change your for-function to this, does it work the opposite then? (Only goes up, when both buttons are pressed)
for (i = Input.touchCount; i > 0; i--) { Touch1 = Input.GetTouch(i); }
Not work, I change your code for “for (i = Input.touchCount; i > 0; i--) { Touch1 = Input.GetTouch(i - 1); }” in order to take the first touch, but now not work the step 3 of the graphic.
Answer by canochaba · Nov 12, 2012 at 02:48 AM
Thanks a lot for the answer, but the problem is that it don't recognize the last touch when both buttons are pressed, i have changed your code in order to get the last touch, but the problem persist like in the picture.
if(touchingLeft && touchingRight)
{
for(int i = 0; i < Input.touchCount; i++)
{
MyTouch = Input.GetTouch(i);
}
if(MyTouch.position.x < Screen.width / 2)
{
ShipPosition = Position.Up;
iTween.RotateTo(gameObject, iTween.Hash("z", 15, "time", 0.3f, "easetype", "easeinoutsine"));
ValueY = 10;
}
else if(MyTouch.position.x > Screen.width /2)
{
ShipPosition = Position.Down;
iTween.RotateTo(gameObject, iTween.Hash("z", -15, "time", 0.3f, "easetype", "easeinoutsine"));
ValueY = -10;
}
}
Sorry I misread your issue.
I think your issue is that the last element in the Touch array won't be the last touch that happened. It's just an array meant to represent the fingers touching the screen. When you touch your first finger that's index[0], When you press down your second finger that becomes index [1] ... even when you release your first finger (index [0]) the second finger is still index [1]. This is on purpose so you can keep track of it.
You'd need to keep track of a LastTouchIndex variable that's in the global scope for your script that you'd set when the phase goes to "began".
Does that make sense?
Thanks, Yes, that's the problem, althought when i release the first finger and press again, the first finger is out.
i.e when the users touch two finger:
touches[0] = finger 1, touches[1] = finger 2
user removes finger 1
touches[0] = null, touches[1] = finger 2
player adds finger
touches[0] = null, touches[1] = finger 2, touches[2] = finger 3
Should I find a way to control when finger is Ended / Canceled for clear the array?
Uhm, from these results, it seems that the last touch is the highest index. So GetTouch(input.touchCount - 1) should always return the latest one to use?
That will give the same result that my loop "for" is giving me. I've founded a possible solution in this post: http://forum.unity3d.com/threads/144536-How-to-handle-Unity-re-assigning-touches so, I'm going to try and share the results with you.
Answer by Demigiant · Nov 12, 2012 at 10:01 AM
Hey canochaba :)
Did you try to debug this, and see exactly what's happening?
// Variable used to avoid showing a log in each update
int touchCount;
void ControlFly()
{
if (touchCount != Input.touchCount) {
touchCount = Input.touchCount;
// Does the correct amount of touches show?
// If not, we can stop here since it's a Unity bug
Debug.Log("Tot touches: " + touchCount);
}
if (touchCount == 0) return;
// If there are touches,
// try getting the one you want to use
// using your preferred left to right precedence
float screenHalfW = Screen.width * 0.5f;
Touch activeTouch;
for(int i = 0; i < touchCount; i++) {
Touch touch = Input.GetTouch(i);
if (touch.phase != TouchPhase.Stationary || touch.phase != TouchPhase.Moved) continue;
if (touch.position.x < screenHalfW || activeTouch == null) activeTouch = touch;
}
if (activeTouch != null) {
// You got an active touch, with left touches
// taking precedence over right touches
// YOUR CODE
} else {
// Touch ended or touch cancelled
// YOUR CODE
}
}
I wrote this directly here, so I hope I made no typos :P Also, I never used Touch inputs before, but I was wondering why you aren't taking into account the TouchPhase.Began?
Thanks $$anonymous$$e, but i still have the same problem. I not take into account the TouchPhase.Began because the behaviour will be the same, I need to keep the last touch index or clear the track. In the previous answer I describe exactly what happens with fingers but i'm obfuscated with this issue :(
so how you managed this in the end? im having exactly the same problem. working on it nearly two weeks and still can't find solution. searched for milions pages etc but still nothing.any help?
Your answer
Follow this Question
Related Questions
Input.GetTouch SOMETIMES not registering on iOS 0 Answers
GUI texture touch to input 1 Answer
Working with Touch screens... 1 Answer
Joystick / Button 3 Answers
iPhone - How to calculate a decent touch swipe speed? 2 Answers