For a while now, I've been working to find a solution to get my enemies flying in different patterns with the most minimal amount of overhead. Tonight I think I came across my final solution.
One of the more unique things about RLIC is it is happens around
a planet. So it plays like a side scrolling arcade shoot 'em up, but when you get far enough horizontally, you are back at the start of the level, because the horizontal element is essentially a heading around the planet. It's kinda cool in theory. I have two functions that help me translate and orient any entity with certain properties with respect to a heading, a height, and the center of the world.
In practice, it's really difficult to program everything
in the game with this consideration, especially when it comes to the movement of the enemies. In a normal, orthographic game, you'd lay out your cool bezier curves and be done. Simple enough. Now, wrap that around a planet and your ability to express those patterns easily becomes difficult because your curves don't respect the curvature of the planet.
The Solution, take one (path of least resistance, worst results):
I've messed around with many different methods to solve this issue. One of them involved not using animation or bezier curves and just trying to math the problem to death, without any visual construction. This has proved to not give me the flexibility I need to express the Galaga-like patterns I want (likely due in part from a lack of deep math knowledge/practice). I can't really make an enemy bob one second and then dive towards the player using math without spending half a day. I just wasn't getting cool enough motions with having them simply moving along sine waves.
Almost the solution:
Once I realized how much I needed to find a curve solution, I started tinkering with the idea of having proxy objects animate in cartesian coordinates, like a normal game would allow. Each robot would connect with a proxy object from which the robot would glean the position and compare it to the last position the robot had for the curve animation. Using that, I can calculate an offset, feed it into my aforementioned planet-centric transform and orientation functions, and get something that worked relative to the robot when it started sampling the proxy object. This is awesome, but I was worried about the overhead of having so many proxy objects animating. If there's 15 robots on the screen, I would need 15 animated proxy objects, I still felt like there was a better, more efficient solution.
The current solution:
Refusing to believe I had an optimal solution, I kept an eye out for a better way and kept poking around answers.unity3d.com
and got an idea from a few posts that I could actually query an animation using a point in time and do something like the following:
AnimationState _animState = this.animation["TestAnimation_01"];
float length = _animState.clip.length;
float newTime = Random.Range(0, _animState.length);
_animState = animation["TestAnimation_01"];
Debug.Log("pre: " + transform.position);
_animState.time = newTime;
This code effectively takes the animation, Test_Animation_01
, and pushes it to a particular time. Then, using Sample(), it forces an update. This might be obvious to some of you guys who use Unity, but I had no idea I could sample an animation from any point in it's duration! From there, I can simply return the transform.position of the GameObject this animation curve is attached to and the robot who asked for it can use it as it wishes.
The opens up the possibility that every robot that needs this pattern for movement in the entire level can sample this AnimationClip from a Manager, ask it what it looks like at a point in time, and free it up for another to use it. We now have n-1 less guys that need to be updating an animating Animation Component every frame.
Here's my little crude sandbox proof of concept for the "curve sharing". This is really crude and still a bit off of what I'll need in my final implementation, but wanted to post regardless it in case anyone had any need for something like this. So again, essentially there's one object with an animation definition and the others are simply asking the single instance to simulate what it looks like at a point in time with respect to when it was activated (waitTime).web democurvesharing.unitypackage
That's about all I have for tonight. This is really going to allow us to be more expressive with how the enemies move, not to mention cut down on the time to tweak the movements.