I have 3d cube which have 3d box collider.
I want to write jump system for cube with collision, but without physics (without gravity, without rotation, etc) (Like 3d platformer)
You can take advantage of the Physics.OverlapBox API to check for collisions before committing to move your object.
Your code will look something like this:
Vector3 nextPosition = transform.position;
/*
You do your normal movement code, but apply
it to nextPosition instead of transform.position
*/
Collider[] hitColliders = Physics.OverlapBox(nextPosition, transform.localScale/2);
if(hitColliders.Length == 0){
transform.position = nextPosition;
}
Note that the object itself shouldn't have a collider, otherwise it will detect itself. You also shouldn't move in big steps as this method doesn't take colliders on the path into account.
There is a great way of doing this. You will still need physics.
The Steps
Have a rigidbody on your player.
There should be a dropdown menu called spmethiing like "constraints". Find it.
Then Set all rotation constraints in this menu to true.
However, I don't understand why you wouldn't want gravity. Don't all platformers have gravity? (There must be some force to pull your player down when they jump). Anyways, if you don't want gravity, then you must uncheck Use Gravity variable.
**Notes: **
To control your player, you must use AddForce(). If you have any questions about adding force, let me know in the comments.
:) Thanks.
Related
I made the endless movement of the object and its repulsion from the walls, but it does not always work correctly. At rounded corners (sometimes even at a straight wall), it just gets stuck and stops moving altogether, or moves slowly to the point where it stops moving. What can this be related to and how can it be fixed?
private void FixedUpdate() {
rb.velocity = direction * normalSpeed;
lastDirection = direction;
}
private void OnCollisionEnter2D(Collision2D collision) {
//Repulsion from objects.
direction = Vector3.Reflect(lastDirection.normalized, collision.GetContact(0).normal);
}
There is a small distance between the objects, but the circle seems to stick to the wall and moves with it until it collides with another collider:
Example
there are objects under the circle that also have colliders, but the collision between them is not considered, since they have the same layer (in the settings, I disabled the collision for objects on the same layer). What can be done to fix this error and what can it be related to?
The object in the general scale:
Example
I tried to increase the size of the wall collider, tried to change polygon collider to box collider, connect composite collider, changed the mechanics of the object movement (in these cases, the movement could work incorrectly), but the result was always the same - the jams (sticking to the wall) continued.
It is difficult to answer your question without having more information, but I can suggest if you are using physics to move your objects - utilize physic materials and remove code that changes direction manually in OnCollisionEnter. Using physic materials you can easily make your object bounce from colliders of your choice without losing velocity.
player and object both have colliders and rigidbodies, object has position and rotation locked, player has only rotation locked. When the player goes to the blocks, the player goes through the blocks, although they do give a bit of resistance. To move the player im setting the rigidbody's velocity, and doing that in FixedUpdate.
i have no idea why this is happening, any ideas?
main part of the code is:
rigidBody.velocity = new Vector3(direction.x, rigidBody.velocity.y + (-Gravity * Time.deltaTime), direction.z);
(direction is determined by the WASD keys, and i'm using my own gravity)
First of all, you do not need to multiply the velocity by time.DeltaTime, because you are moving your object in the FixedUpdate() method; Which uses fixed time intervals since the physics engine does not run in sync with the regular game engine. Also, both objects do not need rigidbodies in order to collide with one another. I suggest looking at your collision matrix in settings and verifying that everything you need collision for is checked correctly. As others have said as well, check your kinematics on the rigidbody.
A last suggestion for working with your own gravity. Do not change the actual gravity value of the game engine. It is typically recommended that you use a multiplier variable and apply it to the constant gravity already set by the physics engine. If you are completely editing the gravity, than maybe consider using a character controller instead.
I guess it has something to do with what the documentation says "In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour".
Try to use AddForce() or similar functions to alter the properties of the rigid body. Colliders etc will then work as expected.
I have a problem with physics. It is my first time doing in 3D, so it may be just a beginner mistake.
I just wanted to create a simple player controller and make it so that it can not pass trough cubes.
The problem is that when going straight into the cube, part of the player is in the cube itself. When stop moving, it pushes me, so they are not intersecting (that makes sense).
I tried moving the player using .Transalte, .MovePosition and by changing the velocity of rigidbody itself. None of it change anything. The player can always move a part of him into the cube.
Any ideas how to solve this?
My player controller:
(The 2 lines commented out in Move() are just other ways to move the player.)
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float movementSpeed;
private Vector3 input;
private void Update()
{
GetInput();
}
private void FixedUpdate()
{
Move();
}
private void GetInput()
{
float inputHorizontal = Input.GetAxisRaw("Horizontal");
float intputVertical = Input.GetAxisRaw("Vertical");
input = Vector3.ClampMagnitude(new Vector3(inputHorizontal, 0, intputVertical), 1);
}
private void Move()
{
GetComponent<Rigidbody>().velocity += input * movementSpeed;
//GetComponent<Rigidbody>().MovePosition(GetComponent<Rigidbody>().position + input * movementSpeed * Time.deltaTime);
//transform.Translate(input * movementSpeed * Time.deltaTime, Space.World);
}
}
Player is standing still
Player is moving towards cube
Settings of the Game Objects itself
Now I think I understand your problem.
The collider is a geometric shape that is checked but the outcome wont take place until the collision has actually taken place, this means, one geometric shape being inside the other. By this I mean, that what you are experiencing is the normal behaviour of the collision. If both elemnts are rigid bodies, both will move and your problem wont be perceivable, but if your cube is not a rigid body or is kinematic, will stand still in the same position, and depending on the other object speed, its normal that an invasion/superposition of the elements is perceivable, because that is the frame were the collision took place, and were your element needs to be moved back because it has collided.
Consider that if the speed is high enough, and the position from one frame to another varies enough, the collision might not even take place, because the geometric parts do not interfere between frames, as the position variation might be bigger than the bounds of the collider itself. The collision check at the end of the day, is dicrete, and not continuous (even you can set it as continuous to be as frecuent as possible).
To solve or improve that, you can adjust the speeds to avoid that being perceivable + adjust your collider to make it react before the graphic superposition occurs. This means making the capsule or the cube collider bigger than the graphic element itself. You can even calculate , to make it as bigger as much as your your speed * Time.deltaTime result or speed * FixedTimeStep result, depending on your safety distance needs. I think one of those should be the safety distance you need to take into account before the graphic collision occurs.
Another thing you can do is tight more the times physics calculations are done.
https://docs.unity3d.com/Manual/class-TimeManager.html
But need to be careful with this as this can be a performance devourer and need to be handled with care. You can make some trials with that and check your problem can improve.
Hope that helps
You can increase the scale of your player's collider from the Collider component attached to it. You can check how big the collider is from the editor scene view.
Edit: The issue might be that your movement or collision code is called in Update instead of FixedUpdate. When working with rigidbodies, you want to call the physics calculations inside FixedUpdate.
remove rigidbody from the cube, you can click on 'Gizmos' in the top right of the editor and make sure the colliders are at the edges of the objects.
I'm really struggling at something that I had imagined to be pretty simple: I have two meshes (fighters) instantiated from the same prefab and I want them to not overlap. The prefab is set to have a box collider. Ideally, I let the animator handles the position. I've tried several approaches:
Configure the animators to "Animate Physics". No collision is detected
Uncheck root motion and move characters using game object's transform's position. No collision is detected
Uncheck root motion, add a rigid body to each character and move character using game object's position. Collision is detected, but the reaction is governed by physics which makes it look unnatural since all I want is to just avoid the characters to pass through each other i.e. just want characters to be pushed back until they don't collide anymore
I really would like to avoid going with a manual approach to this. How would I prevent this overlapping?
Edit: isTrigger is unset on box colliders
A rigidbody is highly configurable and you want a limited set of the physics functionality it can offer. Go with the third solution you enumerated and freeze the rotation in the rigidbody. See the rigidbody page for more details.
As a side note, you might consider using a capsule collider, so that characters "slide" around each other more easily.
Although it's not necessarily preventing overlap, you could create a perimeter for characters. It would be rather simple depending on what you're doing.
If you want to set up a distance perimeter to prevent characters from getting too close to one another you could use the following equation
Vector3 focalPOne = focalPointOfCharacterOne();
Vector3 focalPTwo = focalPointOfCharacterTwo();
float dx = focalPOne.x - focalPTwo.x;
float dy = focalPOne.y - focalPTwo.y;
float dz = focalPOne.z - focalPTwo.z;
// calc distance along z plane
if (Math.Sqrt((dx * dx) + (dy * dy)) < minDistance)
{
// person is too close to the others head.
if (Math.abs(dz) < minHeightAbove)
{
// go to previous position.
}
// if there is no vertical elivation, you can go
// straight to moving them back to previous position
}
enter code here
If this wasn't what you're looking for, please let me know so I can edit or remove it.
The perimeter created would look something like this.
In order to have your characters with their respective box colliders register a collision, both need to have a RigidBody component. That's the only way to make sure the characters do not go through each other considering they share a prefab.
You don't have to handle the separation/rejection of the characters via the physics engine though. Simply make the box collider trigger, and then handle the separation via code in a C# script using onTiggerEnter.
There's a collision detection matrix that could help you, found here: https://docs.unity3d.com/Manual/CollidersOverview.html. Also this image summarizes it beautifully (in the documentation it's in two separate tables for some reason):
I'm new to Unity and after watching and reading some tutorials I'm now trying to make a simple 2D platformer kind of game. In the said game both enemies and player can jump to different platforms and traverse it like the old SnowBros game.
The problem I'm facing is related to programming the enemy movement. In my game there would be several types of enemies but generally for now there are two types, one that can jump from the platform and one that only walks upto the length of the platform, wait for 1 second then flip and walk backwards; meaning they don't get off the platform. Now this is an issue I'm having trouble with. I can't seem to find a way to calculate the length of the underlying current platform. I thought of using the collider.bound.min.x and max.x to come around the problem but the issue is I can't seem to find a simple way to reach the current platform's collider without fetching the script and then going through it.
Since, there would be many platforms of many different sizes and each platform is made up of a prefab of other platforms, it just doesn't seem like a workable solution to use the platform script and then traverse through it.
You can use Physics2D.Raycast to "sense" for collisions on a Ray. Imagine the enemy putting their toe one step forward, feeling if there is still solid ground, and then deciding whether to stop.
void Update()
{
Vector2 newPosition = transform.position + velocity * Time.deltaTime;
Vector2 downwardDirection = Vector2.down; // you may have to replace this with your downward direction if you have a different one
RaycastHit2D hit = Physics2D.Raycast(newPosition, downwardDirection);
if (hit.collider != null)
{
// solid ground detected
transform.position = newPosition;
}
else
{
// no ground detected. Do something else...
}
}
You can and should define the Layers your Raycast is supposed to hit, so it can ignore the enemy itself and avoid self-collision.
Well, I hope that you have prefabs of platform and in those prefabs put colliders at start and at end. You can specify layers and tags so that only enemy can detect those colliders and then you can detect tags on collision from enemy script and make your operation.
First create layers by opening Edit -> Project Settings -> Tags and Layers. Create two Layers
Create layers for enemy and enemyColliders and Goto Edit -> Project Settings -> Physics2D. Set collision matrix as EnemyCollider will collider with enemy only.
And your prefab will be looks like,
I hope this would help you.