I am trying to make the player to climb a ladder. (2D game)
I used this code for that,
void OnTriggerEnter2D(Collider2D collider){
if(collider.gameObject.tag=="Ladder"){
_canClimb = true;
_anim.SetBool("Climb",true);
}
}
void OnTriggerExit2D(Collider2D collider){
if(collider.gameObject.tag=="Ladder"){
_canClimb = false;
_anim.SetBool("Climb",false);
}
}
In the update() ,
if(Input.GetKey(KeyCode.UpArrow) && _canClimb == true){
transform.position = Vector3.Lerp(transform.position,ladderTop.transform.position,Time.deltaTime);
}
I have put a child game object to ladder to get the position of the top of the ladder.
But When the player jumps and hit with the box collider of the ladder I can see the climbing animation. And after that the player falls down to the ground again. It doesn't move up. What is the reason for that?
Now it is working as I expected, Here is the code,
if(Input.GetKey(KeyCode.UpArrow) && _canClimb == true){
_myRigidBody.isKinematic = true;
transform.position = Vector3.Lerp(transform.position,ladderTop.transform.position,Time.deltaTime);
}
I just added this line and it works perfectly :
_myRigidBody.isKinematic = true;
Rigidbody.isKinematic
If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore.
Related
playerLayer = 11;
if (Input.GetMouseButtonDown(1))
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, crooshair.transform.position - transform.position, 100, ~playerLayer);
if (hit != null)
{
Interactable interactable = hit.collider.GetComponent<Interactable>();
if (interactable != null)
{
SetFocus(interactable);
}
}
else
Debug.Log("Nothing was hit");
}
Every time my player shoot a raycast it ends up hitting my player. The reason this is is because the raycast is starting inside of the player (which is what I want it to do) but it keeps detecting the player no matter what I do. I've used layers, tried to disable Queries start in colliders, and even starting the raycast from a little bit outside of the player but nothing works. When I try and offset the raycast from the player it sometimes works but that is only as long as you shoot in the direction that the offset is going. Please help.
Does your Player have any childed objects with a Collider that are not layered as playerLayer? Just to assure your layermask is setup correctly, I would advise assigning it in the inspector then invert it using the tilde.
public LayerMask playerLayer;
void Update()
{
if (Input.GetMouseButtonDown(1))
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, crooshair.transform.position, 100, ~playerLayer);
if (hit != null)
{
Interactable interactable = hit.collider.GetComponent<Interactable>();
if (interactable != null)
{
Debug.Log("Hit" + hit.collider.name);
}
}
}
}
If you are still unable to debug this with assigning the LayerMask in the inspector, if you could post your hierarchy it might help solve the issue.
I am developing a 2d game in unity, and I am trying to add friction to slow the player down when he is on the ground. I launch the player into the air with the rigidbody's add force. I have heard of physics materials, and am currently trying to use them. I am using the 2d version of them, I made one material which had high friction. I add the material to the floor, and then I play the game, and my character is still sliding on the floor. I thought the problem might be with the player not having a physics material, so I added one. It still didn't work.
I tried doing different combinations with the different materials.
I tried attaching a rigidbody, but kinematic to the floor.
I tried looking it up, and couldn't find an answer.
Here is the code that moves the player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public bool isGrounded = true;
public float fireForce;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
camera = camObj.GetComponent<Camera>();
}
void Update()
{
RotateToPoint();
Fire();
}
void OnCollisionEnter2D(Collision2D obj)
{
if (obj.gameObject.tag == "surface")
{
isGrounded = true;
}
}
void OnCollisionExit2D(Collision2D obj)
{
if (obj.gameObject.tag == "surface")
{
isGrounded = false;
}
}
void Fire()
{
if (Input.GetKeyDown(KeyCode.Mouse0) && isGrounded)
{
rb.AddForce(transform.up * fireForce, ForceMode2D.Impulse);
}
}
}
I do not know if I am approaching the problem correctly. If I am not, does anyone know how to avoid slippery game objects. Any help would be appreciated.
Adding a higher angular drag was the solution to my problem. Angular drag is what slows the object down along its rotation. Friction may not always be the problem.
Notice the two highlighted variables. You might want to raise these values (I changed angular drag from its default) to something higher. Adding the physics material might help, you should try this if this first solution doesn't work.
The problem here is that you are not limiting the velocity of the player, so what you can do is set an if statement if the player is touching the floor and the velocity is higher than what you want it to be.
Example:
void FixedUpdate()
{
if (isGrounded == true && rb.velocity.x > 1 || isGrounded == true && rb.velocity.z >1)
{
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
}
So, I'm still not the best at this but I'm trying to use this script for 2D movement but the jumping isn't working for some reason. It keeps saying that the OnCollisionEnter function "is declared but never used". Can someone tell me what im doing wrong? Thanks
If I remove the (Collision col) part it says that "void cannot be used in this context".
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RonyWalking : MonoBehaviour
{
Rigidbody2D rigid;
SpriteRenderer sprite;
public bool isJumping;
public float spd = 2.0f;
// Start is called before the first frame update
void Start()
{
rigid = GetComponent<Rigidbody2D>();
sprite = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
if(Input.GetKey("d")){rigid.velocity = new Vector2(spd, 0);}
else if(Input.GetKey("a")){rigid.velocity = new Vector2(-spd, 0);}
if(Input.GetKeyDown("w") && isJumping == false)
{
rigid.velocity = new Vector2(0, 5);
isJumping = true;
}
void OnCollisionStay(Collision col)
{
isJumping = false;
}
}
}
When using 2D physics, you need to use the 2D lifecycle methods;
void OnCollisionStay2D(Collision2D col)
{
isJumping = false;
}
And you shouldn't put this method inside your Update method... It should be on class level:
public class RonyWalking
{
void Update()
{
// ...
}
void OnCollisionStay2D(Collision2D col)
{
// ...
}
}
Don't worry about "Is declared but never used", this may be because you don't have specific code referencing the method, but Unity will raise events that calls it, "automagically"
Another thing that I can see while reading your code, that may be unintentional behaviour for you, is that when clicking left/right, you set velocity UP to 0, and when clicking up you set LEFT/RIGHT velocity to 0; this will result in freezing the movement mid-air if you jump, then move while in air:
Click D; velocity = 2, 0
Click W; velocity = 0, 5
Character will now move upwards until another input is given
Click D; velocity = 2, 0 and the character will continue moving while in air because when moving sideways the up/down velocity is set to 0
To solve this, either set the other to existing velocity or make the inputs manipulate a Vector that you then apply at the end of the movement code:
Vector2 existingMovement = rigid.velocity;
if (Input.GetKey(KeyCode.D))
existningMovement.x = spd;
else if (Input.GetKey(KeyCode.A))
existningMovement.x = -spd;
if (Input.GeyKeyDown(KeyCode.W) && !isJumping)
{
existningMovement.y = 5f;
isJumping = true;
}
Furthermore, I think you may have some unexpected behaviour with OnCollisionStay; it will fire every frame that you're colliding with the ground, I assume. But I think it may also fire a frame or two AFTER you've jumped since the physics of your character will not INSTANTLY leave the collision, so isJumping will be set to false even after your jump, letting you jump while in the air one more time.
I would recommend that you use OnCollisionExit2D(Collision2D col) to set isJumping = true instead, or OnCollisionEnter2D(Collision2D col) and set it to isJumping = false, depending on the functionality you desire (if you want the ability to jump after walking out of a cliff)
I've joined a game jam, and I'm making a 2D platformer in Unity for it. For this I've created a Jump Pad. Whenever the player character stands on it they'll jump. The problem is that the jump doesn't look like a jump, it looks more like a teleportation upwards. Any fixes? Code below!
void OnTriggerEnter2D(Collider2D other) {
if (other.tag == "Spike") {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
} else if (other.tag == "Jump Pad") {
rb.AddForce(new Vector2(0f, jumpSpeed));
}
}
Edit
https://imgur.com/a/7MM4QJF
this code worked for me
private void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "player")
{
//you can change 20 to whatever number you want
other.GetComponent<Rigidbody2D>().AddForce(new Vector2(0, 20), ForceMode2D.Impulse);
}
}
Note : be sure to tag the player "player"
Note 2 : be sure is trigger is off
You can try to add upward force like below
rb.AddForce(transform.up*jumpSpeed);
Note: Set a 'realistic' jumpSpeed.
DUDE. lol so i just tried this and what do u know it was giving me trouble, but what i did was take that trigger script off the player and have the jumppad detect the trigger.
if (other.tag == "Player")
{
other.GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpSpeed));
}
tag ur player player and put this on the jump pad and set to istrigger
I want the player to jump when the player is grounded.
private void OnTriggerStay(Collider other)
{
if(other.gameObject.layer == 8)
{
isGrounded = true;
}else { isGrounded = false; }
}
The player is on air when spawning. After the player falls to the Terrain, which has the tag Ground, isGrounded is still false. When I set isGrounded manually true and jump again, it's still true after collision. I also don't want the player to double jump in the air, which I probaly already coded but is not working because something is wrong.
Changing OnTriggerStay to OnTriggerEnter doesn't change something. I hope you can help me.
Do not use OnTriggerStay to do this. That's not guaranteed to be true very time.
Set isGrounded flag to true when OnCollisionEnter is called. Set it to false when OnCollisionExit is called.
bool isGrounded = true;
private float jumpForce = 2f;
private Rigidbody pRigidBody;
void Start()
{
pRigidBody = GetComponent<Rigidbody>();
}
private void Update()
{
if (Input.GetButtonDown("Jump") && isGrounded)
{
pRigidBody.AddForce(new Vector3(0, jumpForce, 0));
}
}
void OnCollisionEnter(Collision collision)
{
Debug.Log("Entered");
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
void OnCollisionExit(Collision collision)
{
Debug.Log("Exited");
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
}
}
Before you say it doesn't work, please check the following:
You must have Rigidbody or Rigidbody2D attached to the player.
If this Rigidbody2D, you must use OnCollisionEnter2D and
OnCollisionExit2D.
You must have Collider attached to the player with IsTrigger
disabled.
Make sure you are not moving the Rigidbody with the transform such
as transform.position and transform.Translate. You must move
Rigidbody with the MovePosition function.
Use this to check if collision is detected at all, it's good starting point for further debuging:
private void OnTriggerStay(Collider other)
{
Debug.Log(other);
}
You must have Collider attached to the player with IsTrigger disabled.
I think you mean enabled? I was struggling to get this to work but as soon as I enabled the collider's IsTrigger it started actually working. The OnTriggerEnter/Exit doesn't seem to do very much on a collider that isn't actually a trigger...