Interpolate where OnTriggerExit is called - c#

In my code, I use OnTriggerExit to detect when an object leaves a previous cube's space, and then create another cube. However, because of delta time, the cube gets placed slightly late creating these varied size gaps:
How do I get rid of them, and position the cube properly?
I am pretty sure I need to interpolate, but I am not sure exactly what/how to do it. If needed, I have the last cube, last frame and current transforms, as well as current speed (in Vector3 form). Thanks!

When you leave, set this cube's position to lastCube.position + size_offset, where size_offset is however big your cubes are in the direction that they're moving.
You already have a reference to the previous cube (due to the OnTriggerExit supplying you with a reference to the other collider, from which you can get the needed Transform).

I don't think this is strictly deltatime,s fault. Physisc engine has its on timestep, and if the velocity is x, the object will travel x*dt per physics step. So, by the time the next round of triggers is fired, the object is already penetrating. You could either use a rigidbody (easier but may not give expected results), or check penetration depth with that collider and offset that

Related

AddRelativeForce() causes unwanted turning

I've create a movement script that moves a character (ship) in a topdown view.
Gravity is disabled, but the rest of the settings i left mostly alone.
I'm applying a constant force in the forward or backward direction (local, so relative to the character NOT the world). This however causes some movement in other directions if the character is rotated for some reason.
Debug.Log(nameof(force) + force);
rigidBody2D.AddRelativeForce(force);
Lets me explain with pictures.
Starting point:
Moving forward somewhat (works okay):
Back to starting point (stopping game, starting anew)
And then i manually change the rotation to -90 in the inspector.
I then move forward somewhat.
As we can see since the rotation is -90, moving forward in relative to the character (AddRelativeForce(..)) causes it to move to the right on the screen.
The X position increments accordingly.
However, also the Y component changes, the character gets velocity in this direction, even though i apply no force in that direction - which we can see in the output.
How can I move my character with force without this issue?
Edit:
Here are the project files. Runs under the latest unity 2020.1.14f1. The logic mentioned here is located in MoveExecuteSystem. I use a small ECS framework: https://github.com/Leopotam/ecs
https://wetransfer.com/downloads/b86dfb27b4388b85ac4fef285d87b39520201124193329/00af66
Take into account that AddRealtiveForce adds the force in the local coords system. If the force vector has got always the same value, the outcome is going to be different depending on the rotational position of the entity.
To solve this, you need to apply the force such as: Vector3 force = myShip.forward * forceValue where force value can be an int or a float.
It can be myShip.up or myShip.right depending on what you want. My point is that with the .forward, .up or .right you always will apply the force according to the instant local coordinate system rotational position.
EDIT:
This question seems deeper than I thought, I made the trial in a project myself, and actually there are variations in the position when you apply force only when the object is rotated. Had a quick look and don't know why this is. Seem to be a precisiĆ³n thinh regarding the rotations of the physics the rigidbody uses under the hood.
I tried to remove the friction which I thought might be also cause of the problem but seems not possible. +1 to this question and lookig forward to know the answer.
EDIT2:
Bounciness and friction can be set to 0 if a new physics material 2d is created, but the issue persists.
You can freeze position in determined axis as a solution, but this does not explain the position variation problem.

Hitting a character physics?

Ok, for this task I need to coordinate physics hitting a game object at a certain point and animation, to create the illusion of punching a character and he stumbles back as if propelled by that contact point.
I have rigid bodies on both the hitting object and character being hit, and can tell when the hitting object enters the character's box collider. What I thought to do first was create an impulse at the contact point then trigger my pre made character animation -
Vector3 direction = (this.transform.position - collider.transform.position) / (this.transform.position - collider.transform.position).magnitude;
this.transform.GetComponent<Rigidbody>().AddForce(direction, ForceMode.Impulse);
Problem is this just makes the character float slowly off opposite the hitting object (Rigidbody has gravity checked on character), and depending on where the character is facing, the animation looks not coordinated with the punch.
I wanted to see whether there's a streamlined way of doing this - how can I create a realistic punch/moving backward situation in Unity?
There's no easy way to get this behavior out-of-the-box with Unity. You will need to script a blending of ragdoll physics with animations.
One approach you might want to try is a system that "pins" your ragdoll to the bones of an animation, and if a collision occurs, the ragdoll unpins itself (partially or completely) from the bones, temporarily. When/if it completes being affected by physics, you would probably want to animate from a keyframe dynamically created based on the position of the ragdoll to a target keyframe.
There are also tools like PuppetMaster on the asset store that are meant to do things like this, but they are often not free, because they are difficult to make well.

Unity Object moves when AddForceAtPosition is applied when it should only rotate

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;

Fast swipe movement of GameObject does not collide with Colliders

I am working on a Unity game in a 2D environment. The player GameObject has a Rigidbody2D attached. It moves horizontally when swiping. When swipe is too fast, it does not collide with the Colliders. Maybe it changes its transform position before detecting collision? It does not happen when the swipe is slow.
Based upon your problem I am assuming you are moving your object in the Update() function (please correct me if not). This means you are moving the object a certain amount every frame. However, Unity checks colliders and does physics calculations on a different time interval (Fixed Timestep, https://docs.unity3d.com/Manual/class-TimeManager.html).
Just before the objects collide, the colliders are checked. Unity calculates colliders every Fixed Timestep (default 0.02 times a second). If unity does not detect a collision it means your objects intersect for less time than the Fixed Timestep, or in other words, they are moving very fast (like you describe your situation). One (bad) way to fix this would be to decrease the amount of time in between physics calculations. However, this would greatly decrease your programs efficiency.
Instead, consider moving your object in the function FixedUpdate() so that the object only moves every time the physics checks for a collision. This should fix your problem.
Take a look at the 3rd answer (by Garth-Smith):
https://forum.unity3d.com/threads/rigidbody-2d-wont-collide-with-another-object-when-its-moving-really-fast.248786/
I particularly want to highlight the part:
If you have a Rigidbody2D, you should be moving it in FixedUpdate()
using rigidbody2D.MovePosition(Vector2). This will move the
Rigidbody2D through space, instead of teleporting it from point A to
point B.
The second part about Raycasts should not be necessary for your problem, but if you continue to experience problems your can use them to check a range as jdweng stated in his comment.
Here are a couple places to learn about Raycasts if you are unfamiliar with them:
https://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html
https://unity3d.com/learn/tutorials/topics/physics/raycasting
If the movement of your object is too fast it will simply ignore the collision since it never touches the actual collider - it just skips it.
In order to fix this you need to predict when that collision will happen and trigger it at correct moment.
Setting collision detection to Continuous as pixlark said might help if the swipe is not too fast.
Make sure that the collision detection mode for your Rigidbody2D is set to Continuous or Continuous Dynamic.
simple
go to the rigidbody of the object and change the c

2D Platformer AABB collision problems

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.

Categories