Ok from previous experience when I’ve used GUITexture.hittest with iPhoneTouchPhase.began on the iphone for controls its worked great, but for some unknown reason, the inputs are now repeating if you keep your finger held down or even if you just tap it once, it keeps repeating until you take your finger off and hit some other button. I have no idea whats going on, heres my code (first bit is what governs the touch input just to make it easier to find, and the rest is my full script). Help???
for (var i = 0; i < iPhoneInput.touchCount; i++){
var touch : iPhoneTouch = iPhoneInput.touches[i];
if (touch.phase == iPhoneTouchPhase.Began) {
ljHit = lookJ.HitTest(touch.position);
mjHit = moveJ.HitTest(touch.position);
MBHit = mB.HitTest(touch.position);
RBHit = rB.HitTest(touch.position);
SBHit = sB.HitTest(touch.position);
DRBHit = drB.HitTest(touch.position);
//PBHit = pB.HitTest(touch.position);
}
}
My full script was to long to put in the first post, but here it is.
//GUITextures
var mB : GUITexture;
var rB : GUITexture;
var sB : GUITexture;
var drB : GUITexture;
//var pB : GUITexture;
var lookJ : GUITexture;
var moveJ : GUITexture;
//Transforms
var upperBody : Transform;
var lowerBody : Transform;
var shoulderR : Transform;
var shoulderL : Transform;
//Scripts
var AttackScript : AttackScript;
var Joystick : Joystick;
var LookJoystick : Joystick;
//Misc.
var aOne;
var aTwo;
var aThree;
//Vectors
var ForwardLook : Vector3;
var velocity : Vector3;
var cPos : Vector3;
//Components
var character : CharacterController;
//Booleans
var roll : boolean = false;
var walking : boolean = false;
var attack : boolean = true;
var alive : boolean = true;
var grab : boolean = true;
var wSwitch : boolean = true;
var rollOK : boolean = false;
var MBHit : boolean;
var RBHit : boolean;
var SBHit : boolean;
var DRBHit : boolean;
//var PBHit : boolean;
var ljHit : boolean;
var mjHit : boolean;
var autoLook : boolean;
var anim : boolean;
//Ints
var wType : int = 1;
var tap : int;
//Floats
var maxRotationSpeed : float;
var Aspeed : float;
var ammoLeft : float = 40;
var clipSize : float = 5;
var ammoinClip : float = 5;
var mWep : float;
var rWep : float;
var Atime : float = 2;
var twoSpeed : float = 0.005;
var LastPress : float;
var timer : float;
var Ctime : float = 1;
var crouchHeight : float = 0.5;
var rollTime : float;
var diveSpeed : float = 1;
var time : float;
var rollSpeed : float = 2.0;
var idleSpeed : float = 0.5;
var health : float = 500.0;
var walkSpeed : float = 1.0;
var speed : float = 5.0;
var tTime : float = 0.5;
var switchTime : float = 0.5;
var forwardSpeed : float = 10;
var backwardSpeed : float = 5;
var strafeSpeed : float = 8;
var horizontal : float;
var vertical : float;
//Arrays
var mWeapons : GameObject[];
var rWeapons : GameObject[];
var bullets : GameObject[];
var rGrabs : String[];
var mGrabs : String[];
var mAttack1s : String[];
var mAttack2s : String[];
var mAttack3s : String[];
function Start (){
//Starting Animation
AttackScript = mWeapons[mWep].GetComponent("AttackScript");
animation.Play(mGrabs[mWep]);
AttackSpeed();
//Set Weapons Inactive
for(var b = 0; b < rWeapons.length; b++){
rWeapons[b].SetActiveRecursively(false);
}
for(var a = 0; a < mWeapons.length; a++){
mWeapons[a].SetActiveRecursively(false);
}
if(wType == 1){
mWeapons[0].SetActiveRecursively(true);
}
else if(wType == 2){
rWeapons[0].SetActiveRecursively(true);
}
//Animation Time
rollTime = animation["Roll"].length / 2.5;
//Animation Multi (Allows animations to run simultaneously)
animation["GrabGun"].AddMixingTransform(upperBody);
animation["Walk"].AddMixingTransform(lowerBody);
animation["SSL"].AddMixingTransform(lowerBody);
animation["SSR"].AddMixingTransform(lowerBody);
animation["TKGun"].AddMixingTransform(shoulderR);
animation["SideGunR"].AddMixingTransform(shoulderR);
animation["SideGunL"].AddMixingTransform(shoulderL);
animation["IdleUp"].AddMixingTransform(upperBody);
animation["IdleLow"].AddMixingTransform(lowerBody);
//Animation Layers
animation["IdleLow"].layer = 1;
animation["IdleUp"].layer = 1;
animation["Roll"].layer = 3;
animation["SideGunR"].layer = 0;
animation["SideGunL"].layer = 0;
animation["SSR"].layer = 1;
animation["SSL"].layer = 1;
animation["TKGun"].layer = 0;
animation["GrabGun"].layer = 0;
animation["Walk"].layer = 1;
//Animation Speeds
animation["Roll"].speed = rollSpeed;
}
function Update () {
SetInput();
Move();
Look();
for (var i = 0; i < iPhoneInput.touchCount; i++){
var touch : iPhoneTouch = iPhoneInput.touches[i];
if (touch.phase == iPhoneTouchPhase.Began) {
ljHit = lookJ.HitTest(touch.position);
mjHit = moveJ.HitTest(touch.position);
MBHit = mB.HitTest(touch.position);
RBHit = rB.HitTest(touch.position);
SBHit = sB.HitTest(touch.position);
DRBHit = drB.HitTest(touch.position);
//PBHit = pB.HitTest(touch.position);
}
if (touch.phase == iPhoneTouchPhase.Ended){
MBHit = false;
RBHit = false;
SBHit = false;
DRBHit = false;
ljHit = false;
}
}
if(mjHit){
autoLook = true;
anim = true;
}
else if(!mjHit){
autoLook = false;
anim = false;
}
if(timer - LastPress > tTime){
tap = 0;
if(timer - LastPress < Atime){
attack = false;
AttackScript.attack = true;
}
else{
attack = true;
AttackScript.attack = false;
}
}
if(!roll){
if(rollOK){
if(DRBHit){
animation.CrossFade("Roll");
grab = true;
RollTime();
}
}
}
if(roll){
transform.Translate(Vector3.forward * diveSpeed);
}
if(RBHit){
if(wType == 1){
wType = 2;
DeactivateWeapons();
WeaponSwitch();
}
Fire();
}
if(MBHit){
//if(Input.GetKeyDown("j")){
if(wType == 2){
wType = 1;
DeactivateWeapons();
WeaponSwitch();
}
timer = Time.timeSinceLevelLoad;
if(attack){
if(MBHit){
LastPress = Time.timeSinceLevelLoad;
if(tap > 2){
tap = 1;
}
else{
tap++;
}
Combo();
}
}
}
if(health <= 0){
alive = false;
}
else{
alive = true;
}
if(alive){
if(wSwitch){
if(SBHit){
wSwitch = false;
SwitchButton();
}
}
}
if(walking){
diveSpeed = twoSpeed;
}
else{
diveSpeed = 0.01;
}
}
function RollTime(){
roll = true;
if(wType == 1){
mWeapons[mWep].SetActiveRecursively(false);
}
if(wType == 2){
rWeapons[rWep].SetActiveRecursively(false);
}
yield WaitForSeconds(rollTime + 0.4);
roll = false;
if(wType == 1){
mWeapons[mWep].SetActiveRecursively(true);
}
if(wType == 2){
rWeapons[rWep].SetActiveRecursively(true);
}
}
function Combo () {
if(attack){
switch (tap){
case 0:
//Reset to Idle
animation.CrossFadeQueued("Idle", 0.3, QueueMode.CompleteOthers);
break;
case 1:
//Combo Start
Atime = animation[mAttack3s[mWep]].length;
aOne = animation.PlayQueued(mAttack1s[mWep], QueueMode.PlayNow);
aOne.speed = Aspeed;
break;
case 2:
//Combo Prolonged
attack = false;
Atime += animation[mAttack2s[mWep]].length;
aTwo = animation.PlayQueued(mAttack2s[mWep], QueueMode.CompleteOthers);
aTwo.speed = Aspeed;
break;
case 3:
//Combo Finished
attack = false;
Atime += animation[mAttack3s[mWep]].length;
aThree = animation.PlayQueued(mAttack3s[mWep], QueueMode.CompleteOthers);
aThree.speed = Aspeed;
break;
}
}
}
function DeactivateWeapons(){
if(wType == 2){
mWeapons[mWep].SetActiveRecursively(false);
}
if(wType == 1){
rWeapons[rWep].SetActiveRecursively(false);
}
}
function WeaponSwitch(){
if(wType == 1){
for(var a = 0; a < mWeapons.length; a++){
mWeapons[a].SetActiveRecursively(false);
}
mWeapons[mWep].SetActiveRecursively(true);
AttackScript = mWeapons[mWep].GetComponent("AttackScript");
animation.Play(mGrabs[mWep]);
AttackSpeed();
}
else if(wType == 2){
for(var b = 0; b < rWeapons.length; b++){
rWeapons[b ].SetActiveRecursively(false);
}
rWeapons[rWep].SetActiveRecursively(true);
animation.Play(rGrabs[rWep]);
}
}
function Fire(){
rWeapons[rWep].animation.Play("Fire");
ammoinClip -= 1;
}
function SwitchButton(){
if(wType == 1){
DeactivateWeapons();
if(mWep >= mWeapons.length - 1){
mWep = 0;
WeaponSwitch();
yield WaitForSeconds(switchTime);
wSwitch = true;
}
else{
mWep++;
WeaponSwitch();
yield WaitForSeconds(switchTime);
wSwitch = true;
}
}
else if(wType == 2){
DeactivateWeapons();
if(rWep >= rWeapons.length - 1){
rWep = 0;
WeaponSwitch();
yield WaitForSeconds(switchTime);
wSwitch = true;
}
else{
rWep++;
WeaponSwitch();
yield WaitForSeconds(switchTime);
wSwitch = true;
}
}
}
function AttackSpeed(){
Aspeed = AttackScript.wSpeed;
}
function Reload(){
if(ammoinClip < clipSize){
rWeapons[rWep].animation.Play("Reload");
ammoAdd = clipSize - ammoinClip;
ammoinClip += ammoAdd;
ammoLeft -= ammoAdd;
}
}
function LoseHealth(damage){
health -= damage;
}
function Look(){
if(autoLook){
ForwardLook = Vector3(Joystick.position.x, 0, Joystick.position.y);
}
else if(!autoLook){
ForwardLook = Vector3(LookJoystick.position.x, 0, LookJoystick.position.y);
}
var newForward = Vector3.Slerp(transform.forward, ForwardLook.normalized, maxRotationSpeed * Time.deltaTime);
transform.forward = newForward;
Debug.Log("X = " + newForward.x + "Y = " + newForward.y + "Z = " + newForward.z);
}
function Move(){
var movement = Vector3(Joystick.position.x, 0, Joystick.position.y);
movement.y = 0;
movement.Normalize();
var absJoyPos = Vector2(Mathf.Abs(Joystick.position.x), Mathf.Abs(Joystick.position.y));
movement *= forwardSpeed * ((absJoyPos.x > absJoyPos.y) ? absJoyPos.x : absJoyPos.y);
movement += velocity;
movement += Physics.gravity;
movement *= Time.deltaTime;
character.Move(movement);
if(anim){
MoveAnim();
}
}
function MoveAnim(){
var characterVelocity = character.velocity;
var horizontalVelocity : Vector3 = characterVelocity;
horizontalVelocity.y = 0;
var forwardMotion = Vector3.Dot(transform.forward, horizontalVelocity);
var sidewaysMotion = Vector3.Dot(transform.right, horizontalVelocity);
if (Mathf.Abs(forwardMotion) > Mathf.Abs(sidewaysMotion)){
if (forwardMotion > 0){
animation["Walk"].speed = forwardSpeed;
animation.CrossFade("Walk");
}
else{
animation["Walk"].speed = forwardSpeed * -1;
animation.CrossFade("Walk");
}
}
else if (Mathf.Abs(forwardMotion) < Mathf.Abs(sidewaysMotion)){
if (sidewaysMotion > 0){
animation["SSR"].speed = strafeSpeed;
animation.CrossFade("SSR");
}
else{
animation["SSL"].speed = strafeSpeed;
animation.CrossFade("SSL");
}
}
}
function SetInput(){
vertical = Joystick.position.y;
horizontal = Joystick.position.x;
}
Hey !
I’ve exactly the same problem, my touches are considered in the “began” phase over several frames …
Did you find a way to fix it ?
Thanks!
No sorry, I don’t remember if I fixed it, but I haven’t had a problem since, maybe if you post your code I could try to help.
b-joe
September 29, 2011, 11:12am
5
To me this is perfectly reasonable behavior. When you use the condition that a touch began on a button this stays true over time and you have to tell your code when to stop calling your button-function via an other condition. So by executing the button-function when a touch began you are basically coding a rapid-fire-button.
To code a standard button I would set a variable from 0 to 1 on touchPhase.Began, and on touchPhase.Ended I would check if that variable is 1 and if the Touch ended on the button, then execute the button-function and reset the variable to 0. That way your function is executed only if a touch began and ended on the same button.
Bezzy
November 30, 2011, 11:34am
6
Personally, I would have hoped that TouchPhase.Began was effectively “positive edge” - around for just the beginning frame. If i want other behaviours, I could use TouchPhase.Stationary or TouchPhase.Movement to check that the finger is still down.
It sounds to me like this IS the intent, but because of the asynchronous polling of inputs from iOS (which, I guess, is intended to be used as an event driven architecture, rather than constantly checked), if your frame rate exceeds your iphone’s polling, you’ll get those multiple frames. Thus, if you have controller logic in your update, you’ll have to deal with any place where double positive edge inputs are a problem.
Hooray. Now I have to write another input wrapper to make TouchPhase.Began mean what it actually means.
Skyrise
November 30, 2011, 12:15pm
7
It’s the correct behaviour, touchPhase only manage the input from your finger, but you have to sort the logic on what to do with your buttons by yourself.
If you want a single tap, just use a boolean to manage the status of your button.
Skyrise
November 30, 2011, 12:18pm
8
Bezzy:
Personally, I would have hoped that TouchPhase.Began was effectively “positive edge” - around for just the beginning frame. If i want other behaviours, I could use TouchPhase.Stationary or TouchPhase.Movement to check that the finger is still down.
It sounds to me like this IS the intent, but because of the asynchronous polling of inputs from iOS (which, I guess, is intended to be used as an event driven architecture, rather than constantly checked), if your frame rate exceeds your iphone’s polling, you’ll get those multiple frames. Thus, if you have controller logic in your update, you’ll have to deal with any place where double positive edge inputs are a problem.
Wait, TouchPhase.Began act as intendend: it fires only when your finger touch the screen, only for a single frame.