Unity: Player too close to wall "defies" gravity [Video] - unity3d

i have a little platformer where the player can jump. The jumping works fine, The player jumps high up in the air and falls back down depending on the gravity that I set to it. However, as soon as the player goes over an edge where he can fall down afterwards, his physics seem to get stuck entierly. Instead of falling, he sort of slowly decends as if he was made from leafs or so.
I found out that this also occurs once the player hits a sideways wall. It looks like once you go over an edge the player sort of touches the side of the wall for a second and this kills its physics.
I have recorded this issue here:
https://youtu.be/CE-W4wmMqcA
These are my player settings:
I also tried addin 2D physics to both the wall and the blayer and there set everything to 0. This did alter the effets a little but was far from solving it...
Also, my fixed update, where I jump (catch the bool from update, do physics in fixed:)
void FixedUpdate()
{
currentPlayerSpeed = rb.velocity.x;
if (moveLeft)
{
rb.AddForce((Vector2.left * movementSpeed * Time.deltaTime) - rb.velocity, ForceMode2D.Force);
}
if (moveRight)
{
rb.AddForce((Vector2.right * movementSpeed * Time.deltaTime) - rb.velocity, ForceMode2D.Force);
}
if (jump)
{
if (isGrounded)
{
isGrounded = false;
rb.AddForce(Vector2.up * (jumpHeight * counterForJumpHeight) * Time.deltaTime, ForceMode2D.Impulse);
jump = false;
anim.SetBool("bool_anim_isJumping", true);
}
if (timer != null)
timer.Stop();
counterForJumpHeight = jumpMulitMin;
jumpAlreadCharging = false;
}
if (!moveLeft && !moveRight) // if no movement input is happening
{
if (isGrounded)
{
StopVelocity();
}
}
}

Okay i think i figured it out when you are falling both your moveLeft and moveRight variables are false so you are calling StopVelocity and this if statement is executed.
if (!moveLeft && !moveRight) // if no movement input is happening
{
if (isGrounded)
{
StopVelocity();
}
}
This causes that weird behavior. Since you did not jump but only fall isGrounded is true as well :)

Related

Unity - Object hiting soon the other object

I made a replica project to the game Knife Hit. And I'm having trouble with the following question, is my knife hitting the target before it hits it, or the target is detecting the hit before the knife even arrives. What causes the knife to fly around the target, where it should be stuck on the target. As shown in the image below. Consequently, the spawn of the knives that stay on the target, which is to hinder the gameplay, happen the same, are born and are flying around the target.
The code i use is this:
void Update()
{
if (shoot)
{
lastPosition = transform.position;
transform.position += Vector3.up * speed * Time.deltaTime;
RaycastHit2D hit = Physics2D.Linecast(lastPosition, transform.position);
if(hit.collider != null)
{
shoot = false;
if (hit.transform.tag == "Knife")
{
Level.Instance.HitWrong();
rigidbody.bodyType = RigidbodyType2D.Dynamic;
rigidbody.AddTorque(10, ForceMode2D.Impulse);
}
else
{
transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.y);
transform.parent = hit.transform;
collider.enabled = true;
Level.Instance.HitSucced(rigidbody);
}
}
}
}
You need to make sure your 2D colliders are properly "cutout" outlined... My guess is that your 2D collider is really big around the knife or target

How to fix Game freeze when OnTriggerCollider?

I have one kinematic object (player) which i move very fast (it's need), also i have another objects(obstacles) - they have collider (trigger), and when collider of player enter obstacle collider and trigger event, game freeze to half or one second.
if i reduce speed, then everything is fine
i've tried make player not kinematic and mark obstacles as not trigger (for use OnCollisionEnter event)
how i move player:
void FixedUpdate() {
if (currentWalk != Direction.NONE)
{
checkDirection(); // when distance <0.1f stop moving
transform.position = Vector3.MoveTowards(transform.position, nextPosition, speed * Time.fixedDeltaTime); //speed = 25f;
}
}
nextPosition = Vector3(0f,0f,7f); // just for example, initially player stand in 0,0,0
void OnTriggerEnter(Collider collider)
{
if (collider.tag == "Finish")
{
success.SetActive(true); //success - any object which initially
inactive
}
}
I expect the game won't be freeze, without reduce speed, because i really don't know, what is problem, there are many game with high speed.

Does not work gravity when character touches the wall during a jump

This happens only when :
On hit the wall during the jump + On press left and right arrows.
When there is no wall, gravity acts and character falls down.
However, when character hits the wall, Velocity Y becomes 0 immediately.
When left and right arrow key is up, character falls down again.
GroundCheck works well.
I've been thinking for a lot of time, but I do not know why.
I need help.
My game bug video : https://youtu.be/5omWCYm-y14
My Code :
private void FixedUpdate()
{
isGrounded = Physics2D.OverlapCircle(GroundCheck.position, GroundCheckRadius, GroundLayer) != null;
if (isGrounded)
{
if (Input.GetKeyDown(KeyCode.Z))
{
body.AddForce(Vector2.up * JumpForce);
}
}
body.velocity = new Vector2(Input.GetAxisRaw("Horizontal") * DefaultSpeed, body.velocity.y);
}
If you set velocity directly, rigidbody will get a big horizontal force.
Replace
body.velocity = new Vector2(Input.GetAxisRaw("Horizontal") * DefaultSpeed, body.velocity.y);
with
body.AddForce(Input.GetAxisRaw("Horizontal") * DefaultSpeed * Vector2.right);

Avoid Pushing between rigidbody

I have a issue with my 2D game in unity (pokemon style), I'm using transform.position to move the gameobjects.
I have a player and enemies that follow him, all is ok. But when the enemies make a collision, they begin to push each other
I need that nobody to be pushed when the enemies and player get a collision.
I tried to use kinematic in enemies, but the player can push them.
I tried to add a big amount of mass to the player, but he can push the enemies.
I tried to detect the collision in code with OnCollision, but when I cancel the enemy movement, they don't return to move.
----UPDATE----
I need the collision but without pushing between them, here is a video to illustrate the problem
https://www.youtube.com/watch?v=VkgnV1NOxlw
Just for the record, i'm using A* pathfinding script (http://arongranberg.com/astar/) here my enemies move script.
void FixedUpdate () {
if(path == null)
return;
if(currentWayPoint >= path.vectorPath.Count)
return;
Vector3 wayPoint = path.vectorPath [currentWayPoint];
wayPoint.z = transform.position.z;
transform.position = Vector3.MoveTowards (transform.position, wayPoint, Time.deltaTime * speed);
float distance = Vector3.Distance (transform.position, wayPoint);
if(distance == 0){
currentWayPoint++;
}
}
----UPDATE----
Finally I'll get the expected result,changing the rigidbody2D.isKinematic property to true when the target was close and stop it
Here is a video https://www.youtube.com/watch?v=0Zm0idUU75s
And the enemy movement code
void FixedUpdate () {
if(path == null)
return;
if(currentWayPoint >= path.vectorPath.Count)
return;
float distanceTarget = Vector3.Distance (transform.position, target.position);
if (distanceTarget <= 1.5f) {
rigidbody2D.isKinematic = true;
return;
}else{
rigidbody2D.isKinematic = false;
}
Vector3 wayPoint = path.vectorPath [currentWayPoint];
wayPoint.z = transform.position.z;
transform.position = Vector3.MoveTowards (transform.position, wayPoint, Time.deltaTime * speed);
float distance = Vector3.Distance (transform.position, wayPoint);
if(distance == 0){
currentWayPoint++;
}
}
You can do this in several ways,
You can use Physics2D.IgnoreCollision
Physics2D.IgnoreCollision(someGameObject.collider2D, collider2D);
Make sure that you do the IgnoreCollision call before the collision occurs, maybe when objects instantiate.
or alternatively you can use, Layer Collision Matrix
Unity Manual provides information on using this. This simply does the collision avoidance by assigning different GameObjects to different layers. Try:
Edit->Project Settings->Physics
Or if you want it to just stop moving, You can easily do it like,
bool isCollided = false;
// when when OnCollisionEnter() is called stop moving.
//maybe write your move script like
void Move() {
if(!isCollided) {
// move logic
}
}

Unity 3D game jumping randomly

I am developing my first game with the Unity3D engine and I have run into my first problem! Not as exciting as I thought. If I spam the jump button w my ball jumps the first time then when it lands it does not jump right away but it jumps randomly after a number of button presses. The code I am using is below.
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
private var isFalling = false;
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
if (Input.GetKeyDown(KeyCode.W) && isFalling == false)
{
rigidbody.velocity.y = jumpHeight;
}
isFalling = true;
}
function OnCollisionStay ()
{
isFalling = false;
}
I heard this was a arithmetic behavior problem in UnityScript. I am a very beginner at programming and do not really understand the code in UnityScript and this is the first game/project I am making in Unity3D. Help would be greatly appreciated. Thanks!
You would think that something as simple as jumping should be a no-brainer, but there are a couple of gotchas here:
It can happen that Update() is called twice without any physics updates in between. This means you don't receive OnColliderEnter nor OnColliderStay in between but you still reset isFalling, blocking the jump key.
The moment the ball hits you will receive OnColliderEnter, but not OnColliderStay. This won't happen until the next physics update. If you only listen to -stay you will be one update late.
If you press jump right at the time the ball is supposed to hit the ground then your key is already down when the first collider hit registers. You will be another update late.
Objects sink a little bit into the collider. When you jump, it might take a couple of updates before you clear the collider and you will receive OnColliderStay after you jumped.
I think that last point is the biggest problem here. To solve this you need to do a couple of things:
Use both OnColliderEnter and OnColliderStay. This will imrpove your timing with one update.
Reset isFalling in FixedUpdate instead of in Update. FixedUpdate is part of the physics loop, so it is called right before OnCollisionEnter and OnCollisionStay who will set it again immediately if needed.
Remember that you are trying to jump until you are actually in the air. This allows you to clear the collider with one button press.
The code below implements these points. If you want the timing to be even tighter you must queue the next jump while you are in the air.
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
private var isFalling = false;
private var tryingToJump = false;
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
if (Input.GetKeyDown(KeyCode.W) && !isFalling) tryingToJump = true;
if (tryingToJump)
{
if (isFalling) tryingToJump = false;
else rigidbody.velocity.y = jumpHeight;
}
}
function FixedUpdate()
{
isFalling = true;
}
function OnCollisionStay()
{
isFalling = false;
}
function OnCollisionEnter()
{
isFalling = false;
}