I am playing around with Unity3D and adding physics to the objects in my scene. I currently have a sphere (planet) in the center of the screen, and I have another sphere (moon) positioned outside of it that is not moving. When I run the game I want the moon to orbit the planet by applying a force to it. I have been able to get the force added by calling rigidbody.AddForce() and that will move it in the specified direction but it won't orbit. I'm not sure how to add force to it so that it will continuously orbit the sphere at a constant velocity.
I've tried some examples using a ConfigurableJoint and it orbits, but it starts out bouncing a little and then starts the orbit. My goal is to have a bunch of orbiting moons orbiting at their own speed that are able to bounce off eachother but not lose their velocity.
Any ideas?
Generally speaking you will fail, eventually, because rounding errors in your integration method will slowly throw you out of orbit. You can get very close in the ways suggested, but you could consider doing something more like the Kerbal Space Program, which seems to precalculate the orbit as an ellipse and then follow that ellipse until it has a reason to believe it should stop, rather than strictly "simulating" the orbit ...
If a collision occurs, allow normal physics to resolve the collision, and then recalculate your new orbit based on the result and start following that.
For the moon to orbit you would need to give the moon an initial velocity. Then have it accelerate towards the planet, that is a constant force.
gameObject.rigidbody.AddForce(1, 0, 0);
gameObject.constantForce.relativeForce = Vector3(0, 1, 0);
Related
I'm currently trying to make a game to put my relatively new coding knowledge to test. I figured I learn a lot quicker by just doing things and seeing what happens. I'm currently working on a plane and the last couple of days I made a functional camera system (to rotate around the player based on the mouse) and some animations of the plane. I'm currently trying to create a movement system in which the down key rotates the player up. I noticed however that my AddForce function doesn't do what I want it to do. I'd like the plane to move in the Z axis depending on the current rotation of said plane instead of it just heading into the Z angle of the world.
I'm currently working on this snippet:
//Acceleration
if (gameObject.CompareTag("Player") && playerRb.velocity.z > -349)
{
playerRb.AddRelativeForce(0, 0, -playerSpeed, ForceMode.Acceleration);
}
else if (gameObject.CompareTag("Player") && playerRb.velocity.z < -349)
{
playerRb.velocity = new Vector3(playerRb.velocity.x, playerRb.velocity.y, -350);
}
//
//Movement
//Up/down controls
if (gameObject.CompareTag("Player") && Input.GetKey(KeyCode.DownArrow))
{
transform.Rotate((0.07f * playerSpeed) * Time.deltaTime, 0, 0);
}
As you can see I already tried AddRelativeForce as another topic mentioned but that doesn't seem to work for me. The moment it hits an edge it just falls down into the abyss regardless of it's rotation.
Additionally, I was considering using another AddForce function on the rotate as it doesn't leave the ground (considering it keeps hitting the floor with its tail), is there any way to apply a force on an object from a specific position/angle? (such as the front of the plane).
Thanks in advance!
I think the reason your plane is acting strange is not because of your addrelative force call -- it's because you are setting velocity. playerRb.velocity = new Vector3(playerRb.velocity.x, playerRb.velocity.y, -350); assigns the velocity to push you -350 in the world's z axis, which probably isn't what you want. Velocity is in the global space. Remove that and see what happens.
On a more general note, If you're using physics, try to use only forces and torquees. Using transform.Rotate to change a rigidbody's rotation while physics is active will just make your life difficult, and make the rigidbody do strange things. I do change the velocity of rigidbodies sometimes, but not in every frame. I just don't know enough about physics to mess with velocities that way.
Also, make sure you're doing these things in a FixedUpdate function, since that is where input that affects physics is supposed to be checked.
I want to make the cube climb on the green blocks.I used Friction and Increased Force but Nothing happended.I wanted to make a game like Samsung Edge.
I am using RigidBody to control
If you want the cube to move by rotation I believe the function to use would be AddTorque() - documentation, it's a force you apply at a specific place of rigidbody. Then you have to experiment with friction and location of the torque you apply to get the effect you want.
I have a game object in unity I'd like to thrust vector around with some forces. At the moment I'm trying to add some realistic rotation forces hence using AddForceAtPosition using an offset from the rigidbody center of mass. Yet when i run the game, the object starts moving slightly in addition to the rotation. No other forces are present and there is no drag.
rb.AddForceAtPosition(transform.TransformDirection(Vector3.up * 5), transform.position + transform.TransformDirection(mainThrustPt));
The Rigidbody.AddForceAtPosition function apply both torque and force on the object. this means that the Object will be rotated and moved at the-same time.
If you just want to apply a rotational force that doesn't move the Object, use the Rigidbody.AddTorque or Rigidbody.AddRelativeTorque which will only apply a rotational force to the Object.
You can also free the Rigidbody x,y,z position if you don't want it to move but the movement behavior of the object will be weird sometimes when this is done.
Yet when i run the game, the object starts moving slightly in addition
to the rotation.
If the Object is moving without adding force to it or without using AddForceAtPosition, then gravity is pulling it. Disable "Use Gravity" as I did in the image above.
Use AddTorque if you need rotation.
If you pushed the edge of a ball tied up with string, you would expect it to swing as well as spin. Try using this before applying the force:
rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
This is the setup I have. I am trying to make a game in unity which appears 2d but is actually 3d. I have a simple sphere and a floor, which is made up of cubes placed next to each other(the colliders overlap a little) with the same Y value and Z value. My 2d plane is in X-Y plane(Z being the depth).
Now in the script attached to the sphere, in the Update function, I have used rigidbody.addForce() in the +ve X axis function to move the sphere forward. I have attached rigidbody to the sphere and enabled gravity. The collider of the sphere is the default one.
Now the problem is:
When I run this scene. The sphere moves forward but at the intersection of the colliders, it jumps a bit(very less but still noticable) upward and loses its momentum. It happens at every intersection.
BUT this does NOT happen if I place the sphere on a floor made up of a SINGLE cube(a very long one).
Is this problem arising because of overlapping colliders? How do I solve this issue?
Thanks in advance
I don't think this is fixable. Unity physics is approximate, and even when physics material are set up to 1.0 bounciness, momentum doesn't stay constant — I learned it the hard way when I tried to develop a game depending on constant momentum, and had to write my own little physics simulation for that.
I have a problem with AABB collision resolution.
I resolve AABB intersection by resolving the X axis first, then the Y axis.
This is done to prevent this bug: http://i.stack.imgur.com/NLg4j.png
The current method works fine when an object moves into the player and the player has to be pushed horizontally. As you can see in the .gif, the horizontal spikes push the player correctly.
When the vertical spikes move into the player, however, the X axis is still resolved first. This makes "using the spikes as a lift" impossible.
When the player moves into the vertical spikes (affected by gravity, falls into them), he's pushed on the Y axis, because there was no overlap on the X axis to begin with.
Something I tried was the method described in the first answer of this link.
However the spikes and moving objects move by having their position changed, not velocity, and I don't calculate their next predicted position until their Update() method is called.
Needless to say this solution didn't work either. :(
I need to solve AABB collision in a way that both of the cases described above work as intended.
This is my current collision source code: http://pastebin.com/MiCi3nA1
I'd be really grateful if someone could look into this, since this bug has been present in the engine all the way back from the beginning, and I've been struggling to find a good solution, without any success. This is seriously making me spend nights looking at the collision code and preventing me from getting to the "fun part" and coding the game logic :(
I tried implementing the same collision system as in the XNA AppHub platformer demo (by copy-pasting most of the stuff). However the "jumping" bug occurs in my game, while it doesn't occur in the AppHub demo.
[ jumping bug: http://i.stack.imgur.com/NLg4j.png ]
To jump I check if the player is "onGround", then add -5 to Velocity.Y.
Since the player's Velocity.X is higher than Velocity.Y (refer to the fourth panel in the diagram), onGround is set to true when it shouldn't be, and thus lets the player jump in mid-air.
I believe this doesn't happen in the AppHub demo because the player's Velocity.X will never be higher than Velocity.Y, but I may be mistaken.
I solved this before by resolving on the X axis first, then on the Y axis. But that screws up the collision with the spikes as I stated above.
Why not resolve on the Y-axis first for vertical spikes, and on the X-axis first for horizontal spikes?
Nice graphic, by the way.
As I understand it, you're handling movement and collision something like this:
Move all objects.
For each object O, test for intersection between the player and O, and if necessary, eject the player horizontally or vertically so that it is no longer intersecting with O.
If the player is still intersecting with some object, then (something).
This means that when you come to step (2), you have forgotten which way the object O was moving, so you can't tell if it is trying to push the player upwards or sideways.
Solution: in step (1), store for each object the direction it is moving. When you find the player intersecting with an object, you can look to see whether the object is moving up, down, left or right, and that will tell you which way to perform the ejection.
As Gareth Rees already said, the issue is after a collision is detected, you need more information (both current location and either direction came from or last position) to perform the collision response.
It gets quite complicated if both objects are moving. Instead, choose one object to be the frame of reference and subtract its velocity from everything else.
A straight forward solution might be to create line segments for the movement/delta of the non-frame-of-reference object. Then intersect those segments with the 4 AABB edges. This gives the time of intersection and the normal at the point of intersection. Then you can apply the same response you have now.
One possible solution I found is sorting the objects before resolving based on the velocity of the player.