Hi all, I’m very new to Unreal Engine 5 and wanted to try building a basic target shooter game with some realistic projectile mechanics (interesting math + scalable learning opportunity from a hitscan line trace to gravity affected projectiles and surface penetration)
Notes:
- Projectile logic is built in a Blueprint class component that is tied to a new projectile actor (sphere) that is fired from the weapon. Using first person shooter template with my new projectile actor replacing the original one
- Purely trying to add basic ricochet at this point, loss of projectile energy, etc… will come later
- Projectile actor has a 10 second lifetime (specified variable) before the actor is destroyed
- Loosely referencing this video when I get stuck, but doing the math/modules myself as a learning experience
*I’ve already implemented an effect from gravity/drag on the projectile - In my images below the hit results are the from a line trace ‘Out Hit’. Boolean condition is from the line trace ‘Return Value’ (did the line trace hit an actor?)
Setting the projectile speed super low result in the projectile bouncing (ricocheting) as expected (no loss of energy so it just keeps going)
When ramping this up to higher speeds (realistic bullet velocity) the ricochet is occurring, but appears to be happening sometime after the line trace returns a hit. Since the line trace is based on the vectors of the projectile actor and it’s moving so fast, I’m assuming that when the line trace returns a hit, the projectile actor has already kept traveling through the object before it realises it needs to change direction? (or something along those lines)
To deal with this, I tried making it so that the projectile actor location was instead changed to the location of the line trace impact point before it then applies the ricochet.
This resulted in the projectile actor correctly ricocheting from the point of impact (as found by the line trace, but now the projectile actor appears to disappear or stop dead in it’s tracks after a certain distance (wondering if the projectile stops after some change in delta seconds? Really not sure). Note, the last position variable is calculated by getting the current projectile actor velocity, multiplying it by the delta seconds and adding this to the current projectile actor position. If I set the projectile velocity to extremely low, I can see the projectile actor (sphere moving). In this case it appears to have just disappeared - I can no longer see it at the end of the line trace.
(above is just shooting the projectile with no impact in distance). Interestingly if the projectile ricochets off an object within this amount of time or distance before it disappears, it will continue to exist as expected. The projectile actor appears to disappear before the set 10 second lifetime has elapsed and it is destroyed.
Based on this, I assumed adding a branch might help (if the line trace impacts a point do the ricochet, otherwise just have the projectile travel forwards as normal)
Adding in a branch (condition is the ‘Return Value’ (Hit) boolean from the line trace results in the projectile acting as I would expect. It no longer appears to have ‘such a short lifetime’. Projectile now appears to fire as expected and last for the full 10 second lifetime duration before it is destroyed. The projectile actor can now travel as far as needed in the 10 second lifetime before ricocheting.
This appears to have resolved the issue, but I don’t understand why? Setting the branch to false results in the same issue (projectile disappearing after a short distance or time) as described above. I could understand if the branch was setup to have an “if projectile hit, then do ricochet” and “if projectile doesn’t hit, continue path as normal”, but only one condition is connected? As I said, I’m quite new to this so maybe I’m missing something obvious…
Questions:
- Why does adding this branch resolve the issue?
- Why does this only work if the branch is set to ‘True’ (Line trace hit an actor), not if it is set to ‘False’? (line trace doesn’t hit an actor)
- Why does this branch not need another condition set for the ‘False’ output in order to resolve this issue?
Hopefully my above questions/explanation make sense. Let me know if more detail/information is needed. Any help/insight would be greatly appreciated!
Cheers!