Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement raycast lookahead collision for missiles #2472

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

numidium
Copy link
Collaborator

@numidium numidium commented Dec 4, 2022

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:

  1. Ranged spells can be sent through walls if the player is close enough to the wall.
  2. Enemy arrows can sometimes push the player out of their path without causing damage.
  3. Spell missiles will sometimes be mounted by their targets after collision as if they're solid objects.

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.

@petchema
Copy link
Collaborator

petchema commented Dec 5, 2022

Could you have used FixedUpdate() instead of Update() then?
It's called at a constant rate (used for physics updates), I wonder if that could simplify code somewhat

@numidium
Copy link
Collaborator Author

numidium commented Dec 5, 2022

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.

@numidium
Copy link
Collaborator Author

numidium commented Dec 6, 2022

EDIT: False alarm. After some testing I didn't find any of the below suspected issues with the Player layer.
Found an issue. I'm using the Player layer for the missiles so they won't be able to go through things like loot piles. Will probably need to make a new layer.

@numidium
Copy link
Collaborator Author

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";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel a bit uneasy with possible consequences of changing player's missiles layer, can that be reverted or does it break something else?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@Interkarma
Copy link
Owner

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. :)

@numidium
Copy link
Collaborator Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants