I have a labyrinth in my unity game, this game also has a red ball that is passing through the labyrinth, both have colliders (The ball circle colliders and the labyrinth edge colliders), it seems to work fine, but, when you drag the ball and push it into the labyrinth, passing some seconds, you can get through the colliders and pass, and, if you get enough speed, you can pass all the labyrinth like nothing!, I put in my script a speed limit (10) but it isn't working that well.
Your problem is FixedUpdate and using CollisionDetectionMode.Discrete.
It is called N counts per second, where N is a fixed value. Physics is calculated on FixedUpdate. Now imagine situation:
FixedUpdate is called 60 times per second. Time between FixedUpdate
calls is 1 second / 60 times = 17 ms (approx.)
Collider A size is
1x1x1, Collider B size is 1x1x1
Collider A attached to still object, Collider B attached to object moving towards Collider B with speed 90 units per second.
Physics engine is comparing position of A and
position of B on FixedUpdate It thinks that Collider B just
teleported through Collider A, because it's speed per one
FixedUpdate tick is larger, then collider's size.
If you are going to use very high speed, you have three options:
Try to follow Foggzie's advice
Increase count of FixedUpdates per second, and avoid overloading it with scripts.
Implement your own physics for high-speed objects
Unity deals with this problem through its Collision Detection Modes. Make sure your Rigidbody components have their collisionDetectionMode properties configured accordingly (they default to Discrete). It seems like you'll want the ball to use ContinuousDynamic and the labyrinth to be Continuous but note, as stated in the link:
Continuous Collision Detection is only supported for Rigidbodies with
Sphere-, Capsule- or BoxColliders.
You'll probably need to change the labyrinth colliders.
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.
Hey I am trying to make my sprite button go from green to red and backwards when my player collides with it. I have a boxcollider2d as is trigger, and a script
script : https://gyazo.com/ec64a2bca5b23526c6949bf18cb50a0d
I think this is some of it but I dont get anything at all when colliding with the button can anyone enlighten me on this problem would be very appreciated.
Thanks in advance
It is important to distinguish the difference between Colliders and Triggers.
Colliders are used by the Physics system in order to make it so object do not penetrate or overlap each other. Triggers on the other hand are made so that you can check for overlapping areas, an example is a Ring in Sonic. Sonic collects the rings but they do not stop him from passing, think of these as triggers. If they were colliders sonic would jump into them and bounce off.
In Unity the process for creating a trigger is the same for creating a collider, with 1 additional step, and that is marking a check box.
As such it is also important to know which functions you should use in each case.
OnCollision... For Colliders, (Or Colliders not marked as triggers)
OnTrigger... for Triggers, (Marking a collider in unity as a trigger makes it a trigger.)
To just add a bit more detail, It is also important to use the correct collider types for the correct dimensions of the game, 2d Colliders/Triggers do not interact with 3d Colliders/Triggers. More so physics components: 2d Rigidbodies do not works with 3d colliders, and 3d rigidbodies do not work with 2d colliders/triggers.
As such there are functions for each 2d, 3d, collision, and trigger.
Another important factor is to ensure if you want to use these functions atleast one of the objects have to have a rigidbody of the correct type(2d or 3d).
As such the problem you were running into was using OnCollisionEnter2D for a "collider" that was marked as a trigger, in this case OnCollisionEnter2D is not called, but OnTriggerEnter2D is called.
I'm making a game (similar to Subway Surfers), and I have a floor made of many small cubes. And I want to make my game do something when the player stops colliding with the floor. But when I use OnTriggerExit (Collider other) I never know if the player stops colliding the floor or just moves from one piece of the floor to another:
OnTriggerExit (Collider other){
if (other.tag == "floor") {
if(/*Object isn't coliding with any other object with the tag "floor" (Or simply isn't coliding with the other piece of the floor) */){
//Do something
}
}
}
It depends on the needs of the game. Since you named Subway Surfer, I would go with the z-coordinate of the player.
I would add the heightFromGround field to the player class (calculated as the difference on the z-axis between the player and the platform underneath).
Then, if heightFromGround is higher than a threshold, you know the player is jumping.
This also allows you to control the Animation of the character based on it's height from the ground (so he can prepare to land) and transition to the running state.
To have different platforms at different heights, you need to know the platform currently underneath the player at runtime.
This is just an approach to avoid collision checking.
If you don't need that level of control on Animations and prefer to keep using collisions, you can simply add a field int touchingPlatforms = 1; and add 1 to it OnCollisionEnter, subtract 1 from it OnCollisionExit. The player is jumping if touchingPlatforms is 0.
I've got a coin RigidBody and walls around it with box colliders. For trial purpose I've applied the following code to the coin.
private void OnMouseDown()
{
rigidbody.AddForce(30.0f, 0f, 5.0f, ForceMode.Impulse);
}
But, sometimes the coin passes through the walls, but when I increase the speed from 30 to 50 points it passes through the walls on the first click. I've googled a lot and still got nothing except for the DontGoThroughThings Script which doesn't work for me or I don't really know how to use it.
I've always added a continuous dynamic on the coin and continuous collision detection on the walls but still doesn't work.
the problem with physics collision detection is that sometimes when the speed of an object is too high (in this case as a result of a force added to the rigid body) the collision wont be detected. The reason is that the code you are executing is running at x ammount of steps per seconds so sometimes the rigidbody will go through the collider between one step to another. Lets say you have a ball at 100 miles per hour and a wall that is 1 feet wide, the code will move the ball a determined ammount of feets everytime the code is runned according the physics of it, so the movement of the ball is virtualized but its not a real physical movement so it can happen that from one step to another the ball can move from point a to b and the wall is between those points and as a result the collision will not be detected.
Possible Solutions.
You have a simple solution that wont be as accurate as it should be and a harder one that will be perfectly accurate.
The solution number one will be increasing the colliders size, according to the max speed your coin can get, that way the collider will be big enough so that the collision wont be missed between one frame to another.
The second and harder solution will be adding an auxiliar to your collision detection, some kind of a security check. For example using physical raycast. You can set a raycast to forward direction and determine if that object is an inminent collision, if it does and once the object isnt being collided by the raycast anymore then your collision detection had failed that way you have your auxiliar to confirm that and call the collision state.
I hope it helped and sorry about my english. If you didnt understound it very much i could help you with code but i will need some code from your project.
See if the colliders have their 'Is Trigger' unchecked.
Also, check if the gameObjects have colliders.
I have faced this problem many times..
Make sure Your coin's Rigidbody has "Is Kinamatic" False, Is Triggger:false,
And also "Is Trigger" of walls is False.
You could save the velocity and position on each update and then test for out of bounds, if the coin leaves the valid area you can restore it at the last valid position or plot the collision yourself if you want to