I have the following setup:
A ball object that has a CircleCollider 2d with a frictionless, full-bounce (1) material. The collider is not a trigger. It also has a rigidbody2d on it, with no gravity, some mass, Continuous collision detection and Interpolate set to Interpolate. It also has a script with this code:
Rigidbody2D rb;
private void Awake() {
rb = GetComponent<Rigidbody2D>();
}
Vector2 lastVelocity;
private void FixedUpdate() {
lastVelocity = rb.velocity;
}
private void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Block" && isPiercing) {
rb.velocity = lastVelocity;
}
}
A few Block objects that have a Box Collider 2d on them (also not set to be triggers), nothing else.
The idea is, if I have the isPiercing property set on the ball, it should pass through. Otherwise, it should use default behaviour and the ball should bounce off the blocks as normal (which it does fine).
What actually happens is, there's some 'jitter'; as soon as the ball hits the block, it looks like it back-tracks on its path slightly. It still passes through; just it looks like it hit a speed bump along the way.
Do I need to move the ball forwards along its path when it enters the collision to make up for the bounce it's about to do (or is in the process of doing)?
Maybe get a clip of what's going wrong, but from what I can see, when the ball hits a block with piercing, then you're setting its velocity to its FixedUpdate() velocity. I don't know why you're doing this, but FixedUpdate() is calculated before unity does its physics calculations. I'm not sure, but it seems as if this may move the ball back slightly, like you are saying.
My suggestion would be to not set its current velocity to its FixedUpdate velocity.
Hope this works!
Related
I am making a game in Unity 2D and i wanted the bullet the player shoots from his gun to bounce after it hits a wall. The script i made for the bullet is this:
public float speed = 40f;
public Rigidbody2D rb;
private Vector2 direction;
public void Start()
{
rb.velocity = transform.right * speed;
}
private void OnCollisionEnter2D(Collision2D collision)
{
Vector2 inNormal = collision.contacts[0].normal;
direction = Vector2.Reflect(rb.velocity, inNormal);
rb.velocity = direction * speed;
}
I put a 2D physics material on the colliders which has 1.15 friction and 0.1 bounciness to make the ball bounce (as it wouldn't bounce before without the material) but now the ball bounces off the wall with a different speed every time I shoot it. Sometimes the speed of the bullet is so high it passes through the wall and that is not intended at all. Instead I wanted the ball to bounce with the same speed from wall to wall, but I don't know how to fix this problem. Can someone help me?
You don't need this onCollision part of code to have it bounce, thats a point of having rigidbody, collider and material. unity does calculations for you.
Make bullet dynamic body, if it moves too fast to detect colision change Collision detection" in Rigidbody(on wall but perhapsalso on bullet) from discrete to continous.
And it should bounce.
If angle and speed is always the same result will also always be the same.
I suspect you have wieird results becouse you are ovverriding actual colision.
I'm making a game in which I have to transform the players position after he completes the objective, but when I transform him, he's stuck in the air on the new transform position, even though I have a Rigibody2D set on it with a gravity scale of 2. When I move him manually by dragging and releasing, he falls to the ground normally. I'm fairly new so any help would be appreciated. I can't seem to identify the problem.
Here's the code,
public GameObject player;
public Transform nextPart;
public Camera cam;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (PlayerController.canTransform)
{
player.transform.position = nextPart.position;
cam.transform.position = new Vector3(nextPart.position.x, nextPart.position.y, -10);
}
}
Here's a picture too,
Your code is within the Update function. This means that so long as canTransform is true your player will be placed at that transform every frame.
You need to set that boolean back to false after moving your player or have some other check to ensure you don't move to that position more than once.
It might be better to instead have the player set to that position in a separate function and simply call it one time when you reaches that objective.
I'm trying my first test-game with Unity, and struggling to get my bullets to move.
I have a prefab called "Bullet", with a RigidBody component, with these properties:
Mass: 1
Drag: 0
Angular drag: 0,1
Use grav: 0
Is Kinematic: 0
Interpolate: None
Coll. Detection: Discrete
On the bullet prefab, I have this script:
public float thrust = 10;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.AddForce(transform.forward * 100, ForceMode.Impulse);
}
On my playerController script (not the best place for this, I know):
if (Input.GetAxisRaw("Fire1") > 0)
{
var proj = Instantiate(projectile, transform.position, Quaternion.identity);
}
When I click my mouse, the bullet gets created, but doesn't move. I've added velocity to the rigidbody, which works, but I can't get it to move in the right direction. After googling around, it seems I need to be using rigidBody.AddForce(), which I did, but still can't get my bullet to move.
I've seen the other solution, but this did not work for me either.
Any advice would be appreciated.
Screenshot:
When you're working with 2D in Unity, the main camera basically becomes an orthographic camera (no perspective effects) looking sideways at the game scene along the z-axis. Incidentally, the "forward" direction of a non-rotated object is also parallel to the z-axis.
This means that when you apply a force along transform.forward, you're sending the object down the z-axis - which will not be visible to an orthographic camera looking in the same direction. The quick fix here would be to use a direction that translates to an x/y-axis movement, like transform.up or transform.right.
As derHugo also mentioned in the comments, you might want to look into using Rigidbody2D. There are some optimizations that will allow it to behave better for a 2D game (though you may not notice them until you scale up the number of objects).
I have a small piece of code to make a sprite (in a 3D world) always face the camera (It has to be in 3D space).
public class CS_CameraFacingBillboard : MonoBehaviour {
private Camera m_Camera;
private void Start()
{
m_Camera = Camera.main;
}
void Update()
{
transform.LookAt(transform.position + m_Camera.transform.rotation *
Vector3.forward, m_Camera.transform.rotation * Vector3.up);
}
}
This code ensures the sprite is always facing the camera, causing it to lean backwards as the camera in above the sprite facing down in a 45 degree agle. When I put a rigidbody on the sprite, the sprite moves on its own towards the direction its leaning. The rigidbody works fine without this code attached.
How can I have a sprite that always faces the camera, and has a rigidbody attached?
It seems you've left the rigidbody as Dynamic, you should set it to Kinematic.
EDIT: After you comments, I checked myself inside Unity, and probably I've recreated the behaviour you described. It happens to me too IF I use a Box Collider on the sprite without locking its rigidbody rotation.
So you have three possible solutions:
Use a Box Collider and under Constraints of the rigidbody freeze the rotation:
Use a Sphere Collider (or another one that doesn't behave like the box one, you can check them out in play mode).
Split the components over two game object, a parent and a child. The parent will have all the components except the sprite renderer and the camera script, which will be on the child. This option is the most flexible and less restraining. You can have the box collider without freezing rotations, etc.
Another thing, you can avoid the use of the LookAt method, by simply using:
transform.rotation = m_Camera.transform.rotation;
they have the same outcome.
I'm trying to implement this tutorial on the unity site. I've went over the unity blog and havn't found the solution to my problem there.
I have a simple Rigidbody sphere object over a plane.
The sphere is default sized, and set on: (0,0.5,0).
The plane is also default sized, and set on the origin (0,0,0). Those are the only components I use.
What I'm trying to do is to write a simple C# script behavior for the sphere that will move it across the plane, like so:
public class Controller : MonoBehaviour {
private Rigidbody rb; // Holds the body this script is affecting.
// Called at the start, to set variables.
void Start()
{
rb = GetComponent<Rigidbody>(); // Get the body, if there is one.
}
//For physical changes.
void FixedUpdate()
{
float Horizontal = Input.GetAxis ("Horizontal"); // Get horizontal movement from input.
float Vertical = Input.GetAxis ("Vertical"); // Get vertical movement from input.
Vector3 Movement = new Vector3 (Horizontal, 0.0f, Vertical); // Declaring the movement I'd like to add to the RB. Y axis is irrelevant. X,Z - controlled by user input.
rb.AddForce (Movement); // Making the movement.
}
}
I attached this behavior to the sphere, expecting It'd move when I hit some input key.
Despite this, when I play the project, everything compiles fairly well but the sphere just doesn't move regardless of what I type.
What am I missing?
EDIT: If it's relevant, I also have problems opening the Unity c# code editor (forgot it's name). Whhenever I click open, it just instantly closes. I do everything on Visual Studio.
EDIT 2: My bad, I just figured out I have console Errors. I get the following one:
MissingComponentException: There is no 'Rigidbody' attached to the "Player" game object, but a script is trying to access it.
You probably need to add a Rigidbody to the game object "Player". Or your script needs to check if the component is attached before using it.
UnityEngine.Rigidbody.AddForce (Vector3 force) (at C:/buildslave/unity/build/artifacts/generated/common/modules/NewDynamics.gen.cs:706)
Controller.FixedUpdate () (at Assets/_Scripts/Controller.cs:20)
"Player" is the name I gave the sphere.
I forgot to attach the Rigidbody to the sphere.