Unity2D: Making kinematic player collide with tilemap collider - unity3d

I am working on a 2D game with a Grid with 2 tilemaps in it. The walkable tilemap and the obstacles tilemap. I gave the obstacle tilemap the tilemapcollider2d. I want my player to have a kinematic rigidbody so physics won't do weird things after colliding with the obstacle tiles.
The thing is, the player only collides with the obstacle tiles if it has a dynamic rigidbody. How can I make the player collide with the obstacle tiles, while having a kinematic rigidbody?
I also tried adding a rigidbody2d to the obstacles tilemap but this doesn't have any effect. Unless it's set to dynamic, then all the obstacle tiles start falling down but do collide with the player for a moment before the player clips through it.
This the code for the movement of my player (body = the RigidBody2D of the player):
void Update()
{
// Gives a value between -1 and 1
horizontal = Input.GetAxisRaw("Horizontal"); // -1 is left
vertical = Input.GetAxisRaw("Vertical"); // -1 is down
}
void FixedUpdate()
{
if (horizontal != 0 && vertical != 0) // Check for diagonal movement
{
// limit movement speed diagonally, so you move at 70% speed
horizontal *= moveLimiter;
vertical *= moveLimiter;
}
body.velocity = new Vector2(horizontal * Speed, vertical * Speed);
}
Thanks in advance!

Change Contact Pairs Mode to Enable Kinematic Static Pairs, them handle the collision in OnCollisionEnter2D

I guess you just want the player to stop when he hits the obstacle tile-map
Solution :
Add box Collider 2D for both player and the obstacle tile-map
If you want to detect collision try using trigger

Related

Increase size of touch area - Unity

private void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
With this code I can touch the point on the screen but when I catch my balls on the screen sometimes i can't because they are too fast.
So can i take the point of click and enlarge this point ?
You can use a 2D or 3D Sphere collider and attach it to Empty gameobject , move that game object towards touch points on screen and use OnCollisionEnter2D() or OnCollisionEnter3D() event to detect detections with falling balls. Now the sphere collider is as a whole a point and its radius can altered in inspector to enlarge the points
More about On Collision Event : https://docs.unity3d.com/ScriptReference/Collider.OnCollisionEnter.html
Here's what worked for me:
Before (Inspector View):
BallGameObject
- Rigidbody
- Script that listens to OnMouseDown
After (Inspector View):
BallGameObject
- Rigidbody
- TouchDetectGameObject
- Circle Collider 2d (**Use a Sphere collider if you're in 3d!)
- Radius: 5
- Script that listens to OnMouseDown
Basically, add a child object with no material so it's invisible and its own Circle Collider + OnMouse listeners. Make the child object bigger than the parent. With no other changes, I can now click on my Ball even if I'm off to the side a bit with my touch.

Using Unity Physics to consistently bounce a ball to the same height

My ball can only bounce on the y axis. X and Z movement as well as all rotation are locked in the rigidbody component. Originally I was planning to handle this using a combination of the two methods below. I'm adding my own faux-gravity to the object in FixedUpdate and bouncing the ball upwards when it collides with a platform in OnCollisionEnter. Esentially sending it bouncing up and down forever.
void OnCollisionEnter(Collision collision)
{
ball.AddForce(Vector3.up * force, ForceMode.Impulse);
}
void FixedUpdate()
{
Vector3 gravity = globalGravity * Vector3.up;
ball.AddForce(gravity, ForceMode.Acceleration);
}
The problem is that if I place an angled platform under the ball, it no longer bounces vertically with the same force. I believe this is because Unity Physics is calculating the angle/force the object should bounce in a 3D space, and then because of my script only applying the upward force of that calculation. However, I'd like my ball to bounce with a consistent vertical force regardless of the angle of the platform placed under it.
This could be achieved using a coroutine and Lerp to a certain height, which I tried using the script below, using Physics gravity this time, but it didn't have the same natural bouncing feel as Unity Physics. I'd like to go back to using the Physics system but I don't know how to stop Unity from doing the angular calculation and just launch my ball vertically with the force I want.
IEnumerator MoveBall(Vector2 newPos, float time)
{
ball.useGravity = false;
float elapsedTime = 0;
Vector2 startingPos = transform.position;
while (elapsedTime < time)
{
transform.position = Vector2.Lerp(startingPos, newPos, (elapsedTime / time));
elapsedTime += Time.deltaTime;
yield return null;
}
ball.useGravity = true;
}
It sounds like you want your collider to be setup as a trigger. On your ball's collider, set isTrigger to true and then use OnTriggerEnter instead of OnCollisionEnter. This will prevent Unity's physics engine from creating and resolving a Collision between the ball and whatever it hits.
If you'd also want the ball to bounce off other objects in way that uses Unity's Physics, you'll need to then get creative with which colliders are/arent' triggers, and which physics layers they belong to.

unity2D Moving to a fixed object causes weightlessness

Please look at the photo. There are two objects.
left circle object = circle colider2D + rigidbody2D(freeze Rotation Z, script for move )
Rigidbody2D rigid;
float moveX;
void Start()
{
rigid = gameObject.GetComponent<Rigidbody2D>();
}
void PlayerMove(){
moveX = Input.GetAxisRaw("Horizontal");
rigid.velocity = new Vector2(moveX * 5f, rigid.velocity.y);
}
void Update(){
PlayerMove();
}
right square object = square colider2D + rigidbody2D(freeze positionY, freeze positionX, freeze Rotation Z)
I can move the circle from side to side.
While I press the keyboard and push the circle to the right wall, gravity doesn't work.
I don't know why. I hope gravity will work even if the circle hit the wall.
How can I prevent the problem?
Looks like physics material that's applied to that rigidbody has too much friction and slows down too much when hugging the wall. Try reducing friction value on the material (you can create the physics2D material from the assets panel).

Sprite character slides back when near edge of other collider

I am making a 2D game in Unity. I have added a 2D box collider and a circle collider as trigger on my sprite character. The platform on which the character is standing also have a 2D box collider. So, when my character moves near edge of platform, it experiences a force or something that pulls it away from the edge. You can think it as a protective force that helps your character not falling down the plane but the problem is that this force is not part of game and that's why it should not be there. Following is the code I am using to move my character:
// call this method to move the player
void Move(float h)
{
// reduces character velocity to zero by applying force in opposite direction
if(h==0)
{
rigidBody.AddForce(new Vector2(-rigidBody.velocity.x * 20, 0.0f));
}
// controls velocity of character
if(rigidBody.velocity.x < -topSpeed || rigidBody.velocity.x > topSpeed)
{
return;
}
Vector2 movement = new Vector2 (h, 0.0f);
rigidBody.AddForce (movement * speed * Time.deltaTime);
}
Here is image of properties.
If I keep pushing the character it will fall off the edge but if I stop just by edge the unwanted protective force pulls it back on plane.
Also, if the character bumps into another 2D box collider, it bounces back instead of just falling down.
EDIT- Bouncing effect arises mostly when player bump into other objects while jumping. Code for jumping is
void Update()
{
// The player is grounded if a linecast to the groundcheck position hits anything on the ground layer.
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
// If the jump button is pressed and the player is grounded then the player should jump.
if(Input.GetButtonDown("Jump") && grounded)
jump = true;
}
void Jump()
{
if (jump)
{
jump = false;
rigidBody.AddForce (Vector2.up * jumpSpeed * Time.deltaTime);
}
}
The problem lies in how you're implementing the "drag" force that slows your player down to zero. Because game physics happens in steps rather than continuously, your opposing force can overshoot and briefly cause the character to move in the opposite direction.
In this situation your best bet is to multiply your speed by some fraction each frame (likely between 0.8 and 0.95), or to use Mathf.Lerp to move your X velocity towards zero.
rigidbody.velocity += Vector2.right * rigidbody.velocity.x * -0.1f;
OR
Vector3 vel = rigidbody.velocity; //Can't modify rigidbody.velocity.x directly
vel.x = Mathf.Lerp(vel.x, 0, slowRate * Time.deltaTime);
rigidbody.velocity = vel;
Also give some thought to doing your movement/physics related code within FixedUpdate() instead of Update() and using Time.fixedDeltaTime instead of Time.deltaTime. This will allow for more consistent results independent of framerate.

Move Object by dragging (mobile) makes the balls fall from the cup

I have this cup that contains balls inside. All 2D
I am using Rigidbody2d and Collider2d.
When running in unity and moving the cup (with arrow keys) the balls stay inside the cup. I also added drag movement for Android touch to move the cup.
The problem is that when moving the cup too fast (by draging) the balls fall from the cup collider (using Polygon colider 2d).
Code for movement is:
public float speed = 0.1F;
void Update() {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(-touchDeltaPosition.x * speed, -touchDeltaPosition.y * speed, 0);
}
}
I tried to play with the speed parameter but it wont really help. if the cup movement is too slow it is not very useful for me.
I believe it is related the velocity/force of the ball or cup which makes the cup collider miss...
Any help on this would be appreciated greatly!
it is because you are moving it by changing the position of the cup, that means that when you move it fast, it disappears, and reappears where you dragged it, leaving the balls behind, and then they fall. I had the same thing where my objects would just go through the walls and out of the camera area. I fixed that by using AddForce. This makes the cup move, position by position over to where you dragged. this bumps the balls along, and they stay in the cup. This is what I guess is going on. If you use velocity that would work to.
you could rather than transform.Translate, you could find the vector to where you want to move to.
var direction = touchDeltaPosition - transform.position;
gameObject.rigidbody2D.velocity.x = direction.x * speed;
gameObject.rigidbody2D.velocity.y = direction.y * speed;
hope this solves it
The problem is that, when you're moving the cup too fast, at Frame 1 the ball is inside the cup, but at Frame 2 it's outside. You can reduce the value of "Fixed Timestep" (http://docs.unity3d.com/Manual/class-TimeManager.html) to increase the frequency of the physics calculations, or make the colliders larger.
If a ball in the cup will always stay in the cup, maybe you can turn off the physics of the ball once it's in the cup, or something along those lines.
Usually transform.Translate() is not very efficient when dealing with colliders, instead, you can try three other solutions:
1) rigidbody2D.AddForce(Vector2.Up * Input.GetAxis("Vertical"));
2) rigidbody2D.velocity = new Vector2(//write what you need);
3) which I consider the best solution for dealing with colliders and dragging is : MoveRigidbody2D
Well, this is what worked for me:
var newVec = new Vector2 (transform.position.x, transform.position.y);
var touchDeltaPosition = Input.GetTouch(0).deltaPosition*touchSpeed;
var direction = touchDeltaPosition- newVec;
rigidbody2D.AddForce(direction);