Implement raycast lookahead collision for missiles#2472
Conversation
|
Could you have used FixedUpdate() instead of Update() then? |
Good catch. I wasn't aware of that method but judging from the docs it seems to do the exact same thing I'm doing here. Will refactor later. |
|
EDIT: False alarm. After some testing I didn't find any of the below suspected issues with the Player layer. |
|
I've done a fair amount of testing for this via casting ranged spells/arrows and being on the receiving end of both in various scenarios. Haven't found any issues that weren't there before. I hope this isn't too drastic of a change - I've found it makes missile collision a fair bit more robust and predictable. |
| if (caster && caster != GameManager.Instance.PlayerEntityBehaviour) | ||
| layerName = "SpellMissiles"; | ||
| else | ||
| layerName = "Player"; |
There was a problem hiding this comment.
I feel a bit uneasy with possible consequences of changing player's missiles layer, can that be reverted or does it break something else?
There was a problem hiding this comment.
If the missile exists on the SpellMissiles layer then it can collide with the player. The current code base handles this by spawning missiles a few units in front of the player. However, this can cause spell missiles to go through a wall if you cast right next to one. If you're fast enough you can also get hit by your own arrows.
|
To be up front, I probably won't merge this before 1.0. But I think this PR is something that has a lot of value. There have been enough issues with missiles to warrant some kind of refactor and improvement. I also realise this is your second pass at this, as the first pass reintroduced an older problem. Let's keep this one here as a reference for future work, and see where it goes after 1.0. :) |
|
That's fair. I understand not wanting anything to be radically different for 1.0. I'll be here to follow up on it and answer any questions you have in the future. |
…s now excluded from the LayerMask
…l caster to use the Player-excluding layer mask. Now the Player-excluding layer mask is only assigned if the caster is the Player.
I plan to test this some more before it gets integrated into master but so far everything seems to be working. I made this PR to address a few issues with missile collision I've noticed over the years:
I tried tweaking Unity's physics/collision classes many different ways to alleviate these problems before giving up and rolling my own collision system specifically for missiles. I implemented fixed-interval movement steps (i.e. ticks) for missiles that check for obstacles using raycasts before moving forward.
The advantage of using a fixed interval is that the missiles don't do a raycast on every call to Update. According to the docs, Update is called every frame so the raycasts-to-time ratio would scale to the frame rate which would cause unnecessary strain on the system. Instead, we can tweak the missiles' movement time step to meet our needs.
I assigned separate tick rates for arrows and spell missiles since the former uses rays and the latter uses spheres. I assumed that sphere casting is more expensive than ray casting so I made the tick rate somewhat lower both for that reason and that spheres probably don't need as many timesteps for precision as arrow rays.
Overall I feel this will give us more control over what happens to missiles and should make it impossible for them to go through walls.
EDIT: Per petchema's suggestion, I moved the logic to FixedUpdate so now it uses the global physics tick rate of 50.