Unity Player jump: when to use RaycastHit and when OnCollisionEnter - c#

I am currently learning Unity with C# and now learned two ways to perform a player jump with double jump prevention.
The first is the GetComponent<Rigidbody>().AddForce method with double jump prevention by OnCollisionEnter, e.g. on transform.tag == "Floor".
The second is with the RaycastHit and Velocity for up.
For me the second method didn't work quite well. I was still able to do a double jump.
I was now wondering if someone could explain to me why or when to use one method above the other or which might be superior.
Thanks in advance!

Neither approach is necessarily superior. It all depends on the needs of your game.
Using a well-placed collider at the "feet" of a player model to check for groundedness can work well, but the emphasis is on "well-placed". Poorly positioned or poorly sized/shaped colliders will lead to false positives/negatives. For example, a player may hit the underside of a "ground" platform in the sky and set grounded to true. Or if a player is standing on the very edge of a platform their ground-check collider may not be colliding with the surface they are standing on, causing grounded to be false. And many other edge cases.
Using raycasting gives far more precise control over when and where groundedness should be checked, however, it is more expensive from a processing perspective. Raycasting also allows for upcoming ground collisions to be checked for.
A sophisticated system might use both raycasting and collision detection to cover all necessary groundedness cases.

Related

Character attacks sometimes collide when collision isn't taking place. - Unity Collision

I'm working on a 3D top down game in Unity 2021.3.4f1 (HDRP). In the game I have a player character that's already placed in the game scene before it starts and enemy characters that are instantiated at random spawn points within a certain distance of the player. The enemies and player can use melee attacks to attack each other. Once in a blue moon the player attacks will hit an enemy that the attacks aren't colliding with. This also happens vice versa, where an enemy's attacks will hit the player when the colliders aren't colliding. Otherwise the attacks and collision work flawlessly. I'm 90% sure that this wasn't occurring before I upgraded the engine from a prior 2019 version. Any ideas to as why this could be happening?
I'm using an attack pooling system, where attacks are created with their set info (i.e. attack damage, how many characters can be hit with a single attack etc.) and then thrown into a pool of attack objects. After the attack is registered and has finished, it's deregistered and kept in the pool for further use. I'm using a bool return method called IsCollided that takes in the attacks information as a parameter to detect the collision:
private bool IsCollided(AttackInfo info)
{
foreach (KeyValuePair<TriggerDetector, List<Collider>> data in
control.animationProgress.CollidingBodyParts)
{
foreach (Collider collider in data.Value)
{
foreach (AttackPartType part in info.AttackParts)
{
if (info.Attacker.GetAttackingPart(part) == collider.gameObject)
{
//We want to get the attack scriptable object
control.animationProgress.Attack = info.AttackAbility;
//We also want to get the attacker
control.animationProgress.Attacker = info.Attacker;
//We also want to get the damaged trigger
control.animationProgress.DamagedTrigger = data.Key;
//And then we return true because the attack has collided
return true;
}
}
}
}
//Otherwise it hasn't collided
return false;
}
Basically what I'm trying to say is that attacks will sometimes trigger hit reactions when they're not actually colliding with another character. you could be 15 feet away from a character and you'll collide with them. Most of the time it works when it should. But on a rare occasion this issue occurs.
I'm using a "TriggerDetector.cs" script that has an OnTriggerEnter() method that stores all of the collisions that interact with each character's colliders in a list. Those are then removed from the list using an OnTriggerExit() method that removes the collided with objects when the collision is no longer occurring. Aside from that there's tons of checks which detect if the attack is allowed to collide. There's no issues with that though as the attacks always collide when they should be aside from this issue.
Any help would be greatly appreciated!
I speculate that your system for adding and removing colliders may not work in all cases.
Specifically, I believe that ontriggerexit is not always called correctly, or there is some other problem in the method which, however, I cannot see because you have not published it.
I can advise you to use a different system: instead of using collisions, you can check every frame or every short time with a coroutine, if there are enemies within your area.
To do this, you can study how circles work in mathematics and how you can use them to check if an object is within the area around you.
Since 2019 Unity has made many changes and has probably changed, perhaps making it worse, the collision system.
If you need help with the advice on using the circumference, I can help you, perhaps by opening another question.
If I helped you, you could thank me by marking my answer as accepted: I would be grateful :)
P.S. Instead of foreach use for - it's much better for performance.

Non-existent collision detected with OnCollisionEnter()

I'm trying to make a sticky grenade by disabling its rigidbody upon collision, using OnCollisionEnter(). However, OnCollisionEnter() fires when there is clearly no collision happening, as you can see in this image :
This causes my grenade to stick in the air. I suspect this is due to a lack of synchronization between physics loop & rendering loop. Also, my standard "non-sticky" grenade uses the same model & is working finely.
I already tried the following :
Verify that there are no other colliders which could cause my grenade
to "stick in the air"
Use OnTriggerEnter() instead. The result is a little better but the problem is that it is fired too late, only once the grenade is inside an obstacle or an enemy.
Add rigidbody & continuous collision detection to all objects
Tweak PhysicsManager.DefaultContactOffset from 0.01 to 0.001, as suggested by Eliasar
Switch from "PCM" to "Legacy Contacts Generation"
None of these worked so I'm feeling a little desperate. Thanks in advance for your help !
Code I use to stick the grenade upon collision :
void OnCollisionEnter(Collision c) {
rigidbody.isKinematic = true;
transform.parent = c.transform;
}

How to fix interactable objects movement if not interacted without adding gravity

VR-oriented game in dev.
I have the two-hand-manipulation-script from the MRTK implemented, interacting with my objects works. Goal is to let the objects remain static in their position after interacting - theoretically working. As soon as I add collision with my environment (rigidbody # interactableGameObjects).
But as soon as I start interacting with them and let them actively collide with one of the scenery objects, they start tilting and floating without being willing to stop.
So I'm looking for an easy and not resource hungry way to stop any movement (translation, rotation) of my object after interacting with it - without adding gravity to it.
My main concern is not how to stop all the motion, as I could freeze all constraints of the objects rigidbody or set the Rigidbodys Velocity and angularVelocity = 0.
So my basic idea: "if(movement != 0), and if(object != grabbed), then trigger movement = freeze."
Haven't figured out, how to trigger this kind of event and how to check if item is grabbed or not. Or is there maybe an even easier way?
Thanks for any help!
Note: even if you take the sample scene of the twohandedmanipulation and add ridigbodys to the components, they start floating away without any interaction.
Tried so far:
Putting sample scene in same conditions
Expect vs result: Floating away objects instead of remain fixed in space.
You can use RigidbodyConstraints to freeze the object's position and rotation while retaining the collision properties.
GetComponenet<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
and to unfreeze:
GetComponenet<Rigidbody>().constraints = RigidbodyConstraints.none;

Emitting a constant force from an object(Leaf blower Mechanic) C#

I am just about to tackle a new project where the core game mechanic is covering up dead bodies killed by the mafia with leaves using a leafblower.
You need to cover them well enough to not draw attention when the police question you.
The only problem I can see with this project is how to create this leafblower mechanic.
Off the top of my head I can think of attaching an empty object to my leaf blower which has a constant [rigibody.AddExplosiveForce] that procs on mouse click but thats it.
What should I be looking at and what would be a logical way to create this? You do not need to write the whole code for me, I just wan't to know what tools or scripting API I need to consider.
Thank you :)
You could try continuous adding force using Rigidbody.AddForceAtPosition(). Or calculate directions and try Rigidbody.AddForce().
Basically Rigidbody.AddExplosionForce is working as Rigidbody.AddForce, but uses sphere to calculate Vector3. If you need to emit it continuously, you should just use it in FixedUpdate() and list of object you can get by using Raycasts or simple Trigger Collider, for example Capsule Collider.
You could use Collider Capsule like this ↑↑↑. And in OnTriggerEnter or OnCollisionEnter:
private void OnCollisionEnter(Collider other) {
if (other.gameobject.tag != "leaf") return;
// Your AddForce here.
// Also you can get exact point of collsion by using
// other.contacts and use this as AddForce argument.
}

XNA - Farseer Physics 3.5 - Collision Detection Issues - No/Zero Gravity - Space Game

So I'm working on a space game called Star Commander.
The progress was going beautifully until I decided I needed to implement some sort of physics. I'm mainly going to be needing Farseer Physics for collision detection.
Anyway, since it's a space game, when I am declaring my 'World' object:
private World world;
this.world = new World(Vector2.Zero);
I have no gravity. This causes a weird result. I can collide with objects, but once I stop colliding with them, that's it. I can no longer collide with them and will just go straight through them. However, with gravity:
private World world;
this.world = new World(new Vector2(0F, 1F));
Collision works beautifully.
I've tried looking around for help with Farseer, but a lot of the posts are dated and there are no real good sources for information and sadly, I'm pretty sure I'm not going to get the help I need here either.
The only thing I found whilst looking around was that with objects called "Geoms" I need to disable a property called "CollisionResponeEnabled" or something similar.
However the Geom object is no longer present in Farseer Physics 3 and has been totally replaced by Fixtures. Fixtures do not seem to have this property, however.
I can provide any source code that may help, but keep in mind I am still implementing the physics engine into my project and a lot of the code isn't final and kind of messy.
IMPORTANT EDIT:
After recording a short gif to demonstrate my issue, I found out that I can only collide with an object once, to collide with it again, I have to collide with a different object, but then cannot collide with that object until I collide with a different object.
Example:
It seems to me that your bodies might be "sleeping" after the collision. Have you tried setting SleepingAllowed = false on the bodies to see if this is the problem?

Categories