System Inputs - How to make my game object jump? - c#

I'm making a simple platformer with a rolling ball that rolls around and collects coins to win each level. I'm using Unity's System input from Unity's package manager to help me with controls and key binding and have successfully gotten my ball to roll around with ease and collect coins with a nice UI setup. However, I would like to implement harder levels where the ball jumps. I can not figure out how to make the ball jump. I know there are others ways to go about this but I just can't figure out how to make it work in the system inputs.
(I know an if statement is needed to test if the ball is grounded however again I'm new and still learning)
Gameplay | OnJump in player input is for jumping | KeyBindings
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class PlayerController: MonoBehaviour
{
public float speed = 0;
public bool isGrounded;
public float jumpForce;
public TextMeshProUGUI countText;
public GameObject winTextObject;
private Rigidbody rb;
private int count;
private float movementX;
private float movementY;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
SetCountText();
winTextObject.SetActive(false);
}
private void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
private void onJump(InputValue value)
{
}
void SetCountText()
{
countText.text = "Count: " + count.ToString();
if(count >= 12)
{
winTextObject.SetActive(true);
}
}
private void FixedUpdate()
{
Vector3 movement = new Vector3(movementX, 0.0f, movementY);
rb.AddForce(movement * speed);
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.CompareTag("PickUp"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetCountText();
}
}
}

Make sure you create a new tag called Ground and put it on everything you want your player to be able to jump on (the ground).
public float jumpHeight = 5f;
public bool isGrounded;
void Update()
{
if (isGrounded)//Checks if is on ground
{
if (Input.GetButtonDown("Jump"))//If the space is pressed
{
rb.AddForce(Vector3.up * jumpHeight)
}
}
}
void OnCollisionEnter(Collision other)//If touch other object
{
if (other.gameObject.tag == "Ground")//If other object has Ground tag
{
isGrounded = true;
}
}
void OnCollisionExit(Collision other)
{
if (other.gameObject.tag == "Ground")
{
isGrounded = false;
}
}
You can also do if (Input.GetButtonDown("Jump")) as
if (Input.GetKeyDown("space"))
or
if (Input.GetKeyDown(KeyCode.Space))

Related

Player now does not jump after adding health in Unity

so first time learning C# for my team studio class. I found this video which I was able to get my player moving and jumping perfectly, https://www.youtube.com/watch?v=3GtQ2yQX2kU&t=569s however after I added a health/can die system to the script, now the player refuses to jump no matter what I do. Since I am a newbie at this, I am just going to post the whole thing here if anyone can point me in the right direction. I've played with the box colliders, added the layers to the platforms like the tutorial said... please, if anyone can help. I know I'm a newbie to this :(
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public HealthBar healthBar; //Communicates with the healthbar script
public float moveSpeed;
public float jumpForce;
public int jumpsAmount;
int jumpsLeft;
public Transform GroundCheck;
public LayerMask GroundLayer;
public int maxHealth = 3;
public int currentHealth;
bool isGrounded;
float moveInput;
Rigidbody2D rb2d;
float scaleX;
// Start is called before the first frame update
void Start()
{
healthBar.SetMaxHealth(maxHealth); //Sets healthbar to max health
currentHealth = maxHealth;
rb2d = GetComponent<Rigidbody2D>();
scaleX = transform.localScale.x;
}
public void TakeDamage(int damage)
{
currentHealth -= damage;
if (currentHealth <= 0) //When Health is zero the player is destroyed
{
Destroy(gameObject);
}
healthBar.SetHealth(currentHealth); //Updates Healthbar when damgage is taken
}
// Update is called once per frame
void Update()
{
moveInput = Input.GetAxisRaw("Horizontal");
Jump();
}
private void FixedUpdate()
{
Move();
}
public void Move()
{
Flip();
rb2d.velocity = new Vector2(moveInput * moveSpeed, rb2d.velocity.y);
}
public void Flip()
{
if (moveInput > 0)
{
transform.localScale = new Vector3(scaleX, transform.localScale.y, transform.localScale.z);
}
if (moveInput < 0)
{
transform.localScale = new Vector3((-1) * scaleX, transform.localScale.y, transform.localScale.z);
}
}
public void Jump()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CheckIfGrounded();
if (jumpsLeft > 0)
{
rb2d.velocity = new Vector2(rb2d.velocity.x, jumpForce);
jumpsLeft--;
}
}
}
public void CheckIfGrounded()
{
isGrounded = Physics2D.OverlapCircle(GroundCheck.position, GroundCheck.GetComponent<CircleCollider2D>().radius, GroundLayer);
ResetJumps();
}
public void ResetJumps()
{
if (isGrounded)
{
jumpsLeft = jumpsAmount;// jumpsAmount =2;
}
}
}
I put the groundcheck collider where the video wanted me to, even played around having different locations too. Nothing is working... tried changing the jump force too to see if it needs to be higher. I am at a complete loss.

I want the key to appear after collecting all the coins

i am making a simple 2d platformer game and i really need some help. I have coins and the player needs to collect all of them. I also have a key and a door, door opens right after player gets the key. Here is the problem: Key is visible all the time but i want it to be visible once the player colllects all the coins so player can get the key and end the chapter. How can i make this happen?
This is my players code:
`
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Player : MonoBehaviour
{
private Rigidbody2D myRigidbody;
private Animator anim;
private int score;
public Text totalscore;
[SerializeField]
private GameObject playerhaskey, dooropened;
[SerializeField]
private int speed;
private bool lookright;
void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
score = 0;
lookright = true;
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
movements(horizontal);
changedirection(horizontal);
}
private void movements(float horizontal)
{
anim.SetFloat("Walk", Mathf.Abs(horizontal));
myRigidbody.velocity = new Vector2(horizontal * speed, myRigidbody.velocity.y);
}
private void changedirection(float horizontal)
{
if (horizontal > 0 && !lookright || horizontal < 0 && lookright)
{
lookright = !lookright;
Vector3 direction = transform.localScale;
direction.x *= -1;
transform.localScale = direction;
}
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "gold")
{
collider.gameObject.SetActive(false);
score = score + 1;
changescore(score);
}
}
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "key")
{
other.gameObject.SetActive(false);
playerhaskey.SetActive(true);
dooropened.SetActive(true);
}
}
void changescore(int count)
{
totalscore.text = count.ToString();
}
}
`
First of all as a side note I would use the same technique for both key and coins. You could have a single OnTriggerEnter2D handle both.
Then I assume all coins are enabled at the beginning and apparently all have a tag gold anyway so you could simply do something like e.g.
private int totalCoinsRequired;
private GameObject key;
private void Start()
{
// find the key object
key = GameObject.FindWithTag("key");
// find all coins -> amount needed to unlock key
totalCoinsRequired = GameObject.FindGameObjectsWithTag("gold").Length;
// initially hide the key
key.SetActive(false);
}
...
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.CompareTag("gold"))
{
collider.gameObject.SetActive(false);
score += + 1;
changescore(score);
// if score reaches required amount unlock key
if(score >= totalCoinsRequired)
{
key.SetActive(true);
}
}
}

How to change default attack direction for player?

I coded my player in my platform game so that he would attack with a sword when you press space. It attacks right when I run right. It attacks left when I run left. But when I stand still by default it attacks left. How do I make it attack right instead?
Below is all the code in my player controller script, and also an image of my blend tree.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public int moveSpeed;
private Animator anim;
public int playerJumpPower = 1250;
private float moveX;
public bool isGrounded;
public float fJumpWaitTime = 0.2f;
private float fJumpWait;
private object col;
private bool attacking;
public float attackTime;
private float attackTimeCounter;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (!attacking)
{
if (Input.GetButtonDown("Jump"))
{
Jump();
}
if (Input.GetAxisRaw("Horizontal") > 0.5f || Input.GetAxisRaw("Horizontal") < -0.5f)
{
transform.Translate(new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));
}
void Jump()
{
//Jumping Code
GetComponent<Rigidbody2D>().AddForce(Vector2.up * playerJumpPower);
isGrounded = false;
}
void OnCollisionEnter2D(Collision2D col)
{
Debug.Log("Player has collided with " + col.collider.name);
if (col.gameObject.tag == "ground")
{
isGrounded = true;
}
}
}
anim.SetFloat("MoveX", Input.GetAxisRaw("Horizontal"));
if (Input.GetKeyDown(KeyCode.Space))
{
attackTimeCounter = attackTime;
attacking = true;
anim.SetBool("Attack", true);
}
if(attackTimeCounter > 0)
{
attackTimeCounter -= Time.deltaTime;
}
if(attackTimeCounter <= 0)
{
attacking = false;
anim.SetBool("Attack", false);
}
}
}
After having another look at your Blend Tree, I would check if your Threst is the problem.
What you have right now:
PlayerAttackLeft 0 -1
PlayerAttackRight 1 1
What you should probably have:
PlayerAttackLeft -0.01 -1
PlayerAttackRight 0 1

Unity how to "power bounce" one object from another relative to it's angle?

I'm working on a simple 3D game where some balls (fixed Z position) fall along a path (using gravity and physics material) to a small flat platform and "power bounce" off this platform. The player can rotate this platform so I want to recreate a realistic bounce direction according to the platform's angle.
I'm new to coding but so far I've figured the relationship between the vector of the ball as it comes into collision with the platform and the platform's normal, which should be a perpendicular line from the surface and that can be used to reflect the ball's vector to the other direction.
I already used OnCollisionEnter and if statement to detect whether it's the platform you are colliding with, but I don't understand where to indicate the normal of the surface and how to access it. Should it be as a public class in the other object or can it be detected from the ball game object?
I tried some examples from this and other websites and got this far:
public class OnCollision : MonoBehaviour
{
public float speed = 25f;
public Rigidbody rb;
private Rigidbody rigid;
private void Start()
{
rigid = transform.GetComponent<Rigidbody>();
}
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag == "BouncePad") {
rb.velocity = transform.up * speed;
}
}
}
Now it bounces off vertically, so I'm guessing I should change the code where the transform.up * speed part is.
Could anyone guide me, please?
Much appreciated.
If you are already using Physics material, look into the Bounciness property. A value of 0 means no bounce, a value of 1 will lead to no loss of energy. The angle of the bounce will be calculated for you. Make sure you drag the physics material onto each object-- both the ball and the wall's material will have an effect.
Finally somebody gave me a hand and came to this solution:
public class Bounce : MonoBehaviour
{
public Rigidbody rb;
public float str = 0.21f;
public float str2 = 0.15f;
// Start is called before the first frame update
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "BouncePad")
{
rb.AddForce(rb.velocity * str, ForceMode.Impulse);
}
if (col.gameObject.tag == "BouncePad2")
{
rb.AddForce(rb.velocity * str2, ForceMode.Impulse);
}
}
// Update is called once per frame
void Update()
{
}
}
public class BouncTest : MonoBehaviour
{
[SerializeField] private float hight = 3;
[SerializeField] private int times = 5;
[SerializeField] private float speed = 8;
private Vector3 _startPos;
private bool _checkUP;
private int _countTimes;
private float _hightbuf;
[HideInInspector]
public bool _bounceEnd;
private void Awake()
{
_startPos = transform.position;
}
public void TurnOnBounceEffect()
{
_bounceEnd = true;
_checkUP = false;
_hightbuf = hight;
_countTimes = 0;
}
private void FixedUpdate()
{
BounceEffect();
}
private void BounceEffect()
{
if (_bounceEnd)
{
if (!_checkUP)
{
if (transform.position.y <= (_startPos.y + _hightbuf))
transform.position = Vector2.MoveTowards(transform.position, new Vector2(_startPos.x, transform.position.y) + (Vector2.up * _hightbuf), speed * Time.fixedDeltaTime);
else
{
_checkUP = true;
}
}
else if (times != _countTimes)
{
if (transform.position.y > _startPos.y)
transform.position = Vector2.MoveTowards(transform.position, _startPos, speed * Time.fixedDeltaTime);
else
{
_countTimes++;
_checkUP = false;
_hightbuf /= 2;
}
}
else
{
transform.position = Vector2.MoveTowards(transform.position, _startPos, speed * Time.fixedDeltaTime);
if (transform.position.y <= _startPos.y)
{
_bounceEnd = false;
}
}
}
}
}

Touch movement for phone

I started making a 2D game in Unity and I have a problem with my player. I add 2 buttons for left and right and jump just tapping the display . When I start the game just the buttons left and right works and the jump don't . I added from another script something for jump and now when I start the game the player goes automatically at right and don't respect the buttons action. (but jumping works) this is the 2 codes that I joined them :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public float moveSpeed = 300;
public GameObject character;
private Rigidbody2D characterBody;
private float ScreenWidth;
void Start()
{
ScreenWidth = Screen.width;
characterBody = character.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
int i = 0;
while (i < Input.touchCount)
{
if (Input.GetTouch(i).position.x > ScreenWidth / 2)
{
RunCharacter(1.0f);
}
if (Input.GetTouch(i).position.x < ScreenWidth / 2)
{
RunCharacter(-1.0f);
}
++i;
}
}
void FixedUpdate()
{
#if UNITY_EDITOR
RunCharacter(Input.GetAxis("Horizontal"));
}
private void RunCharacter(float horizontalInput)
{
characterBody.AddForce(new Vector2(horizontalInput * moveSpeed * Time.deltaTime, 0));
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move2d : MonoBehaviour
{
public float playerSpeed; //allows us to be able to change speed in Unity
public Vector2 jumpHeight;
public bool isDead = false;
private Rigidbody2D rb2d;
private Score gm;
// Use this for initialization
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
gm = GameObject.FindGameObjectWithTag("gameMaster").GetComponent<Score>();
}
// Update is called once per frame
void Update()
{
if (isDead) { return; }
transform.Translate(playerSpeed * Time.deltaTime, 0f, 0f); //makes player run
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpHeight, ForceMode2D.Impulse);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("ground")) // this will return true if the collision gameobject has ground tag on it.
{
isDead = true;
rb2d.velocity = Vector2.zero;
GameController.Instance.Die();
}
}
void OnTriggerEnter2D(Collider2D col)
{
if( col.CompareTag("coin"))
{
Destroy(col.gameObject);
gm.score += 1;
}
}
}
If you know a better script please help
Try adding #endif for the #if UNITY_EDITOR

Categories