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.
Related
I am currently working on translating a VR game to the Oculus Quest 2 from a PC standalone version. In this game, the game menu cannot be accessed by the player wearing the headset, as it is not visible to the player; it is instead accessed by another party at the computer itself. When the person at the computer clicks, start game, a number of processes begin, including a coroutine to spawn multiple instances of a game object in a non-player enemy's hands.
Part of the translation process includes allowing the player to start the game from the Oculus Touch controllers, I am attempting to implement a feature where either of the four face buttons will start the game.
if (OVRInput.GetDown(OVRInput.Button.One) || OVRInput.GetDown(OVRInput.Button.Two) || OVRInput.GetDown(OVRInput.Button.Three) || OVRInput.GetDown(OVRInput.Button.Four))
{
startGameClick();
}
However, it seems like calling startGameClick(); more than once, whether in the same script or otherwise, causes the game to not run certain processes, chief among them the ball spawn coroutine. This causes the NPC enemies to activate their throwing animations without having a ball to throw, and they do not return to their idle animations afterwards. I am unsure why this is, however it has been a major roadblock in attempting the platform translation.
Additionally, this is the startGameClick(); function:
// If the start game button is clicked
public void startGameClick() {
StandaloneServer.startgame = true;
if (Master.usingMM && ServerController.IsServerReady())
Master.ready = true;
else if (!Master.usingMM)
Master.ready = true;
roundController.startInput();
beginGameButton.GetComponentInChildren<Text>().text = "In Progress";
beginGameButton.interactable = false;
}
My assumption is that one of the references in this function is the source of the issue, but I cannot pinpoint which one.
Base Information
Unfortunately, to answer your question, we would need to see all of the related scripts for this function which just isn't feasible as that would also require us to be kind enough to sift through your code to find your error.
A Cheap Solution
However, there is a cheap solution to your issue. You can simply reload the scene (or reset the script if it's DNDOL) and it should work again.
It seems I've found a solution at long last.
Instead of calling the startGame() function again, I decided to invoke onClick() to simulate the effect of clicking the button with a mouse, although the player is actually touching the button in the VR space. This worked, and the game is running as it should.
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.
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;
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.
}
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?