i have a 2d platformer with a player that moves. It works perfect in unity and i packaged it and downloaded the apk on my galaxy s7 which also works perfect.
I then tested it in my local supermarkets tablet display and on both tablets i tried, if i touched left, it would pause for a second, then move left.
The animated enemies, spinning coins and physics was working fine so there wasnt that type of lag, just a pause when moving which makes me think the code i have to move is wrong. The tablets looked fairly high spec too.
Here is how i move the player, i call this in the update function:
List<FingerTouch> currentTouches = new List<FingerTouch>();
public class FingerTouch
{
public int id;
public float beganXPos;
public FingerTouch (int fingerId, float fingerBegan)
{
this.id = fingerId;
this.beganXPos = fingerBegan;
}
}
if (!disableMovment)
{
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
float xPos = Input.GetTouch(i).position.x;
if(xPos < Screen.width / 5)
{
playerLeft = true;
} else if (xPos > ((Screen.width / 5) * 4))
{
playerRight = true;
} else
{
playerUp = true;
}
int fingerId = Input.GetTouch(i).fingerId;
currentTouches.Add(new FingerTouch(fingerId, xPos));
} else if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
if (currentTouches.Count != 0)
{
for (int j = 0; j < currentTouches.Count; j++)
{
FingerTouch currentTouch = currentTouches[j];
if (Input.GetTouch(i).fingerId == currentTouch.id || currentTouches.Count == 1)
{
if (currentTouches[j].beganXPos < Screen.width / 5)
{
playerLeft = false;
}
else if (currentTouches[j].beganXPos > ((Screen.width / 5) * 4))
{
playerRight = false;
}
else
{
playerUp = false;
}
currentTouches.RemoveAt(j);
break;
}
}
} else {
playerUp = false;
playerRight = false;
playerLeft = false;
}
}
}
}
It looks a little over the top but it basicily divides the screen into 3 sections 20/60/20 which move left right jump. When the user touches, it stores that touch and when its released, its removed.
This allows multi touch (jumping and moving) while also preventing jumping, sliding ur finger to the right and removing it and being in an unlimited jumping state as you didnt remove your finger in the middle.
Then after that it moves the player like this:
if (hitLeftWall && playerLeft)
{
playerBody.velocity = new Vector2(0, playerBody.velocity.y);
}
Is there anything here that would cause the player to pause before moving? Should this be in fixed update as the player has a rigidbody? Im new to unity so im not sure on the proper way to do things yet.
Related
I try to add a Joystick programmatically by a touch. The prefab with the attached On-Screen Stick gameobject get instantiated and if I release this finger, the gameobject get destroyed. The only problem is, I cannot move the joystick. Is there a way to make the joystick responsible to the finger who instantiated the joystick prefab?
i tried this: but with no luck:
ExecuteEvents.Execute(leftJoyStick.GetComponent<OnScreenStick>().gameObject,
new BaseEventData(EventSystem.current), ExecuteEvents.selectHandler);
please help.
Ok i'm kinda stupid. i don't need a joystick and do it this way bellow.
when i touch the right side of screen i can look around, when i touch the left side of screen i can move around without a static joystick.
private bool hasLeftStick = false;
private Touch joystickLeftToch;
private Vector2 leftStickTouchStartPos;
private bool hasRightStick = false;
private Touch lookFinger;
private Vector2 rightStickTouchStartPos;
// used in Update()
private void ObserveTouches()
{
foreach (var touch in Input.touches)
{
if (Camera.main.ScreenToViewportPoint(touch.position).x > 0.5f)
{
if (!hasRightStick)
{
hasRightStick = true;
lookFinger = touch;
rightStickTouchStartPos = touch.position;
}
}
else
{
if (!hasLeftStick)
{
hasLeftStick = true;
joystickLeftToch = touch;
leftStickTouchStartPos = touch.position;
}
}
if(joystickLeftToch.fingerId == touch.fingerId && touch.phase == UnityEngine.TouchPhase.Moved)
{
Vector2 dir = (touch.position - leftStickTouchStartPos).normalized;
direction = new Vector3(dir.x, 0f, dir.y);
}
if (joystickLeftToch.fingerId == touch.fingerId && touch.phase == UnityEngine.TouchPhase.Ended)
{
direction = Vector3.zero;
hasLeftStick = false ;
}
if(lookFinger.fingerId == touch.fingerId && touch.phase == UnityEngine.TouchPhase.Moved)
{
look = touch.deltaPosition;
thridPersonCam.m_XAxis.m_InputAxisValue = look.x;
thridPersonCam.m_YAxis.m_InputAxisValue = look.y;
}
if (lookFinger.fingerId == touch.fingerId && touch.phase == UnityEngine.TouchPhase.Ended)
{
look = Vector2.zero;
thridPersonCam.m_XAxis.m_InputAxisValue = 0f;
thridPersonCam.m_YAxis.m_InputAxisValue = 0f;
hasRightStick = false;
}
}
if (Input.touchCount == 0)
{
lookFinger.fingerId = -1;
joystickLeftToch.fingerId = -1;
}
}
Hello guys i want move player between two position use Input.getKeyDown
firstPosition = new vector2(0,0); secondPosition = new vector2(0,5);
if player in firstPosition will go to secondPosition if player press E key
if player in secondPosition will go to firstPosition if player press E key
(movement method is transform.Translate)
my code
if (stairsOn)
{
inHelecopter.inHelecopter = true;
rig2d.simulated = !enabled;
if (transform.localPosition.y > stairS.maxHigh)//down
{
dirUp = false;
}
else if (transform.localPosition.y <= stairS.minHigh)
{//up
dirUp = true;
}
if (transform.localPosition.y >= stairS.maxHigh || transform.localPosition.y <= stairS.minHigh)
{
rig2d.simulated = enabled;
stairsOn = false;
}
if (dirUp)
{
transform.Translate(Vector3.up * 2 * Time.fixedDeltaTime, Space.Self);
}
else
{
transform.Translate(Vector3.down * 2 * Time.fixedDeltaTime, Space.Self);
}
}
Try this:
bool b = true;
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if (b)
{
transform.Translate(secondPosition - firstPosition);
b = false;
}
else
{
transform.Translate(firstPosition - secondPosition);
b = true;
}
}
}
In practice, I assign a variable that controls whether it is in the first or second position and moves the player towards the other.
In this script I use the transform.Translate method, but if you can I recommend that you simply assign the position like this:
bool b = true;
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if (b)
{
transform.position = secondPosition;
b = false;
}
else
{
transform.position = firstPosition;
b = true;
}
}
}
Good work!
I want to trigger an event after tot seconds of long press on a touch screen.
I'm trying to achieve this goal with the following code.
The problem is that the time that has passed is, in some way, random.
private float timePressed = 0.0f;
private float timeLastPress = 0.0f;
public float timeDelayThreshold = 2.0f;
void Update() {
checkForLongPress(timeDelayThreshold);
}
void checkForLongPress(float tim) {
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
// If the user puts her finger on screen...
Debug.Log("Touch start");
timePressed = Time.time - timeLastPress;
}
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
// If the user raises her finger from screen
timeLastPress = Time.time;
Debug.Log("Releasing Touch");
Debug.Log("Time passed --> " + timePressed);
if (timePressed > tim)
{
Debug.Log("Closing APP");
// Is the time pressed greater than our time delay threshold?
Application.Quit();
}
}
}
}
The Fact is that this condition "(timePressed > tim)" is never true and i do not understand why.
Time.time returns The time at the beginning of this frame (Read Only). This is the time in seconds since the start of the game..
Fixed pseudo code:
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
_timePressed = Time.time;
return;
}
if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
var deltaTime = Time.time - _timePressed;
if (deltaTime > _maxTimeTreshold)
{
Application.Quit();
}
}
I have a VR Scene with a C# Script on the camera that allows the user to Click Once to move and again to stop.
public float speed = 1.0f;
public bool startedMoving = true;
public GameObject myCam;
// Update is called once per frame
void Update () {
if (startedMoving) {
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
// if(Input.GetButtonDown("Fire1")){
if (Input.GetMouseButton(0)){
startedMoving = !startedMoving;
}
}
What I want to know is how I can CLICK & HOLD to move Backwards..?
Thank you!
~ b
Use enum the represent the status of the mouse instead of startedMoving or multiple booleans that will make everything easier to implement. The comment in the code describes how it works.
using UnityEngine;
using System.Collections;
public class ClickAndHeld : MonoBehaviour
{
public GameObject myCam;
CLICK_MODE clickMode = CLICK_MODE.NO_CLICK;
MOVE_DIRECTION moveDir = MOVE_DIRECTION.IDLE;
public float speed = 1.0f;
//If down for 0.5 secods the it is considered Click and Hold instead of Click
float clickHoldDetectTime = 0.5f;
float clickCounter = 0; //Dont not change
void Start()
{
StartCoroutine(mover());
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
//If in NO_CLICK, set to CLICKED
if (clickMode == CLICK_MODE.NO_CLICK)
{
//Change the mode to CLICKED
clickMode = CLICK_MODE.CLICKED;
}
//If in CLICKED mode, start counting to clickHoldDetectTime
if (clickMode == CLICK_MODE.CLICKED)
{
clickCounter += Time.deltaTime; //Increment counter
//Check if we have reached the clickHoldDetectTime time
if (clickCounter > clickHoldDetectTime)
{
//Reset Counter
clickCounter = 0;
//Change the mode to CLICK_AND_HELD
clickMode = CLICK_MODE.CLICK_AND_HELD;
}
}
//If STILL down and the the current mode is CLICK_AND_HELD then do clickedAndHeldDown stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
clickedAndHeldDown();
}
}
else
{
//If released and the current mode is CLICKED then do clicked stuff
if (clickMode == CLICK_MODE.CLICKED)
{
clicked();
}
//If released and the current mode is CLICK_AND_HELD, change to RELEASED then do relased stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
//Change the mode to RELEASED
clickMode = CLICK_MODE.RELEASED;
mouseReleasedAfterBeingHeld();
}
//Reset each time mouse button is released
reset();
}
}
IEnumerator mover()
{
while (true)
{
if (moveDir == MOVE_DIRECTION.IDLE)
{
}
//Move Forward
if (moveDir == MOVE_DIRECTION.FORWARD)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
//Move Backward
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
yield return null;
}
}
private void clicked()
{
Debug.Log("CLICKED");
//If Idle, become Forward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.FORWARD;
}
//If forward, moves become idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If backward, moves become idle
else if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
private void clickedAndHeldDown()
{
Debug.Log("CLICKED AND HELD");
//If Idle, becomes backward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.BACKWARD;
}
}
//Called when released after being RELEASED from CLICKED_HELD
private void mouseReleasedAfterBeingHeld()
{
Debug.Log("RELEASED AFTER CLICKED AND HELD");
//If backward, move becomes idle
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If forward, move becomes idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
void reset()
{
clickMode = CLICK_MODE.NO_CLICK;
clickCounter = 0;
}
}
public enum CLICK_MODE
{
NO_CLICK, CLICKED, CLICK_AND_HELD, RELEASED
}
public enum MOVE_DIRECTION
{
IDLE, FORWARD, BACKWARD
}
Because you only have one trigger action you're going to have to implement something time based for toggling forward/backwards movement. For example, if you press and release the trigger quickly then forward walk could be toggled, but if you're holding the trigger after N length of time then walk backwards.
He's a practical example to get you starting.
Pressing and releasing the trigger within 300ms will toggle forward movement
Pressing and holding the trigger for longer than 300ms will begin backwards movement, releasing the trigger then will stop backwards movement
This is a theoretical example
public float speed = 1.0f;
bool triggerPressed = false;
float triggerHeldTime = 0f;
public bool movingForwards = false;
public bool movingBackwards = false;
void Update ()
{
// increment hold time if we're still holding trigger
if (Input.GetMouseButton(0) && triggerPressed)
triggerHeldTime += Time.deltaTime;
if (Input.GetMouseButton(0) && !triggerPressed)
{
// reset everything when trigger initially pressed
movingForards = false;
movingBackwards = false;
triggerHeldTime = 0f;
triggerPressed = true;
}
else if (!Input.GetMouseButton(0) && triggerPressed)
{
// upon trigger release
triggerPressed = false;
// if we are not moving backwards, toggle forwards movement
if(!movingBackwards)
movingForwards = !movingForwards;
// always reset backwards movement when we release the trigger
movingBackwards = false;
triggerHeldTime = 0f;
}
// if the trigger has been held for 300ms then move backwards
if(triggerHeldTime > 0.3f)
{
moveForwards = false;
moveBackwards = true;
}
// actually perform the movement
if (moveForwards)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
else if(moveBackwards)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
}
I am trying to get a GameObject to face right when I press the right arrow and then face left when I press left arrow.
What I currently get is the image to flip back and forth over and over again. It won't just stay facing left or right.
On occasion it will switch to the left and stay that way even though I am pressing right. I am sure there is a better way to do this.
public bool isFacingRight;
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow))
{
petAnimate.AnimationName = "run_loop";
} else
{
petAnimate.AnimationName = "start_loop_2";
}
if (Input.GetKey(KeyCode.RightArrow)) {
isFacingRight = true;
}
if (Input.GetKey(KeyCode.LeftArrow)) {
isFacingRight = false;
}
Flip();
}
void Flip()
{
if (isFacingRight == true)
{
transform.Rotate(0, 0, 0);
}
if (isFacingRight == false)
{
transform.Rotate(0, 180, 0);
}
}
You can simply times the X scale by -1. Multiplying by -1 will just turn everything backwards :)
void Flip()
{
// Switch the way the player is labelled as facing
isFacingRight = !isFacingRight;
// Multiply the player's x local scale by -1
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
Note that this method will work on whichever arrow key you press (left or right). If your character is facing right in your scene, set your bool to true, otherwise set it to false
void Flip()
{
if (isFacingRight == true)
{
transform.localScale = new Vector3(.2f, .2f, 0);
}
if (isFacingRight ==false)
{
transform.localScale = new Vector3(-.2f, .2f, 0);
}
}