Elements still bouncing - c#

update - Added a video
I've made things like you can see in many tutorials and forums:
created Physic Material I called "No bounce"
set Dynamic Friction = 0 and Static Friction = 0
created a cube and add a Box collider with Material = "No Bounce"
set Mass = 1, Drag = 0 and Angular Drag = 0
Now I add another cube for the ground, made it very large and added a Box collider with Material = "No Bounce"
I have 2 problems:
- when they collide, the cube bounces (whereas it shouldn't with my configuration)
- I've made a script and attached it to the cube, to change the velocity, and set it to 0 when there's a collision:
using UnityEngine;
public class CubeProperties : MonoBehaviour
{
private Rigidbody _rb;
private bool _landing;
private void Start()
{
_rb = GetComponentInParent<Rigidbody>();
}
public void OnCollisionEnter(Collision collision)
{
Debug.Log("Collision");
_landing = true;
}
public void FixedUpdate()
{
if (!_landing) {
return;
}
_rb.velocity = Vector3.zero;
_landing = false;
}
}
So at the first collision, I try to instant stop the cube with _rb.velocity = Vector3.zero;. But changing velocity has no effect, I dont understand why. I've tried with many value to see what happens... but nothing happened.
The only thing I can add, and it's working, is: AddForce() I tried to a negative value, but this doesn't work either.
What did I forgot?
Here's a video I hope this is easy to understand (and I hope I'm allowed to help with a video):
https://youtu.be/I3C1KBmm5yw

Looks like your mixing 2D physics and 3D physics together. If it's a 2D scene, you'll actually want to use the 2D Rigidbody and Box Collider 2D.
If it's a 3D Scene which is what it seems like, then you just want to make sure you're using the normal OnCollisionEnter. As it stands, the OnCollisionEnter2D won't get called in that setup.
Just to help see if things are getting called, a good tip in Unity is the Debug.Log. It'll send a message to the console if it gets fired off.

Related

Keyboard input works on some occasions but not others

So, I've been trying to learn Unity these past couple of weeks. As a starter project I decided to try and replicate the mobile game Pop the Lock. Right now, I'm having some problems with my keyboard inputs that I just can't figure out how to solve.
This is how my game screen looks: GameScreen. The red bar is the Player and the yellow circle is the Target. As the game progresses, the Player rotates around the ring towards the Target.
Basically, if the Player and the Target are touching AND the Player presses the Space Key at the exact same time, the Player is supposed to gain a point. The Target is also supposed to be destroyed, and a new Target is supposed to randomly be spawned in somewhere on the game screen. At the moment, this system works ... most of the time. About 80% of the time my code operates as it should, but around 20% of the time my code doesn't register when player presses the space key as the two collide. Here's my code:
public class Target: MonoBehaviour {
public GameObject target;
void Update () {
if (Input.GetKeyDown("space")) {
Debug.Log("SPACE PRESSED!!");
}
}
private void OnTriggerEnter2D (Collider2D collision) {
Debug.Log("Collision!");
}
private void OnTriggerStay2D(Collider2D other) {
// This is the part that sometimes isn't registering:
if (Input.GetKeyDown("space")) {
Debug.Log("HIT!!");
Score.score++;
// Code to spawn new Target on random place in the ring:
// Seems to be working as intended:
float distance = 2.034822f;
float x = Random.Range(-2f, 2f);
float y = Mathf.Pow(distance,2) - Mathf.Pow(x,2);
y = Mathf.Sqrt(y);
float[] options = {y, -y};
int randomIndex = Random.Range(0, 2);
y = options[randomIndex];
Vector3 vector = new Vector3(x, y, 0);
GameObject newTarget = Instantiate(target, vector, Quaternion.identity);
Destroy(gameObject);
}
}
}
As you can see I have Log statements that print something every time the player and the target are touching, every time the space key is pressed, and every time the space key is pressed while they are touching. This is how the console looks like when everything is working : Image One. This is what the console looks like when my code isn't working : Image Two.
So even when it isn't working, the collision and the key press are still registered at the exact same time. But for some reason the hit itself isn't registered (so the if condition isn't passed). Because of this I'm quite confident that it's not just input delay or me pressing the key at the wrong time. As I mentioned above, this only happens about 20% of the time, which makes it even more confusing to me. The Target has a trigger collider2D and it also has a dynamic RigidBody2D with gravity scale set to 0 (as I was told it should). Any help would be greatly appreciated.
(How my collider and rigidbody look: Image)
Something you can do is to set a flag to becomes true while you are pressing the key in the update loop, so the update loop will convert to something like:
private bool isSpacePressed = false;
update() {
isSpacePressed = false;
if (Input.GetKeyDown(KeyCode.Space)){
isSpacePressed = true;
}
}
so every loop the flag will be set to false except if you are pressing the space bar and the OnTriggerStay2D while become something like
OnTriggerStay2D () {
if(isSpacePressed){
.. do magic..
}
}
Look that I replace the Input.GetKeyDown('space') to Input.GetKeyDown(KeyCode.Space) I recommend using this one to avoid typing errors

Unity2D: Pushing Player away on collision with enemy

I'm trying to add a script to my game so that whenever the player collides with an enemy he takes damage but is also pushed away in opposite direction. I have tried implementing the Rigidbody2D extension code posted here
Here is part of my player script:
private void OnCollisionEnter2D(Collision2D other)
{
var magnitude = 5000;
if (other.gameObject.CompareTag("Monster"))
{
TakeDamage(25);
GetComponent<Rigidbody2D>().AddExplosionForce(magnitude, this.transform.position, 500);
}
}
When I run the game in Unity I get this error whenever the player collides with an enemy:
Rigidbody2D.AddForce(force) assign attempt for 'Player' is not valid. Input force is { NaN, NaN }.
UnityEngine.Rigidbody2D:AddForce(Vector2, ForceMode2D)
Rigidbody2DExt:AddExplosionForce(Rigidbody2D, Single, Vector2, Single, Single, ForceMode2D) (at Assets/Scripts/Rigidbody2DExt.cs:20)
Player:OnCollisionEnter2D(Collision2D) (at Assets/Scripts/Player.cs:94)
Welcome to StackOverflow.
I would recommend you to try with:
private void OnCollisionEnter2D(Collision2D other){
Vector2 impulse = new Vector2(-7, 2);
if (other.gameObject.CompareTag("Monster")){
TakeDamage(25);
GetComponent<RigidBody2D>().AddForce(impulse, ForceMode2D.Impulse);
}
}
Also you have to find a way to get the desired direction to push the player. For example, if you approach the enemy from the right, you may want to be pushed to the left. In my example, you will be pushed to the left with some up impulse. Let me know if you still have problems :)
References here

Unity 2D sprite doesn't flip

I'm doing a platformer game with Unity 2D and I wanted to flip the character sprite left when the player move him left, but for some reasons it doesn't work. I tried to make this one script:
transform.rotation = new Vector3(0f, 180f, 0f);
but it didn't work. So then I wrote this:
transform.localScale = new Vector3(-0.35f, 0.35f, 1f); //the player's scale x and y are 0.35 by default
but it didn't work too. Then I found this error message in the console: NullReferenceException: Object reference not set to an instance of an object
UnityEditor.Graphs.Edge.WakeUp () (at C:/buildslave/unity/build/Editor/Graphs/UnityEditor.Graphs/Edge.cs:114).
What should I do? I'm doing this game for a game jam so I need to resolve this problem quickly. Thank you.
EDIT: I noticed that I can flip the sprite in the editor, but that I can't do that using scripts.
From this thread I found, it seems like an old bug from Unity's UnityEditor.Graphs.DLL code.
Try restarting Unity completely.
This bug seems to occur only in the editor, and not after a game is built, so you should be safe.
I haven't worked on any 2D Unity projects in a while but here is a piece of code I used to resolve that issue in the past. Let me know if it helps.
private void FlipSprite()
{
bool playerHasHorizontalSpeed = Mathf.Abs(myRigidBody.velocity.x) > Mathf.Epsilon;
if(playerHasHorizontalSpeed)
{
transform.localScale = new Vector2(Mathf.Sign(myRigidBody.velocity.x), 1f);
}
}
This is a bit old so be sure to let me know how this works. You'll need to finish the rest of the controls, but this should work.
public class SpriteFlipper : MonoBehaviour
{
// variable to hold a reference to our SpriteRenderer component
private SpriteRenderer mySpriteRenderer;
// This function is called just one time by Unity the moment the component loads
private void Awake()
{
// get a reference to the SpriteRenderer component on this gameObject
mySpriteRenderer = GetComponent<SpriteRenderer>();
}
// This function is called by Unity every frame the component is enabled
private void Update()
{
// if the A key was pressed this frame
if(Input.GetKeyDown(KeyCode.A))
{
// if the variable isn't empty (we have a reference to our SpriteRenderer
if(mySpriteRenderer != null)
{
// flip the sprite
mySpriteRenderer.flipX = true;
}
}
}
}

Ball object slows down without gravity

I'm making a 2D Block breaker game; the issue is that my ball will slow down after a while, yet there isn't any gravity and the bounciness is at 100% so it should keep all its kinetic energy. I just need the ball to stay at a constant speed.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ball : MonoBehaviour {
public Paddle paddle;
private Vector3 paddleToBallVector;
private bool Started = false;
void Start () {
paddleToBallVector = this.transform.position
paddle.transform.position;
print(paddleToBallVector);
//this.GetComponent<Rigidbody2D>().drag = 0f;
}
void FixedUpdate () {
if (!Started) {
this.transform.position = paddle.transform.position + paddleToBallVector;
if (Input.GetMouseButtonDown(0))
{
Debug.Log("mouse clicked, Started = " + Started);
Started = true;
this.GetComponent<Rigidbody2D>().velocity = new Vector2(2f, 10f);
}
}
}
}
The issue isn't in the code - it's in the game Gravity settings. You could solve it in one of two ways:
1) change the gravity scale of the ball - go to the ball game object or Prefab, and look at the RigidBody2D component. In there, you have a field called "Gravity Scale", usually set to 1. Changing it to 0.1 will make your ball light and quick. However, this setup isn't ideal for a game with multiple levels.
2) Change the global gravity in the project settings. Go in the Edit Menu to the Project Settings and in the menu choose Physics2D:
In the panel that is opened you usually have a realistic gravity scale of -9.81. Change it to something like -1.
This will make all the objects in your game light, and lessen the hold of gravity for all levels. In a brick-breaker type game when only the ball is loose and thrown around, it makes the most sense.
If you want the ball to have constant velocity, you could set it each frame in Update
myRigidbody.velocity = speed * (myRigidbody.velocity.normalized);
Where myRigidBody is a private RigidBody declared somewhere in your script, and set in Start() like this
myRigidbody = this.GetComponent<Rigidbody>();
Because you dont want to have to call GetComponent every single frame.
Create a physics material 2D. Keep the bounciness at 1 but reduce the friction to zero. Now attach that material to your Ball Collider. Your ball won't lose any speed when colliding now

Jumping onto a platform

I am making a 2D platform game in Untiy for android and i am having some issues with a section of code i have. When i jump onto a platform the first time i can land onto the platform but when i jump again i fall through the platform. i have it so the box collider is inactive if the player is less then the height of the platform and active when the player is higher then the platform. I thought the box collider was to small and it was just missing the collider so i have tried different sizes of colliders and i have tried adjusting different heights at which it activates. Also when i set the height to low the player does a double jump. So what am i doing wrong?
public class Rock : MonoBehaviour
{
private BoxCollider2D platform;
private PlayerScript player;
public float height;
void Awake() {
player = GameObject.Find("Player").GetComponent<PlayerScript>();
platform = GetComponent<BoxCollider2D>();
}
void Start () {
platform.enabled = false;
}
// Update is called once per frame
void Update () {
if(player.transform.position.y > height){
platform.enabled = true;
} else if(player.transform.position.y < height){
platform.enabled = false;
}
}
}
Could it be that you're not covering the case where player.transform.position.y == height?
I can see that you're checking for greater / smaller than height but not equality. This could lead to unwanted behavior like the one you're describing.
Let me know if this was the problem.
This code actually worked. The issue ended up being in my playerscript where I had added a chunk of code where I was having a bug if you held the jump button down the player would get stuck in the jump animation.
void OnCollisionStay2D(Collision2D target) {
if (target.gameObject.tag == "Ground") {
grounded = true;
anim.SetBool("Jump",false);
}
}
public void Jump () {
if(grounded){
grounded = false;
anim.SetBool("Jump",true);
myBody.velocity = new Vector2(myBody.velocity.x, 0);
myBody.AddForce( new Vector2(0, jumpForce));
}
}
After some troubleshooting and going and removing pieces of code trying to see why I doubled jump I finally came across this piece then when I was trying with the touch controls instead of with the keyboard I noticed I am not actually able to hold the jump button down like you can with a keyboard so I didn't really need this piece of code. So I was my own worst enemy this time.

Categories

Resources