- Home /
Arrows not stopping immediately when target hit?
Hello!
I am making a small FPS where you shoot arrows at enemies. I want to make it so that arrows stick whenever they hit any object and, if they hit an enemy, they should stick to the enemy.
However, after making several different attempts at making this happen using different object-stopping code, the arrows seem to keep stopping AFTER they collide with the enemy. One would assume that the arrow-stopping code is kicking in too late, but here is what is strange: this bug happens only occurs sometimes whereas in other cases the arrows stick to the enemy correctly. The distance some of the arrows travel is also sometimes way too long.
Here is a picture of the bug in Scene view and the code I use to make the arrow stop.
Thank you very much!
private void OnCollisionEnter(Collision collision) { flying = false;
rb.isKinematic = true;
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
//rb.constraints = RigidbodyConstraints.FreezeAll;
transform.rotation = rotationWhenEnemyHit;
rb.useGravity = false;
if (collision.gameObject.tag == enemyTag)
{
transform.SetParent(collision.gameObject.transform);
enemyHitStats = collision.gameObject.GetComponent<EnemyCombatStats>();
enemyHitStats.TakeDamage(arrowDamage);
enemyHit = true;
}
else
hitButNotEnemy = true;
collider.enabled = false;
}
Answer by arichards · Jul 17, 2019 at 05:15 PM
It's possible the arrow is traveling that much further through the enemy in one frame, though I thought discrete continuous would help that...
Try setting the arrow position to the point of collision. My guess is you'd set .position (not .localPosition) to this value after reparenting to the hit collider. You may want to iterate through all the contact points to make sure you get the one with the right enemy tag on it.
https://docs.unity3d.com/ScriptReference/Collision.GetContact.html https://docs.unity3d.com/ScriptReference/ContactPoint.html
I also think you only need to set isKinematic to stop most of the other rb properties you disable, once you prove it working.
Also I'm sure you know, the character doesn't have a mesh collider? It looks like you're using a capsule collider that's not exactly aligned with your player. I'm assuming that's temporary :)
Hey, thanks for the help! It actually worked great. I had already done exactly this to the rotation but (quite dumbly) never thought of this for the position. Here is the final code (tried my best to get rid of unrelated lines):
private void Update() {
//makes sure arrow is correctly angled when enemy hit
if (!hitButNotEnemy)
{
if (!enemyHit)
rotationWhenEnemyHit = transform.rotation;
else if (!rotationFixed)
{
transform.rotation = rotationWhenEnemyHit;
rotationFixed = true;
}
}
//makes sure arrow is correctly positioned when enemy hit
if (!hitButNotEnemy)
{
if (!enemyHit)
positionWhenEnemyHit = transform.position;
else if (!positionFixed)
{
transform.position = positionWhenEnemyHit;
positionFixed = true;
}
}
}
private void OnCollisionEnter(Collision collision) { flying = false;
rb.is$$anonymous$$inematic = true;
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
transform.rotation = rotationWhenEnemyHit;
transform.position = positionWhenEnemyHit;
rb.useGravity = false;
if (collision.gameObject.tag == enemyTag)
{
transform.SetParent(collision.gameObject.transform);
}
else
hitButNotEnemy = true;
collider.enabled = false;
}
As for the capsule collider: actually I'm using a character controller for the time being. What is happening is that the run animation makes the enemy lean forward a bit, causing the character controller collider to disalign with the model. At some point I will have multiple colliders for the head, body and legs so the arrows have different damage and effects when it hits the enemy, but I'm leaving as is for the time being and it is actually working decently. The game is supposed to handle dozens of enemies at the same time, so I'm wary of abusing mesh colliders.
Thanks again!
Thanks for the update! I'm glad I could help!
Answer by BradyIrv · Jul 17, 2019 at 04:18 PM
Try changing the Rigidbody's detection parameter in the Inspector to be Continuous Dynamic instead of default Discrete.
https://docs.unity3d.com/ScriptReference/Rigidbody-collisionDetectionMode.html
Answer by ulissesnascim · Jul 17, 2019 at 04:37 PM
@BradyIrv I've made sure of that both in the prefab and in code when spawning the arrow. You can see the mode is set to Continuous Dynamic in the bottom right of the screen below (I shot the arrow and paused the game before it hit any colliders)
Your answer
Follow this Question
Related Questions
How to fire my bow and arrow which I have imported into Unity from 3ds max 2 Answers
How can I nail an arrow to an enemy(In 2D)? 1 Answer
2D Character suddenly stops moving for no given reason 1 Answer
How to get an animation script working? 1 Answer
How do I make an object stick to all other objects (2D) 2 Answers