How to fix boolean value? - c#

I am trying to get this jump/movement system and the bool for a ground check is not changing. When I try the code the value of the bool is its starting value. Here is my code. The code is c# and the engine I am using is unity.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MOVEMENT : MonoBehaviour
{
public float playerJumpHeight;
public GameObject player;
public float speed;
public float PlayerXPosition;
public bool isgrounded = false;
public GameObject data_to;
void fixedupdate()
{
PlayerXPosition = player.transform.position.x;
}
void OnCollisionEnter(Collision theCollision)
{
if (theCollision.gameObject.name == "floor")
{
isgrounded = true;
transform.Translate(0,0,1);
}
if (theCollision.gameObject.name == "Height_Check")
{
isgrounded = false;
transform.Translate(0,0,0);
}
}
//consider when the character is jumping .. it will exit collision.
void OnCollisionExit(Collision theCollision)
{
if (theCollision.gameObject.name == "floor")
{
isgrounded = false;
}
}
void Update()
{
Rigidbody2D rb = GetComponent<Rigidbody2D>();
if (Input.GetKeyDown(KeyCode.W) && isgrounded == true) {
rb.AddForce(transform.up * speed);
}
if (Input.GetKey(KeyCode.A))
rb.AddForce(Vector2.left);
if (Input.GetKey(KeyCode.D))
rb.AddForce(Vector2.right);
}
}

If your game is 2D, you must use OnCollisionEnter/Exit 2D.
void OnCollisionEnter2D(Collision theCollision)
{
if (theCollision.gameObject.name == "floor")
{
isgrounded = true;
transform.Translate(0, 0, 1);
}
// ...
}

Related

Problems with OnCollisionEnter2D & OnCollisionExit2D

I'm trying to make the Player not jump continuously so I use isOnGrounded variable to check if the player is on the ground or not. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class PlayerController : MonoBehaviour
{
//REFERENCES
private Rigidbody2D rb2D;
//VARIABLES
[SerializeField] float moveSpeed = 0;
private float moveX;
[SerializeField] bool isOnGrounded = true;
[SerializeField] float jumpY;
// Start is called before the first frame update
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
moveX = Input.GetAxis("Horizontal");
PlayerJump();
}
private void FixedUpdate()
{
PlayerMove();
}
void PlayerMove()
{
rb2D.velocity = new Vector2(moveX * moveSpeed * Time.fixedDeltaTime, rb2D.velocity.y);
}
void PlayerJump()
{
if (Input.GetKeyDown(KeyCode.Space) && isOnGrounded == true)
{
rb2D.AddForce(new Vector2(rb2D.velocity.x, jumpY));
}
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Ground"))
{
isOnGrounded = true;
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.CompareTag("Ground"))
{
isOnGrounded = false;
}
}
}
The problem is when the Player is standing on Platform01 so obviously isOnGrounded = true and when the Player moves out of Platform01 isOnGrounded = false, I suppose when move in Platform02 it will automatically check the Ground and isOnGrounded = true but it still false and everything just messing up.
This is because OnCollisionEnter2D(Platform02) is triggered before OnCollisionExit2D(Platform01).
You can remember the last hit collider and compare with it when leave a platform.
public class PlayerController : MonoBehaviour
{
private Collision2D ground;
public bool IsGround => (bool)ground;
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Ground"))
{
ground = other;
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.CompareTag("Ground") && other == ground)
{
ground = null;
}
}
}

Juggled player animation on the slopes in Unity

I have another issue with my animator in 2D.
Currently i have only few slopes in game, but it annoys me, because i don't know how to make animation work properly on them. This is one example:
As you can see, there is little slope. Now how my Animator looks like:
The code now looks like it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using System;
public class PlayerMovementScript : MonoBehaviour
{
[SerializeField] float runSpeed;
[SerializeField] float jumpSpeed;
[SerializeField] float climbSpeed;
Vector2 moveInput;
Rigidbody2D playerRigidbody;
Animator playerAnimator;
CapsuleCollider2D playerCapsuleCollider;
float gravityScaleAtStart;
void Start()
{
playerRigidbody = GetComponent<Rigidbody2D>();
playerAnimator = GetComponent<Animator>();
playerCapsuleCollider = GetComponent<CapsuleCollider2D>();
gravityScaleAtStart = playerRigidbody.gravityScale;
}
void Update()
{
Run();
FlipSprite();
ClimbLadder();
Falling();
}
void OnMove(InputValue value)
{
moveInput = value.Get<Vector2>();
Debug.Log(moveInput);
}
void OnJump(InputValue value)
{
if (!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))) { return; }
if (value.isPressed)
{
playerRigidbody.velocity += new Vector2(0f, jumpSpeed);
}
}
void Run()
{
Vector2 runVelocity = new Vector2(moveInput.x * runSpeed, playerRigidbody.velocity.y);
playerRigidbody.velocity = runVelocity;
bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
if (playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
playerAnimator.SetBool("isRunning", playerHasHorizontalSpeed);
} else
{
playerAnimator.SetBool("isRunning", false);
}
}
void FlipSprite()
{
bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
if (playerHasHorizontalSpeed)
{
transform.localScale = new Vector2(Mathf.Sign(playerRigidbody.velocity.x), 1f);
}
}
void ClimbLadder()
{
if (!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Climb"))) {
playerRigidbody.gravityScale = gravityScaleAtStart;
playerAnimator.SetBool("isClimbing", false);
playerAnimator.SetBool("isClimbingIdle", false);
return;
}
Vector2 climbVelocity = new Vector2(playerRigidbody.velocity.x, moveInput.y * climbSpeed);
playerRigidbody.velocity = climbVelocity;
playerRigidbody.gravityScale = 0;
bool playerHasVerticalSpeed = Math.Abs(playerRigidbody.velocity.y) > Mathf.Epsilon;
playerAnimator.SetBool("isClimbing", playerHasVerticalSpeed);
playerAnimator.SetBool("isClimbingIdle", !playerHasVerticalSpeed);
}
void Falling()
{
if (
playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Climb"))
|| playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))
) {
playerAnimator.SetBool("isJumping", false);
playerAnimator.SetBool("isLanding", false);
return;
}
bool playerHasVerticalSpeed = Math.Abs(playerRigidbody.velocity.y) > Mathf.Epsilon;
if (playerRigidbody.velocity.y >= 0)
{
playerAnimator.SetBool("isJumping", playerHasVerticalSpeed);
playerAnimator.SetBool("isLanding", false);
} else
{
playerAnimator.SetBool("isJumping", false);
playerAnimator.SetBool("isLanding", playerHasVerticalSpeed);
}
}
}
If my player went on slope, Animator shows my animations switch quickly between Run, Jump and Land. How to fix it to save correct jump animation?

How do I call a method which is in another class, when swiping up, down, left or right? Unity2D

I have a Unity project that I started a couple of days ago. It is a simple 2D top down shooting game, which is aimed to be played on smartphone platforms.
I have a Shooting script, which basically has a method called Shoot1, which spawns in a bullet.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooting : MonoBehaviour
{
public Transform firePoint;
public GameObject BulletRedPrefab;
public GameObject BulletGreenPrefab;
public float bulletForce = 20f;
// Update is called once per frame
void Start()
{
}
void Update()
{
}
public IEnumerator Shoot1()
{
yield return new WaitForSeconds(0.00001f);
GameObject bullet = Instantiate(BulletRedPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
}
I also have the Swipe script which determines the direction of the swipe, etc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Swipe : MonoBehaviour
{
private bool tap, swipeUp, swipeDown, swipeLeft, swipeRight;
private bool isDraging = false;
private Vector2 startTouch, swipeDelta;
// Update is called once per frame
private void Update()
{
tap = swipeUp = swipeDown = swipeLeft = swipeRight = false;
if (Input.touches.Length > 0)
{
if (Input.touches[0].phase == TouchPhase.Began)
{
isDraging = true;
tap = true;
startTouch = Input.touches[0].position;
}
else if (Input.touches[0].phase == TouchPhase.Ended || Input.touches[0].phase == TouchPhase.Canceled)
{
isDraging = false;
Reset();
}
}
if (Input.GetMouseButtonDown(0))
{
tap = true;
isDraging = true;
startTouch = Input.mousePosition;
}
else if (Input.GetMouseButtonUp(0))
{
isDraging = false;
Reset();
}
swipeDelta = Vector2.zero;
if (isDraging)
{
if (Input.touches.Length > 0)
swipeDelta = Input.touches[0].position - startTouch;
else if (Input.GetMouseButton(0))
swipeDelta = (Vector2)Input.mousePosition - startTouch;
}
if (swipeDelta.magnitude > 125)
{
float x = swipeDelta.x;
float y = swipeDelta.y;
if (Mathf.Abs(x) > Mathf.Abs(y))
{
if (x < 0)
swipeLeft = true;
else
swipeRight = true;
}
else
{
if (y < 0)
swipeDown = true;
else
swipeUp = true;
}
Reset();
}
}
private void Reset()
{
startTouch = swipeDelta = Vector2.zero;
isDraging = false;
}
public Vector2 SwipeDelta { get { return swipeDelta; } }
public bool SwipeUp { get { return swipeUp; } }
public bool SwipeDown { get { return swipeDown; } }
public bool SwipeLeft { get { return swipeLeft; } }
public bool SwipeRight { get { return swipeRight; } }
}
And I have the GestureDetector script which is aimed to shoot a bullet whenever the user swipes left, right, up or down. When I tried to make the player object (which is called robot) move via swiping, it worked. But when I try calling a method from another class with swiping, it's not working.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GestrueDetector : MonoBehaviour
{
public Shooting other;
public Swipe swipeControls;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
private void Update()
{
if (GameObject.Find("robot") != null)
{
if (swipeControls.SwipeLeft)
desirePosition += Vector3.left;
other.Shoot1();
if (swipeControls.SwipeRight)
desirePosition += Vector3.right;
other.Shoot1();
if (swipeControls.SwipeUp)
desirePosition += Vector3.up;
other.Shoot1();
if (swipeControls.SwipeDown)
desirePosition += Vector3.down;
other.Shoot1();
}
}
}
I just started using unity this week, so I'm quite new to the software. Thank you very much!
For coroutines you need to call this methods like this:
StartCoroutine(Shoot1());
I a little bit changed your classes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooting : MonoBehaviour
{
public Transform firePoint;
public GameObject BulletRedPrefab;
public GameObject BulletGreenPrefab;
public float bulletForce = 20f;
void Start ()
{
}
void Update()
{
}
public void Shoot()
{
StartCoroutine(Shoot1());
}
private IEnumerator Shoot1()
{
yield return new WaitForSeconds(0.00001f);
GameObject bullet = Instantiate(BulletRedPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
}
And for GestrueDetector:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GestrueDetector : MonoBehaviour
{
public Shooting other;
public Swipe swipeControls;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
private void Update()
{
if (GameObject.Find("robot") != null)
{
if (swipeControls.SwipeLeft)
desirePosition += Vector3.left;
other.Shoot();
if (swipeControls.SwipeRight)
desirePosition += Vector3.right;
other.Shoot();
if (swipeControls.SwipeUp)
desirePosition += Vector3.up;
other.Shoot();
if (swipeControls.SwipeDown)
desirePosition += Vector3.down;
other.Shoot();
}
}
}
Just read more about how coroutines are working in Unity - https://docs.unity3d.com/ScriptReference/Coroutine.html

Jump/Throw Coding or Animation Issues

The Setup
I have a basketball player with an animator and 5 assigned animations to that animator as followed:
PlayerIdle
PlayerWalk
PlayerJump
PlayerBend
PlayerShoot
Setup_FruitHoops
Player Animation Window with Parameters
The Problem
In PlayMode, the player is able to move and jump successfully. The issue comes when the player attempts to grab the apple that is on the ground. The desired game design that I wanted was for the player to bend over and grab the apple by pressing the G key and then press G again to throw the apple towards the hoop to score a point. However, when I run it and after I first press G, the player can no longer jump, grab, or throw. The below section is the code for PlayerMovement and GrabberScript. Any advice is greatly appreciated.
PlayerMovement.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 5f;
private Rigidbody2D rb;
private Animator anim;
private bool isGrounded, jumped;
private float jumpshotPower = 6f;
public Transform groundCheck;
public LayerMask groundLayer;
private void Awake()
{
rb = GameObject.Find("Player Parent").GetComponent<Rigidbody2D>();
anim = GameObject.Find("Player Parent").GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
CheckIfGrounded();
PlayerJump();
}
private void FixedUpdate()
{
PlayerWalk();
}
void PlayerWalk()
{
float h = Input.GetAxisRaw("Horizontal");
if (h > 0)
{
//going right
anim.SetBool("isWalking", true);
rb.velocity = new Vector2(speed, rb.velocity.y);
ChangeDirection(-1);
}
else if (h < 0)
{
//going left
anim.SetBool("isWalking", true);
rb.velocity = new Vector2(-speed, rb.velocity.y);
ChangeDirection(1);
}
else
{
//standing still
anim.SetBool("isWalking", false);
rb.velocity = new Vector2(0f, rb.velocity.y);
}
}
void ChangeDirection(int d)
{
Vector3 temp = transform.localScale;
temp.x = d;
transform.localScale = temp;
}
void CheckIfGrounded()
{
isGrounded = Physics2D.Raycast(groundCheck.position, Vector2.down, 0.1f, groundLayer);
if (isGrounded)
{
if (jumped)
{
jumped = false;
anim.SetBool("isJumping", false);
}
}
}
void PlayerJump()
{
if (isGrounded)
{
if (Input.GetKey(KeyCode.UpArrow))
{
jumped = true;
rb.velocity = new Vector2(rb.velocity.x, jumpshotPower);
anim.SetBool("isJumping", true);
}
}
}
}
GrabberScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrabberScript : MonoBehaviour
{
private bool grabbed, throwObject;
private RaycastHit2D hit;
public float distance;
public Transform holdpoint;
public float throwForce;
public LayerMask notFruitLayer;
private Animator anim;
private void Awake()
{
anim = GameObject.Find("Player Parent").GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.G))
{
if (!grabbed)
{
//grab fruit
anim.Play("PlayerBend");
Physics2D.queriesStartInColliders = false;
hit = Physics2D.Raycast(transform.position, Vector3.down * transform.localScale.x, distance);
if(hit.collider != null && hit.collider.tag == "Apple")
{
grabbed = true;
}
}
else if(!Physics2D.OverlapPoint(holdpoint.position, notFruitLayer))
{
//throw fruit
grabbed = false;
if(hit.collider.gameObject.GetComponent<Rigidbody2D>() != null)
{
PlayerShooting();
}
}
if (grabbed)
{
hit.collider.gameObject.transform.position = holdpoint.position;
}
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, transform.position + Vector3.down * transform.localScale.x * distance);
}
void PlayerShooting()
{
if (grabbed == true)
{
if (Input.GetKey(KeyCode.G))
{
throwObject = true;
hit.collider.gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(transform.localScale.x, 1) * throwForce;
anim.Play("PlayerShoot");
}
}
}
}

Bullet spawn stops/buggs randomly

I'm having some difficulties with my shooting script. Normally the bullets works just fine but sometimes(totally random) I can't shoot any more.
I can see the sprite right beside my character but it doesn't move. And if that happens it can't be fixed until I restart the game.
The weapon Script is on the player
public class weaponScript : MonoBehaviour {
public Transform shotPrefab;
public float shootingRate = 0.25f;
private float shootCooldown;
public float xtrans;
void Start(){
shootCooldown = 0f;
}
void Update(){
if (shootCooldown > 0){
shootCooldown -= Time.deltaTime;
}
}
public void Attack(bool isEnemy)
{
if (CanAttack){
if(PinkPlayerControler.playerFaceRight == true)
xtrans = transform.position.x + 2f;
else if(PinkPlayerControler.playerFaceRight == false)
xtrans = transform.position.x - 2f;
shootCooldown = shootingRate;
var shotTransform = Instantiate(shotPrefab) as Transform;
//shotTransform.position = transform.position;
shotTransform.position = new Vector3(xtrans, transform.position.y,transform.position.z);
}
}
public bool CanAttack
{
get{
return shootCooldown <= 0f;
}
}
}
And the other two on the bullet
public class bulletMove : MonoBehaviour {
public Vector2 jumpVector;
public int speed;
void Update(){
startMovement ();
}
void startMovement(){
if (PinkPlayerControler.playerFaceRight == true) {
rigidbody2D.velocity = transform.right.normalized * speed;
Destroy(this);
}
else {
rigidbody2D.velocity = -transform.right.normalized * speed;
Destroy(this);
}
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "bulletDeath" || other.tag == "groundTrap")
Destroy (this.gameObject);
else if (other.tag == "destroyByBullet") {
Debug.Log("blockHit");
Destroy (other.gameObject);
Destroy(this.gameObject);
}
}
}
Shoot Script
public class shootScript : MonoBehaviour {
public static int damage = 1;
public static bool hit = false;
void Start()
{
Destroy(gameObject, 2);
}
void Update(){
if (hit == true)
Destroy (this.gameObject);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "bullet") {
Destroy(other.gameObject);
}
}
}
I don't get why it stops to work so randomly.
Thanks in advance :)
Chrizzly

Categories

Resources