I am using Farseer Physics Engine to build a "Monster Dash" like game targeted for the PC using C# and XNA,
I am trying to move a body with it's texture, the texture is built from parts so they all should move together, basically it looks like this:
public void Update()
{
tilingFloorPosition.X += (floorMoveSpeed / MeterInPixels);
_tilingFloorBody.Position = tilingFloorPosition;
// Update the textures position
for (int i = 0; i < texturePositions.Length; i++)
{
texturePositions[i].X += floorMoveSpeed;
}
}
But whenever my player lands on top of the floor he just goes through it like there is nothing there, what am I doing wrong?
If the player is falling through the floor then I can only assume that either the floor's body isn't actually in position, or the two bodies are not colliding. Can you confirm that the floor is indeed positioned correctly? If you're able, turn on the Farseer Debug View. If so, then the collision must not be occurring.
Check:
That both the player and the floor are not sensors.
That they are not within the same CollisionCategory and at least one of them is included within the others CollidesWithCategory.
That you have not added one of the bodies to the others IgnoreBody list.
That the body types will collide. See: Farseeer Body Types.
Also, it may be worth noting that it is possible that manually setting the position could skip the collision. Try instead setting the LinearVelocity.
Related
In my 2D side-scrolling game I move my character using the built-in physics engine by manipulating the rigidbody.velocity.
I would like to add some sort of dodge (roll) ability, where the character moves 3 units in its direction.
Here is the code I used:
void FixedUpdate() {
if (Input.GetKeyDown(KeyCode.A) ) {
Vector2 pos = rb.position;
pos.x -= 5;
rb.MovePosition (pos);
}
}
This method works but the character kind of jumps to the position rather than moving to it (Lerping?) and also doesn't detect collisions despite the body type being dynamic.
Then I tried this:
if (Input.GetKeyDown(KeyCode.A)) {
rb.AddForce(new Vector2(-50, 0));
}
I found the AddForce way isn't accurate at all.
Is there a proper way of doing this?
Maybe you could change the Transform.pos inside Vector2.Lerp to make it look smooth? (Sorry, not enough experience with 2D in unity.)
Just increase rigibody.velocity for a set time. Your chararter object could then play a fitting aniamtion. If The player should not be able to cancle midrole jsut block the controls for that time.
I'm doing a AI using the NavMesh pathfinding solutions, and I don't to want to use a NavMeshAgent because of some limitations (like teleporting when a carved object comes close, etc.),
Thus I made a sort of fusion, moving a Rigidbody on the path of NavMesh.CalculatePath(), this is working quite good so far, but I have trouble detecting the OffMeshLinks on my path (because it's just an array of Vector3).
I can "trick" a bit using NavMesh.Raycast() like above, but it's not working all the time and sometimes detecting OffMeshLinks that aren't one
NavMeshHit hit;
//Raycast between two corners of a path, because OffMeshLink are most of the time over a hole
if (NavMesh.Raycast(_pathCorners[0], _pathCorners[1], out hit, NavMesh.AllAreas))
{
//If the hit position is really close to the corner, it's surely a offmeshlink generate from the NavMesh
//Or if the second corner is higher than the first one, it's surely a offmeshlink I generate myself
if ((hit.position - _pathCorners[0]).sqrMagnitude < 1
|| _pathCorners[0].y < _pathCorners[1].y)
{
ActivateJump(_pathCorners[0], _pathCorners[1]);
}
}
Thanks in advance :)
I've tried asking this question on the Unity answers site, but since I've yet to receive an answer I figured I'd ask this question here as well. I am trying to make a 3D version of the game "Snake", but I am running into serious problems trying to make the first snake segment follow the head of the snake. The GameObjects I am using are spheres with rigidbody components, with the player having control only over the "head" of the snake. Then, as the snake grows, more spheres are added that should follow the path that the main sphere makes.
I would like to know if there is either a more elegant solution to what I am trying to achieve, or at least a little help into what I may do to fix the current implementation. I am attaching the code of the segment that is supposed to follow the head. The naming for the objects are in Spanish, but it may not be that hard to figure out what is going on from a non-Spanish speaking person's perspective.
I have also properly commented the code, so that you can understand what I am doing at each sentence. The main idea that partially works right now is to send the snake segments information about where exactly the head made a turn so that when the segments get to a particular turning point, they can make a turn in the direction the head turned. The problem I have is that sometimes the segment travels past by the point where it should make a turn, and I don't understand if it is because of precision problems (I am making float comparisons to determine if a segment has reached a certain position where it turns) or if it's something else.
using UnityEngine;
using System.Collections.Generic;
using Clases;
public class ControladorSegmento : MonoBehaviour {
//This is a generic list of Objects that store both turning position and turning direction that the head has made
public List<PosicionCambioDireccion> listaPosicionesCambioDireccion;
//This would be the head in the case of only one segment that is following
public GameObject lider;
//Speed
public float rapidez;
//Direction
public Vector3 direccion;
//This is an index that is used to iterate over the list of turning points
private int indiceCambioDireccion;
// Use this for initialization
void Start () {
indiceCambioDireccion = 0;
listaPosicionesCambioDireccion = new List<PosicionCambioDireccion>();
//First find the Head of the snake so that we can access its position in order to determine segment spawning position
lider = GameObject.Find("Cabeza");
//Set the position of the new segment 2 units right behind the head
transform.position = lider.GetComponent<Transform>().position - lider.GetComponent<ControladorCabeza>().direccion * 2f;
//Get the current direction of the head so that the segment inmediately moves in its direction
direccion = lider.GetComponent<ControladorCabeza>().direccion;
}
void LateUpdate () {
//Check if there has been a change in direction that the segment has to follow
if ((listaPosicionesCambioDireccion.Count > 0) && (listaPosicionesCambioDireccion.Count > indiceCambioDireccion)) {
//Compare how close we are to the turning position. If we are sufficiently close, change segment direction
if (Mathf.Abs(transform.position.x - listaPosicionesCambioDireccion[indiceCambioDireccion].posicion.x) < 0.0999999 &&
Mathf.Abs(transform.position.z - listaPosicionesCambioDireccion[indiceCambioDireccion].posicion.z) < 0.0999999) {
//Change segment direction at the current position
direccion = listaPosicionesCambioDireccion[indiceCambioDireccion].direccion;
//Increment turning positions list index so that we get the next turning point in the list (if there is any)
indiceCambioDireccion++;
}
}
}
void FixedUpdate() {
//Change the velocity
GetComponent<Rigidbody>().velocity = direccion * rapidez;
}
}
I am still really new working with Unity and it seems I have still much to learn. And again, if you have a more elegant solution to what I am trying to achieve, please let me know. Right know I am aware that this implementation could cause a sort of memory leak in the sense that, as long as the head keeps changing direction, the list of turning points that is stored is going to keep growing and growing which obviously is something one should avoid.
You may record each segment's position in last frame in a list(include head), at the next frame, create a vector from the current position of the head segment to the last position recorded last frame. Then step the distance of the sum of both head & first segment's radius from the current position of the head, and place your first segment there. Repeat these steps for all other segments consist your snake. Hope this can help you.
My Problem can be seen through this video..
You will be able to see in the link above that until I move rod down every thing works well but as soon as I move down the burger gets stuck in the rod. Help me I want it to just deflect off the surface. Something like ping pong game....
For deflection I used the following snippet of code.
foreach (Bar rod in bar)
{
if(rod.CollisionRectangle.Intersects(GameBall.CollisionRectangle))
{
GameBall.speed *= -1;
Console.WriteLine("game" + GameBall.speed);
}
}
Here gameball refers to the burger and rod refers to the images at the top and the bottom.
What seems to be happening is that the rod is overlapping the ball more than the ball is moving in one frame. In other words, if the ball is moving 3 pixels per frame but the objects are overlapping by 5 pixels they won't be able to come out of collision by simply changing direction. You'll need to actually move the ball out of collision first.
That said, collision detection and response is always tricky code to write. The key is to separate the detection code from the response code.
In other words. For every frame:
Detect all collisions
Move all objects
What you're doing now is moving things during the detection phase. That's going to lead to trouble when 2 objects are moving towards each other.
There's way more material on this subject than I can fit into an answer. I suggest looking around for tutorials on AABB collision detection.
Is your CollisionRectangle the built in Rectangle class in MonoGame/XNA?
Assuming it is and the loop is in Update, maybe you could try inserting a break so that it'll stop updating the gameball speed immediately after the first change. This is because the game is updated 60 times per second, there condition might be true for a few miliseconds or so when the game is updating.
foreach (Bar rod in bar)
{
if(rod.CollisionRectangle.Intersects(GameBall.CollisionRectangle))
{
GameBall.speed *= -1;
Console.WriteLine("game" + GameBall.speed);
break;
}
}
Let me know if it doesn't work and maybe i can try it in a new project when i'm free.
When the ball intersect with the bar, you change the direction but the collision is still here so maybe you can try this:
foreach (Bar rod in bar)
{
if(rod.CollisionRectangle.Intersects(GameBall.CollisionRectangle))
{
GameBall.speed *= -1;
// Reset position of the ball
// Something like :
// For the top bar
Gameball.y = rod.y + rod.height;
// For the bottom bar
// Gameball.y = rod.y - Gameball.height
Console.WriteLine("game" + GameBall.speed);
}
}
I am a begginer. I am using Monogame and Farseer Physics Library in C#. (latest versions)
In my game, whenever my ball (circle) hits the corner of a rectangle, (or even another circle), it is supposed to only change direction on the Y-Axis.
However, it does not only change direction on the Y-Axis, (as intended), but it also moves a small amount to the right as well (or the left accordingly), depending on how you hit the corner (or another circle). It is as if some force is being put on the ball, making it move on X-Axis as well.
This movement is cool and all, and it makes a lot of sense, but in my game, it does not, therefore i want to get rid of it.
How is this possible ? I am guessing i have to change some default values.
This what my coding looks like:
BallBody.BodyType = BodyType.Dynamic;
BlockBody.BodyType = BodyType.Static;
Ball.LinearVelocity = new Vector(0,-1); // ball going up
BallBody.OnCollision += Ball_OnCollision;
public bool Ball_OnCollision(Fixture f1, Fixture f2, Contact contact)
{
// if the Ball (f1), collides with the Block (f2)
if (f2.Body == BlockBody)
// change the direction of the Ball on Y-Axis
Ball.LinearVelocity = new Vector(0,-1);
return true;
}
Also with high speeds, this occurs:
Even though the ball is never able to pass through the Block (tunneling), I want to know how could i possible fix that so that the ball never enters the Block area ?
Unfortunately, this is surprisingly difficult to do with Box2D. The best I could manage when I tried, was to record the velocity of the ball when the contact started, and then when the contact ends, manually set the velocity to what I wanted. That works fine when the ball only begins and end contact with one block at a time, but in some cases the ball can begin touching two blocks in the same time step. You would have to look at the arrangement of the blocks it touched, and calculate for yourself what angle you would expect it to bounce away at. Eventually I just gave up and did not bother to cover that case.