Lots of UnitySteer changes this last week. Mikko Mononen was kind enough to comment on a neighbor avoidance approach I was trying out, and suggested something based on his own DetourCrowd. I promptly implemented it, only to run into an oscillation problem. After a quick review, it turns out that the oscillation wasn’t being caused directly by the RVO implementation, but instead by some leftover details from OpenSteer.
You see, previously UnitySteer’s Vehicles kept track of their speed, and calculated their velocity by projecting the speed along the vehicle’s forward vector. This is the way OpenSteer does it, since it seems mostly focused on vehicles that act that way, but it has the effect of assuming that the vehicle can only move forward and backwards – which causes a problem when I aimed to create vehicles which could side-step (necessary for move natural agent behavior). One could apply a sideways force – and several behaviors were doing just that – but all the vehicle calculations assumed that the recorded speed was being projected along the Vehicle’s forward. This messed up future vehicle position predictions when the agent was moving slightly sideways but not enough to turn, since the agent’s future position did not lay along its forward vector.
Needless to say, this is not a behavior that you want if you’re implementing cars, but for my bipedal agents it is perfect.
While I was at it, I’ve also changed the way that Radars are used. We previously kept track separately of a layer for obstacles and one for vehicles, which was just silly. Right now we just have a property for the layers checked, and any gameObject with a DetectableObject component which is not a vehicle will be considered an obstacle.
These are not the only changes, however. The latest modifications are:
- Steering behaviors are no longer ticked independently. Autonomous vehicles will now add to the priority queues a method that is ticked for calculating and setting the Vehicle’s Velocity, which will then be applied on every FixedUpdate.
- Steering behaviors no longer cache the force value, and will calculate it every time that the Force property is queried.
- The vehicle’s Velocity is no longer estimated based on speed and the forward vector. Instead I am recording the actual velocity applied to the vehicle.
- The vehicle’s Speed is now no longer a property you can set, and is instead calculated based on the vehicle’s velocity.
- Removed Radar.ObstacleLayer. Any DetectableObject that is not a vehicle will be considered as an obstacle.
- Removed Radar.ObstacleFactory. DetectableObjects should know how to create their own obstacles if they’re not spherical.
- Updated other steering behaviors to work with DetectableObjects.
- Added methods to Radar to create a list of DetectableObjects to be ignored.
Finally, I’ve begun using more Linq during this process, because I really like its expressiveness and it has served us very well on the game. Unity however has issues with Linq on iOS, since it seems to be ignored by their AOT compilation – your game will build just fine, but you’ll get runtime exceptions once you deploy. This means that this branch is not suitable for iOS use until Unity improves their AOT compilation support for generics (which by their own admission is quite limited).
As before, this is an experimental branch, so here be dragons. Like I mentioned on a commit log, this is looking more and more like UnitySteer 3 instead of a point release, but I’m happier now about the general state of things.