I’m trying to write an animation job that performs foot-fixup against terrain as part of a PlayableGraph. However, both Physics.Raycast() and RaycastCommand.ScheduleBatch() complain about not being on the main thread.
What’s the correct way to raycast from the playable thread? If not, is there a way to synchronize with the main thread?
For reference, here’s the log produced by attempting to kick off a raycast batch through the job system, which I assumed with the idiomatic solution:
Point of clarification: the foot location that we’re querying-from is coming from the AnimationStream itself – we’re adjusting the incoming animation-pose with ik, so the position isn’t known before the playable-graph kicks-off evaluation.
Not yet. I have some hacky workarounds (e.g. save/publish query position to main thread, perform raycast next-frame, apply previous-frames’ result with some adjustments), but the results aren’t ideal since there’s a first-frame-pop and a frame-delay.
Some folks on twitter pointed me at [this megathread]( Animation C# jobs in 2018.2a5 page-5#post-5246465) where people are discussing some of the more technical/experimental aspects of PlayableGraphs, alongside devs, so I x-posted there yesterday (fingers-crossed).
There is no way to do that, as you cannot schedule jobs from inside another job, access the main thread from a job, or access job data from another job.
Here is a reasonable workaround, which is commonly used:
Do your raycast before the job runs by approximating the foot position by using the previous frame position and velocity, along with the current frame deltaTime.
As long as your animation is reasonably smooth (no pops), the result is pretty good. It’s best when the foot is not moving much, which is where the player will have time to look at it anyway.
In most cases, you should also be averaging or stabilizing your IK target position a bit, if you don’t want your foot to repeatedly pop when it’s right on the edge of a steep drop.
Finally, you should store your raycast result position in character space (as opposed to world space), so that your foot doesn’t point to a random spot in space if you ever teleport your character. (Well either that or disable IK for a frame when teleporting).
Yeah, as noted in my first reply, I’ve already implemented that workaround. The frame delay has mixed results. My next test is to precompute a “collision texture” of the ground-neighborhood that can be sampled during the animation job, which is looking promising, but still feels like extremely unnecessary and is a big liability both in terms of tuning, maintenance, and performance.
Not scheduling jobs from other jobs is an impractical limitation. There’s a whole class of useful cross-system integrations (animation/physics, animation/audiomix, etc) which we’ve implemented on Unreal at my dayjob which won’t be portable to Unity. We don’t need to access internal data, just results – the idiom is akin to “goroutines”: the parent job kicks off other jobs, suspend itself until they’re finished, then gathers their results and resumes execution. Is there a venue for feature-requests where I could post this feedback?
Sidebar: In practice only swimming animations are “reasonably smooth” (I would know, I wrote the animation controller for ABZU, lol) – real animations are erratic by-design (animators want to emphasize key poses, not tweens).
Alternatively, if a PlayableGraph is the level of abstraction to “compose jobs” then perhaps there can be a “RaycastPlayable” which could be interposed between, e.g., my AnimationMixerPlayable and my AnimationScriptPlayable?