I'm currently working on a simple 2d jump and run game. I want to move my player with physics (using addforce).
In the editor, my player jumps at a normal height. But when i build the game it suddenly jumps way higher. I put everything in fixedUpdate() and don't know where the problem is?
//Movement
rb.velocity = new Vector2(horizontalMove, rb.velocity.y);
//Jump
if (jumpPressed)
{
if (isGrounded)
{
rb.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);
anim.SetTrigger("takeOf");
}
}
Dan
If jumpPressed is true for every frame when the jump key is held, this could be the issue. This would mean that the code could act several times, reapplying the upwards force several times (before it goes far away enough from the ground that the ground check does not detect it). If this is the case, it can be fixed by:
rather than using AddForce, set the vertical velocity to the velocity of the jump.
changing the jumpPressed to only return true if jump was pressed this frame
Imposing a limit to how often you can jump (if you cannot jump twice within 0.1 seconds, that could fix the issue)
Related
I have a ball in my demo game that has a bounce rate of 0.6. If the ball lands on a platform, of course it bounces. But the thing is, I actually tried to stick the ball to the platform.
When the ball collides with the surface of the platform, the speed of rigid body 2D becomes 0. But I guess because of the bounce rate, ball jumps a little bit and lands again in 0.02 seconds. Because of this, OnCollisionEnter2D runs for 2 times, which is something I don't want. Here is my code;
private void OnCollisionEnter2D(GameObject other) {
if(other.GameObject.tag == "platform") {
//Sets the rigidbody2D velocity as zero vector, angular drag and linear drag as 10f
game.SetBallVelocity(Vector2.zero, 10f, 10f)
}
}
How can I make OncollisionEnter2D only runs for single time? In another word, let the Ball really stick at the first time?
I don't have enough information to give you the exact answer but one of those should fix the problem:
1: Changing collision mode on the ball's rigidbody (test both Discrete and Continuous)
2: OnCollisionEnter2D is called before the physics calculations that change the ball's velocity, so use OnCollisionExit2D()
Quick side note, your IDE should have warned you of this but other.gameobject.CompareTag("platform") is faster than directly comparing the strings (other.GameObject.tag == "platform")
I've just started making a 2d physics based game but when I tried to set up a catapult thing to check some features I noticed the projectile started to slide off but when I turned up the friction it also turned up the air resistance, how do I increase friction without increasing air resistance?
In Unity, there are only two values that describe friction. Linear drag, and Angular drag.
Linear drag - describes how fast the object velocity is slowing down per tick
Angular drag - describes how fast the object rotation is slowing down per tick
I think you would need a little script to achieve different drags in different enviroments, pseudo-code would look like this
if(in_the_catapult)
{
// Set the rigidbody to high value to not slide off
rigidbody.drag = 100;
}
else if(touching_the_ground)
{
// Set the rigidbody to what the friction should be on the ground
rigidbody.drag = 2;
}
else if(in_the_air)
{
// Set the rigidbody to what the air resistant should be
rigidbody.drag = 0.1;
}
This code should run in Update to check every frame if the state has changed or it should be run on the event if the condition has changed because it's probable that your bullet will bounce off the ground multiple times.
My question is the same as the title. My player and enemies both move WAY faster when I build the game compared to when I play in the editor. I have looked online, but most forum pages say to multiply movement by Time.deltaTime, but for some reason, this doesn't work for me, because even when I re-build the game movement is way faster. If it helps, my character and enemies are both moved by Rigidbody2D.MovePosition. I think that I need to limit the framerate so that everything is slower, but I'm not sure. If you think I should, how would I go about doing that? Thanks in advance.
Both the enemies and player use this to move:
GetComponent<Rigidbody2D>().MovePosition(transform.position + move * speed * Time.deltaTime);
If it helps, "move" is a Vector3 coordinate and speed is set to 30 for the player character. I have clicked "build and run" every time after I made a change.
Is your code in FixedUpdate() or Update()? Physics code should be in FixedUpdate(). Note I changed Time.deltaTime to Time.fixedDeltaTime
void Update() {
//Your Non Physics Code
}
void FixedUpdate() {
//Your Physics code aka
GetComponent<Rigidbody2D>().MovePosition(transform.position + move * speed * Time.fixedDeltaTime);
}
I have a bullet that is fired with a Impuls on the rigidbody.
Then, each frame i do a raycast forward with the speed of the bullet, which sometimes does, and sometimes doesn't find an enemy.
When i skip through the game frame by frame, i can clearly see my debug-raycast inside the (boc)collider of the enemy, but it still won't find it.
Im pretty sure it doesn't just pass the enemy, in the editor i can clearly see the green raycast inside the collider.
Any suggestions? I also tried with a linecast, which i found on here, but that gives the same result. (the line is on the exact same position and also draws the debug-line inside the collider. The layers are also correct, as i said, sometimes it will, and sometimes it wont find the target...
void Update()
{
//get direction and distance
Vector3 direction = _rigidBody.velocity.normalized;
float distance = (_rigidBody.velocity.magnitude * Time.deltaTime);
//raycast for targets
RaycastHit raycast;
if (Physics.Raycast(transform.position, direction, out raycast, distance, HitLayerMask))
{
Debug.DrawRay(transform.position, direction, Color.red);
}
else
{
Debug.DrawRay(transform.position, direction, Color.green);
}
}
You can see the tiny debug ray, aswell als the collider from side-view. It also it almost right in the middle from the front-view.
I'm thinking it might be because the start and end of the raycast are inside the boxcollider?
the rigidbody is moved by
//Speed = 500 in this case, but lowering doesn't change anything
rigidBody.AddRelativeForce(Vector3.forward * Speed, ForceMode.Impulse);
UPDATE:
After some more debugging and testing, i found that it happens because you won't get a hit from inside a collider.
Here's what happend:
bullet is outside target collider, but raycast is to short to find it.
bullet moves forward, enemy also moves forward (closing in on eachother). Bullet is now inside the collider
raycast won't find enemy because thats just how raycast work
What i could do, is make the distance of the raycast further, but also not so far away that it would result in weird hits that would graphically look weird.
i thought that using
float distance = (_rigidBody.velocity.magnitude * Time.deltaTime);
would be enough (since thats the distance the bullet traveled since last frame, but because the enemy also moves, the above can happen. Well, it would be enough if the enemy wouldn't move :/
One possible solution is to go to Project Settings -> Script execution order and put the bullet's MonoBehavior after Default Time. That way everything else has already finished moving before you do the ray cast. A hacky solution but should work.
I am on my third day of learning Unity and are currently doing the roll-a-ball tutorial. I am trying to add a restart button, that teleports the ball back to the start-position/origin. It all works good, but the ball will keep moving after I restart, but I want it to stay in a spot and not move by itself.
What I mean is that if I'm moving left at max speed and press 'R' to restart, then it will keep moving left fast for some time, but what I want to achieve is that the ball would not keep moving by itself after I restart it's position (perhaps it's speed is just decreasing so slow that it's unnoticeable, in which case I'd want it to slow down faster).
Here's my code that I just tried out and "hoped" would work, but doesn't. I think that the problem I have here is that a new axisHorizontal/axisVertical variable value is assigned again the next frame, the value being taken from Input.GetAxis, which from what I have heard is not possible to change.
That means that a movementForce bigger than 0/0/0 and AddForce will be activated again the next frame.
using UnityEngine;
using System.Collections;
public class PlayerScript : MonoBehaviour {
public float movementSpeed = 7f;
private Rigidbody rigidSphere;
void Start() {
rigidSphere = GetComponent<Rigidbody>();
}
void FixedUpdate() {
float axisHorizontal = Input.GetAxis("Horizontal");
float axisVertical = Input.GetAxis("Vertical");
Vector3 movementForce = new Vector3(axisHorizontal, 0.0f, axisVertical);
rigidSphere.AddForce(movementForce * movementSpeed);
if (Input.GetKeyDown(KeyCode.R)) {
transform.position = new Vector3(0, 0, 0);
rigidSphere.AddForce(0, 0, 0);
axisHorizontal = 0;
axisVertical = 0;
}
}
}
I tried googling on how to change the value that is taken from GetAxis, but others claim it's impossible to do so. So I have really no idea how to make it not keep moving forever...
And I also got a 'bonus' question that has arised during those two days that I have been learning Unity, but they are not worth a seperate question, perhaps if they have been already answered before (I've been unable to find any documentation that'd help me on it), then just give me a link on where I could find the answer to my problem.
The question is that how do I make the ball stop moving after some time after I press a button (W/A/S/D, the default values for positive/negative buttons in Input Manager)? For example, I press 'W' just for a second, but the ball will keep moving forward forever and will never stop.
What I want to achieve is after I for example press 'W' for a second, after a few seconds the ball will completely stop, it just seems that the value from GetAxis never goes back to 0. I tried to google about it, and I think it's something to do with Gravity in the Input Manager - I tried changing it, but the ball will still keep moving forever, the only thing I noticed did change was the speed of the ball.
I'd be really grateful if someone could help me with these problems.
I am trying to add a restart button, that teleports the ball back to
the start-position/origin. It all works good, but the ball will keep
moving after I restart, but I want it to stay in a spot and not move
by itself.
I see that you tried to solve this by using rigidSphere.AddForce(0, 0, 0);. This will only add 0,0,0 to the existing force the ball is moving at. The solution to this is to set the Rigidbody velocity to 0.
Replace rigidSphere.AddForce(0, 0, 0); with rigidSphere.velocity = Vector3.zero;
Even when you do this, Input.GetAxis value increases and decreases over time before reaching 0. So, on the next frame, the ball might still be moving due to this.
To stop this, also replace Input.GetAxis with Input.GetAxisRaw.
Input.GetAxisRaw will immidiately return to 0 when the key is released.
What I want to achieve is after I for example press 'W' for a second,
after a few seconds the ball will completely stop, it just seems that
the value from GetAxis never goes back to 0.
Since the ball is rolling, you need to increase the angular drag of the ball. This will make the ball stop rolling after releasing the key. The angular drag is on the Rigidbody attached to the ball. Also increase the drag if that's not enough.