Couldn't get it working using SphereCast-ing

With a bit of debugging, I discovered that my hits[ ] array was returning no hits whatsoever, even though the SphereCastAll radius was the same in both the script and inspector, and there was definitely another enemy in range. I found some documentation that says that SphereCastAll doesn’t return any hit from an object that starts out within the sphere, so I switched to Physics.OverlapSphere and have it working exactly as Sam demonstrated. So… Is this something I did? I’m using Unity 2021.3.12, so has SphereCast changed since the course was made? This doesn’t seem the likeliest answer, since I couldn’t find anyone else who has this issue. As I say, I have it working with a different method, but I’m curious about what went wrong. Any help or ideas would be appreciated… and I can try to recreate my exact (old) code if need be, though there was no material difference (that I could see) between Sam’s and mine (I used a TryGetComponent to remove one if check, but otherwise they were the same).

This is not something that’s come up before, so I’m interested in seeing what’s going on
Humor me, and paste in your code (the SphereCastAll version, not the OverlapSphere version).

This is intriguing. The ray goes from the camera so for anything to start inside the sphere it would have to be very close to the camera. Or the sphere is enormous

I was thinking along the same lines, but I want to see the OP code to see if there might be another cause.

Oh dear. I’ve unwittingly mislead you find gentlemen. The SphereCastAll used at the end of the lecture to make the cursor area bigger works like a dream. I love being able to click in the general area and it magically knows what I’m trying to click on! …though I was getting good at pinpointing the pickups and the tiny sphere colliders I’d made for them chuckling No… my issue arises in the first part of the lecture in the AIController when the enemy is shouting out for allies… So, since this SphereCast doesn’t travel anywhere, and is fairly large (I went with a radius of 5), there can be fellow enemies totally within the sphere at the moment it “bursts.” …and according to my debugging of hits[ ], the array returns empty. …anyway, here’s the code you had requested. I rewrote it and re-tested it, and a unity that is only two units away is completely ignored.

…scratch that. Since writing the above, I fiddled with it a little bit more and, just to be on the safe side, copied Sam’s code exactly. Turns out, a SphereCast with 0 maxDistance won’t work with Vector3.zero as the direction, while Vector3.up works fine. So… it’s working the way Sam said, but any idea why one works and not the other? I have to confess that Vector3’s still confuse me a bit. …also, hurray because I got to learn about SphereCastAll and OverlapSphere!

Interesting. It appears that direction is important for a SphereCast (and SphereCastAll). From what I can find with a very quick search is that the SphereCast only detects collisions at its ‘front’. Someone’s tested it (see this Unity Answers answer).

So without the direction there is no way to determine the ‘front’. I suspect it may be an optimisation that Unity implemented.

So the conclusion is that if you’re not going to be moving the ray, perhaps use OverlapSphere

I think this just applies in general.

Personally, as I’m working through a sort of “let’s put together the best of the RPG and Third Person courses into a single project”, I’m using a Targeter child GameObject that fires an event to tell the controller that the Player (or perhaps a rival faction) is in range. The Targeter just uses a simple Sphere collider.

1 Like

Absolutely. OverlapSphere very seldom enters my thought-vocabulary. I may want to use it more often but generally, I use sphere colliders

Either one consumes resources… either the Physics system is raising the OnTriggerEnter for you, or you’re doing it in Update()… I haven’t profiled it, but I’m going to be that the extra overhead in the Update() method is costlier than the Physics engine just adding one more colission check to it’s duty list.

Thank-you both for your responses :slight_smile:

I read this late Friday and was excited about it, taking yesterday to run it over in my mind and thought it made a lot of sense, so… I decided to give it a test this morning with 5 enemies stationed equidistant in a cross pattern and manually cycling the SphereCast direction between Vector3.left, right, up, down, forward… I had anticipated that with right, left, and forward at least, targeting the middle enemy would only alert four out of the five (all five starting out within the 5 unit radius sphere, and already oriented to face the player), but in each instance, all five enemies were alerted. So I’d have to run some much more detailed tests to figure out how SphereCasting actually works (perhaps the initial “burst” is in all directions, and then optimizes only its forward face?). Anyhow, I’m not going to attempt at this particular moment :slight_smile: , so I’ll content myself with how far the discussion has come, and thank-you both very much for the input. I suppose my short-term takeaway should be that Vector3.zero doesn’t count as a direction :smiley:

So… if I’m understanding this correctly, instead of using Update() to check if the player/target is within range, you have a sphere collider set to the AI’s detection distance and use OnTriggerEnter to make the system event-driven, then… toggle it off (or enter SuspicionBehaviour) on OnTriggerExit? The way I’m imagining it seems like a lot less overhead. …and if I’m understanding it correctly, it could even be used on the Player. For instance, clicking on a navigation point doesn’t enable their SphereCollider, but clicking on an enemy enables it and sets it to the weapon’s range… and if the enemy is within said range then switch to an attacking state? is thinking while typing and isn’t sure how much smoke has already filled the room …am I somewhat describing what you’ve implemented? I really like event-driven programming, so any way to stop Update() from constantly having to ask “Are we there yet?” is lovely :laughing:

You’re right on track.
The data is still being polled on a regular basis, but not in Update() and by a highly optimized physics engine (PhysX by NVidia) that smokes our silly distance checks every update.

1 Like

Wow, I learned a lot in this discussion! …almost makes me want to make more silly, random mistakes and post about them! :laughing: Thank-you very much, both of you, for the great responses! I’m hoping to start on the Inventory RPG course this week, so I’m sure I’ll see you there :slight_smile:

I’ve been doing this coding stuff since the Reagan administration. I can tell you that I have learned a LOT of what I know about coding from silly random mistakes. :slight_smile:

1 Like

This has been bugging me, so I whipped up a quick simulation to see if I could figure out how a SphereCast actually works (Spoiler: I’m not sure I succeeded :smiley: ). I used a button that triggered the SphereCast, configurable with a serialized Vector3 for direction and float distance (pictured), which collected an array of hits, accessed the hit’s renderer and changed the material colour. The center green sphere of each group of three is 5 units away from the central white sphere, and the SphereCast’s radius was also set to 5 (the transparent sphere has a 5 unit radius for reference), so that center green sphere is half inside the SphereCast, while the inside green sphere is totally within, and obviously, the outer sphere is completely outside. I was going to include a video, but the gif came out really small, so I just took a couple screen shots.


The results of the 0 length SphereCast were the same for each direction (Vector3.up, down, left, right, forward) and as we’d already discovered, it simply failed to work with Vector3.zero. The second screenshot is simply a SphereCast with length of 20 to trigger hits in the left-hand matrix.

So… I can’t guarantee that SphereCast doesn’t have a leading edge, but… it almost looks to me that Unity just generates a capsule and reads collisions with it. Either way, with a length of 0, it works exactly how Sam needs it to, and (seemingly) exactly like OverlapSphere. grin

Anyway, this was a fun way to pass an hour and sate my curiosity :slight_smile: and I figured I’d share the results before this topic was closed, so hope someone finds some value from this. Cheers!

…sometimes I just can’t turn my brain off… It occured to me that I’d been using SphereCastAll in the previous post, and realized that I didn’t know how a single SphereCast could act, so code was tweaked, and I have found the leading edge! When using SphereCast (with the same parameters as the above SphereCastAll (I called them SphereCasts, sorry, that wasn’t very precise of me sheepish)) the operation ignores any object touching the sphere at the start of the cast, and then registers the first object touched by its leading edge.

So, while 12 green spheres were ignored, the SphereCast triggered a colour-change in the first green sphere that it touched after it was called. So yes, SphereCastAll may not have a leading edge, and could act like a capsule, SphereCast definitely behaves like it has a leading edge.

This really is my last post on the topic! :smiley: I think… hope? …maybe. Shush brain!

Privacy & Terms