Im trying to use touch controls to move my character on a device such as an iPhone. So far I have had limited success. This code works but only with one of the buttons. I have both a left and right button and the left button worked until I added the right button. Now only the right button works. Any help would be appreciated.
foreach (Touch touch in Input.touches)
{
if(leftButton.guiTexture.HitTest(touch.position) && touch.phase != TouchPhase.Ended)
{
move = -1;
anim.SetFloat ("Speed", Mathf.Abs (move));
}
else if(rightButton.guiTexture.HitTest(touch.position) && touch.phase != TouchPhase.Ended)
{
move = 1;
anim.SetFloat ("Speed", Mathf.Abs (move));
}
else if((leftButton.guiTexture.HitTest(touch.position) && touch.phase == TouchPhase.Ended) &&
(rightButton.guiTexture.HitTest(touch.position) && touch.phase == TouchPhase.Ended))
{
move = 0;
}
}
An much easier alternative method for clicking would be
if(Input.GetMouseButtonDown(0))
{
//Your stuff here
}
remember to change input for clickable object (which i think is touch)
First, do a sanity check and verify that the left and right buttons are setup correctly on your component.
I'm not currently on a computer with unity to test everything, but there is a lot of redundancy here, we can clean it up to make debugging the problem easier. Another red flag is I don't see move being set to 0 before the input check, so I'll add that. Try this code and see if you are still seeing the problem, and perhaps you will be able to better debug with monodevelop what is happening.
move = 0;
bool isLeftPressed = false;
bool isRightPressed = false;
foreach (Touch touch in Input.touches)
{
// Only process touches that aren't in the ended phase
if (touch.phase == TouchPhase.Ended)
return;
if (leftButton.guiTexture.HitTest(touch.position))
isLeftPressed = true;
if (rightButton.guiTexture.HitTest(touch.position))
isRightPressed = true;
}
if (isLeftPressed && isRightPressed)
{
// Do nothing when both are pressed (move already set to 0)
}
else if (isLeftPressed)
{
move = -1;
}
else if (isRightPressed)
{
move = 1;
}
anim.SetFloat ("Speed", Mathf.Abs (move));
I made a few assumptions about what you were trying to do with the check if both left and right are pressed. Rather than setting the move value in the foreach loop, we just set flags so that after processing each touch we can see which buttons are being pressed (If finger 0 is touching one, and finger 1 is touching the other, I assume that means you want there to be no movement?)
Related
This is a weirdly phrased question...and I don't know how to explain it well. I'm making a ledge hang mechanic for my game I'm making, you press either of the directions to get onto the ledge, but you also press the directions to get off of the ledge. This means while you're trying to get on the ledge, he instantly falls off. Making a fixed wait time also doesn't feel good...I'm thinking that it would set the axis to 0 until the button is let go, but the problem is that if it's 0, the button is let go. It's a conundrum I can't solve.
Here is the code that detects movements pressed on the left or right arrow keys.
mx = Input.GetAxisRaw("Horizontal");
//Detects if the left or right arrow keys are pressed, and turns it into a number.
Here's some of the code that detects movement while you're hanging There's already a problem...there's an "if hanging" statement right before that's supposed to restrict movement until you let go or jump, but since moving is supposed to ALSO get you out of the hanging, it makes this point moot. I could really just use different buttons, like restricting it to just the jump button or down key (since that uses a different variable), but I want to see if a solution is possible.
if (IsGrabbing == true)
{
rb.velocity = new Vector2(0f, 0f);
rb.gravityScale = 0f;
// mx2 detects vertical movement. This is still a problem, if you're pressing down before you hang, it'll instantly hang instead of waiting for another press, but it's not as bad because you don't press down to hang on a ledge
if (mx != 0 || mx2 < 0)
{
//Just the code that makes you let go and unable to hang, this is reset when you land.
IsGrabbing = false;
anim.SetBool("IsHanging", false);
redXSize = 10f;
redYSize = 10f;
greenXSize = 0f;
greenYSize = 0f;
rb.gravityScale = 5f;
}
I've tried many things, a lot of "while" loops I've tried just crash the game. Does anyone know how to fix this issue? I'll provide all the code if needed.
Edit: With the help of the reply, I've found the solution! There needs to be a flag set like this, where by default it's false. However, it also only checks if it's false, and the else statement means it's true, not to mention the only way to set it to true bypasses that gate anyways. This gives the result needed! Also, while "while" loops seem to break it, adding a condition to every check to not do it while grabbing seemed to fix it. Thanks, everyone!
if (IsGrabbing == true)
{
if (mx != 0 && InitiateGrab == false)
{
InitiateGrab = false;
}
else
{
InitiateGrab = true;
}
rb.velocity = new Vector2(0f, 0f);
rb.gravityScale = 0f;
if (mx != 0 && InitiateGrab == true || mx2 < 0 && InitiateGrab == true)
{
IsGrabbing = false;
InitiateGrab = false;
anim.SetBool("IsHanging", false);
anim.SetBool("IsRising", false);
redXSize = 10f;
redYSize = 10f;
greenXSize = 0f;
greenYSize = 0f;
rb.gravityScale = 5f;
}
}
Since you don't have the code. I can't exactly help you out with the specifics, but I still understand what you're asking and can still help you out. Here is the "sample" code that I'd use in your case:
bool isHanging = false;
void Update()
{
if (Input.GetKeyDown("space") && !isHanging)
{
isHanging = true;
// Use ur code to hang onto the ledge.
} else if (Input.GetKeyDown("space") && !isHanging)
{
isHanging = false;
// Use ur code to get off the ledge.
}
}
bool CheckIfHanging()
{
if(isHanging) { return false; }
else return true;
}
Essentially, this causes a toggle effect where when you press the spacebar AND are close enough to the ledge, you set the bool to true, and you hang onto the ledge and went you want to get off it, you set the isHanging to false, and run your code to jump off the ledge. This does have the effect of making ur controls a toggle control however. If you're looking for a "press" control, where you hold onto a key to hold onto the ledge, and then let go when you press off, then maybe try this:
void Update()
{
if (Input.GetKeyDown("space"))
{
// Hang onto ledge
} else if (Input.GetKeyUp("space"))
{
// Let go of ledge.
}
}
Hope I could help!
(P.S. please put ur code in next time so that I can help you out more!)
Quick update on my answer since u posted ur code. Maybe try changing ur movement code to something like this
bool isHanging = false;
int speed; [SerializeField]
void MoveCharacter()
{
if (isHanging) return;
else mx = speed * Input.GetAxisRaw("Horizontal");
}
Essentially, this still allows you to move with your arrow keys, but will essentially stop your movement code if you're hanging. Also from ur previous comment, you said that you apparently can't use Input.GetKeyDown/Up for your left/right arrows? I'd recommend using KeyCode if that's the case, that should have the input for all btns in ur keyboard.
bool HangLedge()
{
if (!isHanging && Input.GetKeyDown(KeyCode.DownArrow)) return true;
else if (!isHanging && Input.GetKeyDown(KeyCode.DownArrow)) return false;
}
// Set ur ledge code and movement code to take this bool, and run the code when it's either false/true.
Hope I could clarify!
I have this simple code. I have used the if statement to check that if i press the pause button, the jump animation will not be triggered. After the Paused Menu is activated, when i click resume, the game will start immediately and the character will jump straight away.
I have tried using Coroutines, with real time and time.timeScale = 0.001, but the action will still be triggered. Any ideas on how to solve?
private void Jump()
{
if (Input.touchCount > 0 && rb.velocity.y == 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
startTouchPosition = Input.GetTouch(0).position;
if (startTouchPosition.x < screenMinusButton.x || startTouchPosition.y < screenMinusButton.y)
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
}
Try to putting invisible full screen panel , back of the button/menu.
Does the character actually jumps or it's just an animation issue ?
Try to check your rb.velocity in the inspector. If is not visibile, try to enable debug mode in the upper corner.
If the Y doesn't change maybe it's just an animation triggered wrongly
Check if the EventSystem has any GameObject currently considered as active. If yes, the touch is performed over button else the touch is not over the button.
Add using UnityEngine.EventSystems; at the top of your script. Then modify your code as shown below.
if (Input.touchCount > 0 && EventSystem.current.currentSelectedGameObject == null && rb.velocity.y == 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
...
}
Use IsPointerOverGameObject()
if (!EventSystem.current.IsPointerOverGameObject() && Input.touchCount > 0 && rb.velocity.y == 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
}
I recently found the answer.
I am trying to get my 'player' to change directions with my below script
however, it is contently staying stuck in the first 2 if statements of my 'void Update()'
I am trying to use these two scripts (1. https://pastebin.com/AGLatvUD (I wrote this one) and 2. https://pastebin.com/2XA3w04w)
I am attempting to use CharacterController2D to move my player with specified points and actions
Don't know if this is the right place to ask but I figured I'd try!!
void Update() // not sure if should have more in 'FixedUpdate' or others (maybe?)
{
if (isRight && transform.position.x > currentPoint.position.x) // flipping the character -- I'm pretty sure I can use TestCharacterController2D to do this for me, this is comparing the player's 'transform'
{
moveSpeed = -0.25f; // tells controller to head in the left direction
isRight = false; // no longer facing right
}
if (!isRight && transform.position.x < currentPoint.position.x) // reverse of above
{
moveSpeed = -0.25f; // tells controller to head in the right direction
isRight = true; // no longer facing left
}
if (transform.position == currentPoint.position) // checks to see if player is at 'currentPoint'
{
pause = true; // starts the pause sequenece
if (pause) // when the movement is pause do the the following
{
animator.SetFloat("Speed", 0); // player stops moving -- works!
if (maxPause <= 100) // checks to see if still paused
{
Debug.Log(maxPause);
maxPause--; // reduce pause amount (working way out of loop)
if (maxPause < 0) // found 'maxPause' was going to far below zero
maxPause = 0;
}
if (maxPause == 0) // when 'maxPause' timer has finished
{
pointsSelection++; // move to netx point
maxPause = 100; // reset 'maxPause' timer
pause = false; // resume 'transform.position == currentPoint.position' process
}
}
if (pointsSelection == points.Length) // makes sure 'pointsSelection' doesn't go out of bounds
pointsSelection = 0; // start the player's movement process over again
}
else // not sure if requried
Debug.Log("removed pause = false");
any help would be appreciated!!!
Thank you very much!!
I am an amateur (obviously :))
littlejiver
There's nothing that sets the character's position exactly to currentPoint. There are a number of ways to solve this. One way is to check if the character is near the currentPoint instead of exactly on it.
if (Vector2.Distance(transform.position, currentPoint.position) < 0.1f) {
pause = true; // starts the pause sequenece
...
I have a game where you slide some stuff and when you find the special one. Instead of sliding you need to just tap on it. For this I created the following code, but it's not working as I wanted to:
void Update()
{
if (Input.touchCount > 0)
{
// get the first one
Touch firstTouch = Input.GetTouch(0);
// if it began this frame
if (firstTouch.phase == TouchPhase.Began)
{
if (firstTouch.position.x > screenCenter)
{
Anim.SetBool("Swiper", true);
print("Swipe");
}
}
else if (firstTouch.phase == TouchPhase.Stationary)
{
if (E.FInt == 1)
{
//Sound
print("Debugged");
SceneManager.LoadScene(Beh.SceneArray[Beh.Counter]);
}
}
}
}
The problem here is that it executes the code of when you slide even if you just tap.
Lets look at this section:
// if it began this frame
if (firstTouch.phase == TouchPhase.Began)
{
if (firstTouch.position.x > screenCenter)
{
Anim.SetBool("Swiper", true);
print("Swipe");
}
}
If the touch-phase is Began and the the touch is on the right side of the screen, then CLEARLY it's a swipe.
No, no its not. It's a touch that is just beginning. It hasn't had a chance to be swiped yet.
When I run my app on Android, the first finger touch calls Input.GetMouseButtonDown(0)
and the second touch calls Input.GetMouseButtonDown(1).
I want to override GetMouseButtonDown(0) in some cases- so the second finger (1) touch will become the first (0) and I don't know how to do it.
Either this or how to force mouseButtonUp on the first finger touch- I want to remove this first "click" from the system so it'll not use Input.mousePosition in a case of 2 touches.
Why?
I'm creating a paint app when the user can draw lines.
There is an area when the user can paint (in a rectangle) and an area where he shouldn't, I know how to detect when pressed on unwanted area.
But sometimes the palm of my hand creates unwanted first touch Input.GetMouseButtonDown(0) on the unwanted area (without Input.GetMouseButtonUp(0)) and when I start to draw a line
Input.mousePosition gets the average of both touches, so I just want a way to remove a "down" touch/click from the system. Or another way to solve my problem.
Here is my code:
if (Input.touchCount == 0)
{ screenPoint = new Vector3(0, 0, 0);
currentTouch = 4; //currentTouch is for GetMouseButtonUp(currentTouch) }
for (int i=0; i< Input.touchCount; i++)
{
touch = Input.GetTouch(i);
screenPointTemp = touch.position;
screenPointTemp3 = new Vector3(screenPointTemp.x, screenPointTemp.y, zCam);
//if the touch is in a "good" zone-
if (Camera.main.ScreenToWorldPoint(screenPointTemp3).z > BottomNod.transform.position.z - nodeScale)
{
screenPoint = touch.position;
currentTouch = i;
}
}
}
if (Input.GetMouseButtonUp(currentTouch))
{...}
When working on mobile devices to detect a touch on the screen without clicking on any object, you should be using Input.touchCount with Input.GetTouch or Input.touches. Although I highly recommend Input.GetTouch since that doesn't even allocate temporary variables like Input.touches. To get the postion of the touch use, Input.GetTouch(index).position.
Each of these functions returns Touch so you can use Touch.fingerId to detect/keep track of how many touches you want at the-same time. You can also use the index that is passed in to Input.GetTouch to keep track of the touch. That's totally up to you.
This detects every touch down, move and up on mobile devices:
for (int i = 0; i < Input.touchCount; ++i)
{
//Touch Down
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
}
//Touch Moved
if (Input.GetTouch(i).phase == TouchPhase.Moved)
{
}
//Touch Up
if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
}
}
Limit to one touch only(Use index 0):
if (Input.touchCount == 1)
{
//Touch Down
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
}
//Touch Moved
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
//Draw?
}
//Touch Up
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
}
}
Like I said, you can limit this with fingerId. The implementation depends on what exactly that you want.