I'm trying to make my square jump in Unity 2D when I press Space button. I have the following code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public float moveSpeed;
public float jumpSpeed;
float moveX;
Vector2 pos;
// Update is called once per frame
void Update()
{
MoveHorizontally();
Jump();
}
void MoveHorizontally(){
moveX = Input.GetAxis("Horizontal") * Time.deltaTime;
pos.x = moveX * moveSpeed;
transform.position = new Vector2(transform.position.x + pos.x,transform.position.y + pos.y);
}
void Jump(){
if (Input.GetKeyDown("space")){
GetComponent<Rigidbody2D>().AddForce(new Vector2(0,jumpSpeed * Time.deltaTime), ForceMode2D.Impulse);
Debug.Log("Jumped!");
}
}
}
When I press Space button, "Jumped!" message shows up, but my square not jumping. Any idea?
Thanks a lot.
I tried using Input.GetKey function. It works, but that function keeps making my square go upwards if i keep holding Space button.
U need to assing a value to jumpforce. and of course to the moveforce. if u dont wanna jump repeatly Just name a bool for checking if u are on ground. I use mine as" private bool = isGrounded".
and try the code below. It makes ur jump a condition as a function of touching ground.
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Ground"))
isGrounded = true;
}
and here is my code for jump.
public void PlayerJump() {
if (Input.GetButtonDown("Jump") && isGrounded) {
isGrounded = false;
myBody.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);
}
}
whenever u jump it makes your bool variant false and whenever u touch ground it make ur bool true.
Make sure "Ground" must be same exactly the tag your ground has.
When you call AddForce() method you don't have to multiply with "Time.deltaTime".
What you can do is the following:
First cached your "Rigidbody2D" component from your Start() method because if you call it every frame it will affect your game performance.
private Rigidbody2D rigidbody2D;
void Start()
{
rigidbody2D = GetComponent<Rigidbody2D>();
}
Second, instead of Update() method you should call the FixedUpdate() method which is recommended when you deal with Physics
void FixedUpdate()
{
MoveHorizontally();
Jump();
}
Third, on your Jump() method as I said on top you should not multiply the jump force with Time.deltaTime, instead do the following:
public float jumpForce = 10f;
public void Jump()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rigidbody2D.AddForce(Vector2.up*jumpForce);
}
}
You can adjust the jumpForce as you want.
Also Vector2.up is a shorthand for writing Vector2(0, 1)
You can read more about Vector2 here Vector2.up Unity's Documentation
Related
I wanted to make an endless runner game where the player can jump and he moves forward automatically, so, for the forward movement i wanted to use the rigidbody velocity function in order to make the movement smoother and for the jump i made a custom function. My problem is, when i use in my update method the velocity function alone, it works, when i use it with my jump function it stops working. What can i do?. I tried changing the material of the floor and of the player's box collider to a really slippery one but nothing
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePrima : MonoBehaviour
{
[SerializeField]
private float _moveSpeed = 0f;
[SerializeField]
private float _gravity = 9.81f;
[SerializeField]
private float _jumpspeed = 3.5f;
public float speedAccel = 0.01f;
private CharacterController _controller;
private float _directionY;
public float startSpeed;
public float Yspeed = 10f;
private int i = 0;
public float touchSensibility = 50f;
public int accelTime = 600;
[SerializeField]
Rigidbody rb;
// Start is called before the first frame update
void Start()
{
startSpeed = _moveSpeed;
_controller = GetComponent<CharacterController>();
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
rb.velocity = new Vector3(0f, 0f, 1f) * _moveSpeed;
touchControls();
}
public void touchControls()
{
if (SwipeManager.swipeUp && _controller.isGrounded)
{
_directionY = _jumpspeed;
print("Entrato");
}
_directionY -= _gravity * Time.fixedDeltaTime;
_controller.Move((new Vector3(0, _directionY, 0)) * Time.fixedDeltaTime * Yspeed);
i += 1;
if (i % accelTime == 0)
{
_moveSpeed += startSpeed * speedAccel;
i = 0;
}
}
private void OnControllerColliderHit(ControllerColliderHit hit) //Checks if it collided with obstacles
{
if(hit.transform.tag == "Obstacle")
{
GameOverManager.gameOver = true;
}
}
}
You should either use the CharacterController or the Rigidbody. With the CharacterController you tell Unity where to place the character and you have to check yourself if it is a valid position. With the Rigidbody you push it in the directions you want, but the physics around the character is also interfering.
You can use Rigidbody.AddForce to y when jumping instead of _controller.Move.
First of all. I am pretty much a blank beginner and was trying to make a little game in unity.
It's a stick that gets addforced up and rotated at the same time.
Now the problem is that when I add the transform.up force, it is bound to the objects z rotate and not the global
Is there any way around that?
using UnityEngine;
public class LaunchCAR : MonoBehaviour
{
public Rigidbody2D rb2D;
public float thrust = 10.0f;
public float torque = 1f;
private void Start()
{
transform.position = new Vector3(0.0f, -2.0f, 0.0f);
}
void FixedUpdate()
{
if (Input.GetMouseButtonDown(0))
{
rb2D.AddRelativeForce(-(transform.up) * thrust, ForceMode2D.Impulse);
// float turn = Input.GetAxis("Horizontal");
rb2D.AddTorque(torque, ForceMode2D.Impulse);
}
}
}
AddRelativeForce expects object-space (local) coordinates, but you're passing transform.up which is in world-space coordinates.
Use either Vector3.up or AddForce instead.
(This is 2D project)
My character need to run left and right and jump on ground. It is my first experience with Unity and it latest available version of it, I manage to make my Character run left and right and flip when it is change direction, but it does not jump at all.
For the Character I am currently using 2 Box Collider 2Ds and Rigidbody 2D. Character has mass equal 1.
For the Ground I am currently using 2 Box Collider 2Ds. Ground is single sprite which is cover bottom part of screen.
Below is the code for jumping and grounded I am currently trying to use.
'''
{
public float maxSpeed = 10f;
public float jumpVelocity = 10f;
private bool isGrounded;
private float move = 0f;
private Rigidbody2D rb2d; //Store a reference to the Rigidbody2D component required to use 2D Physics.
private SpriteRenderer sprt_render;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
isGrounded = true;
}
// Update is called once per frame
void Update()
{
GetInput();
}
private void GetInput()
{
move = Input.GetAxis("Horizontal");
if (transform.position.x > -6.2 && transform.position.x < 5.7)
{
rb2d.velocity = new Vector2(move * maxSpeed, rb2d.velocity.y);
}
else
{
rb2d.velocity = new Vector2(move * maxSpeed * -1, rb2d.velocity.y);
}
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
Debug.Log("Jump");
rb2d.velocity = new Vector2(rb2d.velocity.x, jumpVelocity);
isGrounded = false;
//rb2d.AddForce(Vector2.up * jumpVelocity, ForceMode2D.Impulse);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
}
'''
As you can see I try to use two different approach in connection with jump realisation using Velocity and using AddForce result is totally the same it is not jumping even first time. I check thought breakpoint it definitely go trough jumping code but nothing happened.
I have came across similar problem which few people already posted on the forum. I checked the exisiting posts but still not couldn't rectify the issue. I have cube in my program which hits the floor when program starts. However, I found that onCollisionEnter is not being called when cube hits the floor. Rigidbody is attached to the cube. Could anyone guide me where am I making mistake?
Code of cube is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cube : MonoBehaviour
{
public float speed = 3.5f;
public float jumpingforce = 10f;
private bool canjump = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetKey("right"))
{
transform.position += Vector3.right * speed * Time.deltaTime;
}
if(Input.GetKey("left"))
{
transform.position += Vector3.left * speed * Time.deltaTime;
}
if(Input.GetKeyDown("space"))
{
GetComponent<Rigidbody>().AddForce(0,jumpingforce,0);
}
}
void onCollisionEnter(Collision collision)
{
Debug.Log("checking collision....");
}
}
First of all OnCollisionEnter needs to start (as btw any method and class name should in c#) with a capital O .. otherwise Unity will not recognize it and never call it. Unity calls these methods (like also Awake, Start, Update) as "Messages". If they do not exactly match the name they are never found and never called.
Some more things:
Do not call GetComponent repeatedly. It is quite expensive! Rather store the reference once and re-use it.
Then whenever a Rigidbody is involved you should not update it's transformations using the Transform component! This breaks the Physics! Rather use Rigidbody.MovePosition within FixedUpdate
Small Sidenote: Remove any empty Unity message method like Start, Awake, Update. Even if they are empty they are called by Unity as message only causing unnecessary overhead.
So you should change your code to something like
public class cube : MonoBehaviour
{
public float speed = 3.5f;
public float jumpingforce = 10f;
private bool canjump = false;
// you can also already reference this via the Inspector
// then it skips the GetComponnet call
[SerializeField] privte Rigidbody rigidbody;
private void Awake()
{
if(!rigidbody) rigidbody = GetComponent<Rigidbody>()
}
private void FixedUpdate()
{
// Getting this input in FixedUpdate is ok since it is a continues call
if(Input.GetKey("right"))
{
rigidbdy.MovePosition(rigidbody.position + Vector3.right * speed * Time.deltaTime);
}
if(Input.GetKey("left"))
{
rigidbdy.MovePosition(rigidbody.position + Vector3.left * speed * Time.deltaTime);
}
}
private void Update()
{
// this one-time input event has to be checked in Update / frame-based
// since it is true only for one frame and FixedUpdate might not be called during that frame
if(Input.GetKeyDown("space"))
{
// also it's ok calling this in Update since it is a one-time event
// and unlikely to happen twice until FixedUpdate is called again
rigidbody.AddForce(0,jumpingforce,0);
}
}
private void OnCollisionEnter(Collision collision)
{
Debug.Log("checking collision....");
}
}
i have a turret,as a game object when a enemy enters it's collison box,the turret starts firing towards it,the logic is when the enemy exits the collider,it should stop its firing ,and other problem is that when again an enemy enters the collison box i.e the second enemy,it gives me an exception ,"MissingReferenceException :the object of type 'transform' has been destroyed but you are still trying to access it.Your script should eihter be check if it is null or you should not destroy it",but i am checking if the list in not null in my code.here is my code
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TurretScript : MonoBehaviour {
public float shotInterval = 0.2f; // interval between shots
public GameObject bulletPrefab; // drag the bullet prefab here
public float bulletSpeed;
private float shootTime = 0.0f;
private List<Transform> targets;
private Transform selectedTarget;
private Transform myTransform;
private Transform bulletSpawn;
void Start(){
targets = new List<Transform>();
selectedTarget = null;
myTransform = transform;
bulletSpawn = transform.Find ("bulletSpawn"); // only works if bulletSpawn is a turret child!
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "enemy"){ // only enemies are added to the target list!
targets.Add(other.transform);
}
}
void OnTriggerExit2D(Collider2D other){
if (other.tag == "enemy"){
targets.Remove(other.transform);
Debug.Log("gone out");
}
}
void TargetEnemy(){
if (selectedTarget == null){ // if target destroyed or not selected yet...
SortTargetsByDistance(); // select the closest one
if (targets.Count > 0) selectedTarget = targets[0];
}
}
void SortTargetsByDistance(){
targets.Sort(delegate(Transform t1, Transform t2){
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
void Update(){
TargetEnemy(); // update the selected target and look at it
if (selectedTarget)
{
// if there's any target in the range...
Vector3 dir = selectedTarget.position - transform.position;
float angle = Mathf.Atan2(dir.y,dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);// aim at it
if (Time.time >= shootTime){// if it's time to shoot...
// shoot in the target direction
Vector3 lookPos = new Vector3(bulletSpawn.position.x,bulletSpawn.position.y,0);
lookPos = lookPos - transform.position;
float ang = Mathf.Atan2(lookPos.y,lookPos.x)*Mathf.Rad2Deg;
GameObject b1 = Instantiate(bulletPrefab,new Vector3(transform.position.x,transform.position.y,5),transform.rotation)as GameObject;
b1.rigidbody2D.velocity = new Vector3(Mathf.Cos(ang*Mathf.Deg2Rad),Mathf.Sin(ang*Mathf.Deg2Rad),0)*bulletSpeed;
shootTime = Time.time + shotInterval; // set time for next shot
}
}
}
}
here is my enemy script
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EnemyScript : MonoBehaviour {
public Transform target;
public float speed = 2f;
public int Health;
public float GetHealth()
{
return Health;
}
void Update ()
{
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
}
void TakeDamage(int damage){
Health -= damage;
if (Health <= 0)
Destroy(gameObject);
}
void OnTriggerEnter2D(Collider2D otherCollider)
{
PlayerControl shot = otherCollider.gameObject.GetComponent<PlayerControl>();
if (shot != null)
{
SpecialEffectsHelper.Instance.Explosion(transform.position);
Destroy(shot.gameObject);
}
}
}
you need to check if the selected target is the target leaving the collider. You remove the target from the targets list but the selectedTarget var is still populated.
For the null ref exception. Are you using Destroy() to kill the target? Destroy() doesn't cause an OnTriggerExit() or OnCollisionExit() event call, the object is just gone.
edit: you can get around the lack of a call by adding an OnDestroy() function to the dying object that sets it's position to something well outside the level/view of the player. This way the target leaves the collider and then disappears rather than just disappearing in place.