This is the code i have coded through the online tutorial it is a normal swiping input but i want to change it to cross-platform input. I have no idea how to change it hope you guys can help me out
if (Input.touchCount == 1)
{
if (isSwipping)
{
Vector2 diff = Input.GetTouch(0).position - startingTouch;
diff = new Vector2(diff.x / Screen.width, diff.y /
Screen.width);
if (diff.magnitude > 0.01f)
{
if (Mathf.Abs(diff.y) > Mathf.Abs(diff.x))
{
if (diff.y < 0)
{
Slide();
}
else
{
Jump();
}
}
else
{
if (diff.x < 0)
{
ChangeLane(-1);
}
else
{
ChangeLane(1);
}
}
isSwipping = false;
}
}
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
startingTouch = Input.GetTouch(0).position;
isSwipping = true;
}
else if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
isSwipping = false;
}
}
Related
I have the following code which works very well. I mean... pretty well. The only problem, is when the animation state switches, it's very edgy and sudden, and it doesn't look natural AT ALL. Does anyone know how I can fix that? Thank you in advance!!!
//this runs in Update()
if (Input.GetKey(KeyCode.Space) || jumped) {
if (!characterController.isGrounded)
jumped = true;
else
jumped = false;
if (jumped) {
animator.Play("jump");
return;
}
}
if (characterController.velocity == Vector3.zero) {
animator.Play("idle");
if (!weaponEquipped && !switchingWeapon)
animator.Play("idleArms", 1);
return;
} else if (Input.GetKey("a")) {
if (isRunning && !vitals.isEmpty("stamina")) {
animator.Play("runLeft");
return;
}
animator.Play("walkLeft");
return;
}
if (Input.GetKey("d")) {
if (isRunning && !vitals.isEmpty("stamina")) {
animator.Play("runRight");
return;
}
animator.Play("walkRight");
return;
} else if (Input.GetKey("s")) {
if (isRunning && !vitals.isEmpty("stamina")) {
animator.Play("runBack");
if (!weaponEquipped && !switchingWeapon)
animator.Play("runBackArms", 1);
return;
}
animator.Play("walkBack");
if (!weaponEquipped && !switchingWeapon)
animator.Play("walkBackArms", 1);
return;
} else if (isRunning && !vitals.isEmpty("stamina")) {
animator.Play("run");
if (!weaponEquipped && !switchingWeapon)
animator.Play("runArms", 1);
return;
} else {
animator.Play("walk");
if (!weaponEquipped && !switchingWeapon)
animator.Play("walkArms", 1);
} if (!isRunning && characterController.velocity.magnitude > 0) {
animator.Play("walk");
return;
}
What you're looking for is a Blend Tree, which, combined with Animator, smoothly fades between animations, based on the variable that you define. I can't rewrite your whole code and setup your Blend Tree, but here's a starting point:
using UnityEngine;
using System.Collections;
using System.Collections.Generics;
public class YourClass: MonoBehaviour
{
public Animator animator;
float vertical = 0f;
float horizontal = 0f;
void Update()
{
if (Input.GetButtonDown("Jump"))
{
animator.SetTrigger("Jump");
}
else
{
vertical = Input.GetAxis("Vertical");
horizontal = Input.GetAxis("Horizontal");
animator.setFloat("Vertical Movement", vertical);
animator.setFloat("Horizontal Movement", horizontal);
}
}
}
I'm pretty new to all of this so sorry for rookie mistakes.
I've built a State Machine that I'm pretty happy with, with just one problem, whenever the player jumps on a slope and keeps running (either up or down) the animation won't switch to running and stays at falling.
private void FixedUpdate()
{
GroundCheck();
if (state != State.hurt)
{
Movement();
DoubleJump();
StateMachine();
}
HurtCheck();
anim.SetInteger("state", (int)state);
}
private void Movement()
{
float hDirection = Input.GetAxis("Horizontal");
//holding down "D" makes the value positive and vice versa
if (hDirection < 0)
{
rb.velocity = new Vector2(-speed, rb.velocity.y);
transform.localScale = new Vector2(-1, 1);
}
else if (hDirection > 0)
{
rb.velocity = new Vector2(speed, rb.velocity.y);
transform.localScale = new Vector2(1, 1);
}
else
{
}
if (Input.GetButtonDown("Jump") && isGrounded == true)
{
Jump();
}
}
private void StateMachine()
{
if(rb.velocity.y > 2f && isGrounded == false)
{
state = State.jumping;
}
if(rb.velocity.y < 2f && isGrounded == false)
{
state = State.falling;
}
if(rb.velocity.y == 0 && Mathf.Abs(rb.velocity.x) > 2f)
{
state = State.running;
}
if(rb.velocity.magnitude == 0)
{
state = State.idle;
}
}
It looks like you intend rb.velocity.y to be greater than 0 when on a slope. But in order to enter the running state you have a condition that rb.velocity.y == 0. If you want to run on a slope, then maybe you should change that condition like this.
if((rb.velocity.y < 2f) && (Mathf.Abs(rb.velocity.x) > 2f))
{
state = State.running;
}
I'm trying to figure out which collider with same tag is touching my character firstly when multiple colliders are touching my character same time.
if (col.transform.gameObject.tag == "enemy") {
hit = true;
rgd.AddForce(new Vector2(0, 2.150f), ForceMode2D.Impulse);
if (transform.position.x-col.transform.gameObject.transform.position.x < 0)
{
rgd.AddForce(-1*rgd.transform.right * 40);
}
else
{
rgd.AddForce(1*rgd.transform.right * 40);
}
if (Mathf.Approximately (angle, 0)) {
Destroy (col.transform.gameObject);
damage = 0;
} else {
damage = 25;
}
enemydamageSound.Play();
}
I solved it by adding a few code.Here is my new code:
private int jumpCount = 0;
if (col.transform.gameObject.tag == "ground")
{
isGround = true;
jumpped = true;
jumpCount = 0;
}
if (col.transform.gameObject.tag == "enemy")
{
hit = true;
if (!isGround && jumpCount == 0)
{
rgd.AddForce(new Vector2(0, 2.150f), ForceMode2D.Impulse);
jumpCount++;
}
if (transform.position.x - col.transform.gameObject.transform.position.x < 0)
{
if (jumpCount == 0)
{
rgd.AddForce(new Vector2(0, 2f), ForceMode2D.Impulse);
}
rgd.AddForce(-1 * rgd.transform.right * 40);
}
else
{
if (jumpCount == 0)
{
rgd.AddForce(new Vector2(0, 2f), ForceMode2D.Impulse);
}
rgd.AddForce(1 * rgd.transform.right * 40);
}
if (Mathf.Approximately(angle, 0))
{
Destroy(col.transform.gameObject);
damage = 0;
}
else
{
damage = 25;
}
enemydamageSound.Play();
}
I try to creacte some buildings in 2d, but it should not be touched with the other buildings.I have a
private GameObject building;
From Update i called function
buildFence(Vector2 nextPos)
where i create new building
And from this function i called function which must return boolean type
public bool canbuild()
{
//Debug.Log(building);
if (building.GetComponent<Rigidbody2D>().IsTouchingLayers(LayerMask.GetMask("Buildings")))
{
building.GetComponent<SpriteRenderer>().color = Color.red;
//Debug.Log("canb=false");
return false;
}
else {
building.GetComponent<SpriteRenderer>().color = Color.green;
return true;
}
}
but this function always return true. If i called the same function from Update,
everything works well.
All code here
void Update()
{
if (mode)
{
if (TEST)
{
if (!UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
{
if (Input.GetMouseButtonDown(0) && idBuilding != 0 && buildFlag)
{
buildFlag = false;
startpos = cam.ScreenToWorldPoint(Input.mousePosition);
if (idBuilding != 1)
{
building = (GameObject)Instantiate(buildings[idBuilding - 1], startpos, new Quaternion(0, 0, 0, 0));
building.GetComponent<Collider2D>().isTrigger = true;
canbuild();
}
else
{
}
}
if (Input.GetMouseButton(0) && idBuilding != 0)
{
if (idBuilding != 1)
{
Vector2 pos = cam.ScreenToWorldPoint(Input.mousePosition);
building.transform.position = pos;
canbuild();
}
else
{
buildFence(cam.ScreenToWorldPoint(Input.mousePosition));
if (!canbuild())
{
Debug.Log("succes");
}
}
}
if (Input.GetMouseButtonUp(0) && idBuilding != 0)
{
if (canbuild())
{
buildFlag = false;
Vector2 viewportPoint = Camera.main.WorldToViewportPoint(building.transform.position + new Vector3(2, 2, 0));
bAccept.anchorMin = viewportPoint;
bAccept.anchorMax = viewportPoint;
bAccept.gameObject.active = true;
}
else
{
Debug.Log("CantBuild");
Destroy(building);
buildFlag = true;
}
//building.GetComponent<Collider2D>().enabled = true;
}
}
}
else
{
}
}
}
void buildFence(Vector2 nextPos)
{
Vector2 delta = nextPos - startpos;
//Debug.Log("v2" + (nextPos - startpos));
//Debug.Log("v2.angle="+ Vector2.Angle(new Vector2(x, y), (nextPos - startpos)));
//Debug.Log("v2.angle=" +);
if (delta.magnitude >= 2.55 && canBuildNext)
{
if (delta.x < 0)
building = (GameObject)Instantiate(buildings[0], startpos, Quaternion.Euler(0, 0, Vector2.Angle(new Vector2(x, y), (nextPos - startpos))));
else
building = (GameObject)Instantiate(buildings[0], startpos, Quaternion.Euler(0, 0, -Vector2.Angle(new Vector2(x, y), (nextPos - startpos))));
building.GetComponent<Collider2D>().isTrigger = true;
canBuildNext = false;
}
if (!canBuildNext)
{
if (!canbuild(ref building))
{
Debug.Log("HERE");
if (delta.x < 0)
building.transform.rotation = Quaternion.Euler(0, 0, Vector2.Angle(new Vector2(x, y), (nextPos - startpos)));
else
building.transform.rotation = Quaternion.Euler(0, 0, -Vector2.Angle(new Vector2(x, y), (nextPos - startpos)));
}
else
{
startpos = nextPos;
//building.GetComponent<Collider2D>().isTrigger = false;
Zabor.Push(building);
canBuildNext = true;
}
}
}
public bool canbuild()
{
//Debug.Log(b);
//Debug.Log(building);
if (building.GetComponent<Rigidbody2D>().IsTouchingLayers(LayerMask.GetMask("Buildings")))
{
building.GetComponent<SpriteRenderer>().color = Color.red;
//Debug.Log("canb=false");
buildfail = false;
return false;
}
else {
building.GetComponent<SpriteRenderer>().color = Color.green;
buildfail = true;
return true;
}
}
If a player touch he jump and on swipe (left - right simply moves from left to right .. like any runner).
Everything seems good but as always there is a BUT
Here's the code:
Vector3 startPos;
float minSwipeDistX, minSwipeDistY;
bool isJump = false;
void Start()
{
minSwipeDistX = minSwipeDistY = Screen.width / 6;
}
bool isSwipe = false;
bool isTouch = false;
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.touches[0];
switch (touch.phase)
{
case TouchPhase.Began:
startPos = touch.position;
break;
case TouchPhase.Moved:
isTouch = true;
float swipeDistHorizontal = (new Vector3(touch.position.x, 0, 0) - new Vector3(startPos.x, 0, 0)).magnitude;
float swipeDistVertical = (new Vector3(0, touch.position.y, 0) - new Vector3(0, startPos.y, 0)).magnitude;
if (swipeDistHorizontal > minSwipeDistX)
{
float swipeValue = Mathf.Sign(touch.position.x - startPos.x);
if (swipeValue > 0 && !isSwipe)//to right swipe
{
isTouch = false;
isSwipe = true;
Debug.Log("Right");
}
else if (swipeValue < 0 && !isSwipe)//to left swipe
{
isTouch = false;
isSwipe = true;
Debug.Log("Left");
}
}
// add swipe to up
if (swipeDistVertical > minSwipeDistY)
{
float swipeValueY = Mathf.Sign(touch.position.y - startPos.y);
if (swipeValueY > 0 && !isSwipe)
{
isTouch = false;
isSwipe = true;
Debug.Log("Up");
}
}
break;
case TouchPhase.Stationary:
isJump = true;
break;
case TouchPhase.Ended:
case TouchPhase.Canceled:
isTouch = false;
isSwipe = false;
break;
}
}
}
void FixedUpdate()
{
if (isJump && !isTouch)
{
Debug.Log("Tap");
isJump = false;
}
}
When doing a simple touch (TouchPhase.Stationary) immediately reacts to the player jump.
And when do Jump Swipe UP then jump player when I let go of the finger. I understand it all through what I use (TouchPhase.Ended).
I tried to put TouchPhase.Moved but then all the time before the motion and use jump (TouchPhase.Stationary).
Mauger who faced such a problem?
If so then tell me how to do so was to touch and swipe swipe touch.
This my code:
void Update()
{
#if UNITY_ANDROID || UNITY_IPHONE
if (Input.touchCount > 0)
{
Touch touch = Input.touches[0];
switch (touch.phase)
{
case TouchPhase.Began:
startPos = touch.position;
StartCoroutine(Jump());
break;
case TouchPhase.Moved:
isSwipe = true;
float swipeDistHorizontal = (new Vector3(touch.position.x, 0, 0) - new Vector3(startPos.x, 0, 0)).magnitude;
float swipeDistVertical = (new Vector3(0, touch.position.y, 0) - new Vector3(0, startPos.y, 0)).magnitude;
if (swipeDistHorizontal > minSwipeDistX)
{
float swipeValue = Mathf.Sign(touch.position.x - startPos.x);
if (swipeValue > 0 && !isTouch)//to right swipe
{
isTouch = true;
StartCoroutine(Right());
}
else if (swipeValue < 0 && !isTouch)//to left swipe
{
isTouch = true;
StartCoroutine(Left());
}
}
//add swipe to up
if(swipeDistVertical > minSwipeDistY)
{
float swipeValue = Mathf.Sign(touch.position.y - startPos.y);
if(swipeValue > 0 && !isTouch)
{
isTouch = true;
StartCoroutine(Jump2());
}
}
break;
case TouchPhase.Ended:
isSwipe = false;
isTouch = false;
break;
}
}
#endif
}
IEnumerator Jump2()
{
yield return new WaitForSeconds(0.05f);
if(playerVelocity <= 0.2f)
{
Debug.Log("Swipe Up");
}
}
IEnumerator Jump()
{
if (!isSwipe)
{
yield return new WaitForSeconds(0.05f);
if (!isSwipe && playerVelocity <= 0.2f)
{
Debug.Log("Tap");
}
else
{
yield break;
}
}
else
{
yield break;
}
}
IEnumerator Right()
{
Debug.Log("Right");
}
IEnumerator Left()
{
Debug.Log("Left");
}
I came up with that :
It should put you in the proper direction
float validInputThresold = 5f;
enum Gestures {
None,
Stationary,
SwipeRight,
SwipeLeft,
SwipeUp,
SwipeDown
}
Gestures currentGesture;
public void Update() {
currentGesture = Gestures.None;
HandleTouch(Input.GetTouch(0));
HandleCharacterMovement(currentGesture);
}
Vector3 originalPosition;
void HandleTouch(Touch touch) {
if (touch == null) return;
switch (touch.phase) {
case TouchPhase.Began:
originalPosition = touch.position;
break;
case TouchPhase.Moved:
Vector3 delta = touch.position - originalPosition;
if (delta.magnitude > validInputThresold) Moved(touch, delta);
break;
case TouchPhase.Stationary:
currentGesture = Gestures.Stationary;
break;
case TouchPhase.Ended:
case TouchPhase.Canceled:
currentGesture = Gestures.None;
break;
}
}
public float gestureThresold = 10f;
void Moved(Touch touch, Vector3 delta) {
if ((Mathf.Abs(delta.x)<=gestureThresold && Mathf.Abs(delta.y)<=gestureThresold)
|| (Mathf.Abs(delta.x)>gestureThresold && Mathf.Abs(delta.y)>gestureThresold) )
currentGesture = Gestures.Stationary; //IF FINGER MOVED IN DIAGONAL, INVALID STATE FALLSBACK TO STATIONARY
else if (delta.x > gestureThresold) currentGesture = Gestures.SwipeRight;
else if (delta.x < -gestureThresold) currentGesture = Gestures.SwipeLeft;
else if (delta.y > gestureThresold) currentGesture = Gestures.SwipeUp;
else if (delta.y < -gestureThresold) currentGesture = Gestures.SwipeDown;
}
bool playerIsMoving = false;
// ALL THE ROUTINES HERE SET THE PLAYER IS MOVING FLAG
// TO TRUE AND THEN TO FALSE WHEN THE MOVEMENT IS DONE
void HandleCharacterMovement(Gestures gesture) {
if (playerIsMoving) return;
switch (gesture) {
default:
case Gestures.None:
case Gestures.Stationary:
return;
case Gestures.SwipeRight:
StartCoroutine(MovePlayerRight());
return;
case Gestures.SwipeLeft:
StartCoroutine(MovePlayerLeft());
return;
case Gestures.SwipeUp:
StartCoroutine(Jump());
return;
case Gestures.SwipeDown:
StartCoroutine(Crouch());
return;
}
}
Not sure it is valid, did it by head. feel free to correct it.
The idea behind that :
Find the finger
If any and it is moving get the delta
if delta is over certain amount validate it
if valid assign a gesture state that you can track
process player movement accordingly if player is not already moving