Sunday, November 30, 2014

Swarm Force

As part of the new direction with only fighting bosses in arena's, attacking a boss weakpoint is dependent on how hard the overall swarm hits the weakpoing. In order for there to do damage, the swarm needs to build up enough force to pack a punch past a threshold. That may be hard to determine by looking at the change of rate of the swarm. Part of my task was to create a way to show how much damage the swarm can do when they strike that is independent of any enemy weakpoint. My first approach was to change the color of the swarm based on their speed; however, when the swarm takes damage, they also change color to signify the swarm has been hurt. So I changed it to have a trail behind the swarm that indicates how much force they would impart on impact. I thought using a particle effect that would emit behind them would create a nice effect. Part of the problem was that the change in force direction was so much that the emitting particles would go in all different direction. It was also hard to distinguish between the particle effect and the swarm. Trying to determine another way to have a stream behind the swarm, I decided to look into the trail renderer that I happened to see when selecting the particle system.

The trail renderer draws a line based on its change in position. While it was possible to change the trail renderer's length based on velocity (or force), I decided it was better to change the color of the line based on a gradient using the velocity (or force). Originally, I had the trail renderer follow the position of the geometric mean of the swarm. Based on the advice of my teammates, I added the trail renderer to each minion in the swarm.

The Trail Renderer normally

The Trail Renderer when the swarm has enough force

Based on the aethestic value of the swarm emiting a trail as they orbit the orb, we all decided this was the best way to show off the force of the swarm and how it will affect the weakpoint of a boss. This does create some performance issues which will be addressed; however, it is not the bottleneck as the collision between the swarm and an enemy weakpoint is where the biggest performance spike is. 

Friday, November 21, 2014

Gravity Well

During class on Tuesday when we presented the sprint build of the game, it did not get the best reception. The main complaints was that they felt the mechanics of the game were too boring. The past two days, we thought about ways of either saving the mechanics we have now or creating a new mechanic that could be completed before two weeks when we have to present at EAE open house. There were two mechanics that we were split on at the meeting: using a gravity well and splitting the swarm between the two joysticks. The split between two joysticks is using the same mechanics as before, except you get rid of the central character and manipulate the swarm the same way. At its current iteration, each minion of the swarm would go towards the joystick point that they were closest to and use boid rules to swarm around that central point. The player could then use the two points to direct the swarm by attacking the enemy at two points and slamming each one into the enemy at its weak point. My idea was to use a gravity well that the swarm would be attracted to. The player could then use the right joystick to add direction onto the swarm to create a directional attack. If the swarm go too wild, then the player could create a dampening field that would increase its gravitational pull and slow the swarm caught in it to an insignificant speed. I was tasked to prototype this so that the team could play with both and get a better idea which mechanic would be more fun.

The above video shows that implementation (though it still needs work with fine-tuning). When it starts, it just shows the swarm orbiting around the orb. At about 15 seconds in, I move the right joystick to add the offset on the swarm and give them direction. At about 36 seconds, I use the dampening field and show its effects.

In video games, there are two main ways to tackle a physics problem. The first way is to fake the physics and use animations and scripted events to imitate a physics problem. This gives the programmer and player more control over the object; however, the downfall is that its too jilted and stiff and  doesn't look right. The second way is to use a more dynamic approach by essentially creating a simulator that calculates the next points using known physics equations. This create a more natural feeling to the movement of the object, but it takes control out of the hand of the player and is damn difficult to get right. The difficult part is all the constants and variables. It would be a miracle if I could use the gravitational constant of the universe for finding the force of gravity, But it such a low number that its decimal is on the order of magnitude of 6. This would make objects too slow. Use a number too large and the objects move too fast and too out of control. There are many things that can go wrong when using the dynamic approach, but if fine-tuned correctly can create such beautiful motion and animation with an amazing feeling. That's why I like using the dynamic approach over the static, scripted approach that many of my friends have tried getting me to use. I too must accept facts that if we can't get the feeling we want, we don't have the time to play with it and get the right feeling in under three weeks. We may have to use the scripted approach or go with another mechanic.

Wednesday, November 19, 2014

Globals Maybe Evil

95% of the time, global variables are more evil than goto. Good software design demands that a variable not be more accessible than it should be. If other objects need the variable, then there are ways to pass the information without making it available to everyone and without checking for misuse. The only time a global should be public if its a static const (or just a const), since there is no possible misuse since other objects can only read the data. In game development, using static consts is how properties of objects, such as velocity at certain states or values that a conditional needs to pass, are kept and defined. The main complaint of this approach is that the value cannot be reassigned and the game will need to be recompiled in order to try a different value. This simply isn't true, with knowledge of debugging, static consts can be changed in memory to reflect a different value without recompiling. With these tools, Unity gives the use of creating public globals that can be edited from the inspector. These values can even be changed while the game is running.

To many, this option seems quite attractive. When I started in Unity 3 years, this option seemed attractive. Now that I am a much better software engineer now than I was then, I know better. The only value of this approach is passing in game object prefabs and textures than using GameObject.Load() which has worse performance than using a public variable. Even then, there is no reason to make it public for all to read and change without testing the data. Data should always be tested, no matter who's giving it. By using a single point of entry for data to be written to a variable, such as a setter, then there it can be safely assumed that the variable used from then on shouldn't need additional testing. However, if the data can be changed from anywhere at anytime, then the data will constantly need to be tested and vetted for correctness. This is a horrible practice and requires more code than is necessary.

In Unity, all game objects are spilt into two: the global prefab and a specific instance in the game. Public values can be changed in both with the prefab affecting all instances, but changing the value of an instance will not affect the prefab or any other instance. This seems to make sense on the surface, until you realize what these values are suppose to represent. These values are suppose to replace static consts that can be changed to get the right value. The speed of a game object should not be represented in the inspector to be changed arbitrarily, instead it should have const values that can affect the true speed such as acceleration, min/max speeds, or speeds depending on state. Why would these values need to be changed arbitrarily on instance. Why should one instance need to have a larger max speed than another? If such a difference needs to established, then the variable should never have been a static const in the first place. That value should be established in the object itself or established in the object that creates the entity and passed to the newly created entity.

If the public variable can be affected in two different places, that creates many subtle bugs that may be hard to track. When testing a game object, the values are generally changed in the instance inspector and not the prefab. When the right values are found, more often than those changes aren't saved back into the prefab. Sometimes they are, and sometimes the values are directly edited into the prefab; however, there have been many times that I saved a value in the prefab, but it didn't percolate into all the instances of the game object.

Despite everything I stated, there is always the biggest reason why using public variables to directly impact what should be a static const: anyone can access it. I already showed that when letting anyone access it, you need to test the data constantly; however, this approach gives more scope to the variable than it needs to. The only object that should access the variable is the inspector. No other game object, or Unity Engine, needs to access this variable and the fact they do have access is a very scary thing. I feel that using a public variable give way more power and control to everything than what is gained from the convenience of directly updating the variable at runtime. A global variable has created many subtle bugs that are hard to track down and fix.

At some point, the team at Unity decided this was one of the worst ideas they had, so they implemented measures so that you could use the inspector and keep scope. By making a variable private, but serializable the inspector can still gain access to the variable and the variable is given the correct scope so that no other object can access it. Using serialize also opens the door to many other options for the inspector. By creating structs or classes that encapsulate another object or makes a field more readable: for example

struct Range
    float min;
    float max;

This creates greater readability and makes the inspector much nicer to read so that we don't need two variables for min and max. Despite these improvements, there are still problems. These values are still meant to represent static consts, but are still represented by private var. While only the inspector and the object they are assigned to can only update them, that means the object it is assigned to can still update it. This is not the behavior we want from the object and we have to create a contract with the programmer that they will not change these variables in the object. Even though I wish these values could be made static const and still accessed from the inspector, I understand the difficulty in doing so and why it may be non-existent on a their list of priorities when there is so much that hasn't been incorporated (such as a draw line method in the GUI). You can't win every battle and I will take compromise where I can. A private serialize value that can be edited is a hell of a lot better than a public global.

Are globals evil: yes, yes they are. But, there are many times in which they are a necessary evil.

Friday, November 7, 2014

Level Design

For this current sprint, my task was to create a pipeline and tools to design levels so that the designers could then design their own levels for the game. While the task itself wasn't that hard, there are many design decisions that I had to make with the team to ensure the process of building a level be as efficient as it can be. The very first thing I wanted to get solved was borders. This is an underwater game so borders aren't that simple. The bottom of the sea floor is obvious, but there isn't an upper limit. Where does the player stop, a certain depth below sea level, or can they surface and that's the border. While there isn't a good solution for the game yet, we decided on a soft border in which if the player gets too close to the surface, then some force (pressures of water or too much light is bothering) will force them down. Also with that soft border there are some design decisions. How will it force the player down. Does it just add a vector onto the player's trajectory that is so great they are forced down, or does it take control out of the players hand and play an animation as the player swims down to the correct level. I chose the latter as I feel it has the most aesthetic value to it and can give a more logical reason why the player can't swim too close to the surface. I also chose it because it gave me the opportunity to change the architecture of Entity types (Player, Swarm, and Enemies) to be more closely related in terms of assignment and state control. I feel that I may need to change it to the more dynamic approach of forcing the player down, but not taking control away from them. Fortunately, I've added a way to have multiple ways of being able to move the player down so that it is easy to switch based on designers choice or if there is some other choice of the type of soft boundary.

Hard boundaries (moving into a wall) was a lot easier, but I still had to experiment with ways to create hard boundaries in the most efficient way. The initial way I did it was to use a series of rectangle that would act as the collision wall. It would be a series of them, because they could be used to approximate a curved wall since Unity does not have curved lines and it would be too computationally heavy to do collision detection with a spline. While this method did work and is the standard way of doing it, making the rectangles took way too long, was hell trying to scale, rotate, and move each rectangle, and there was a possibility of a gap in the wall potentially creating future, hard to find bugs. I learned of an alternative way using Unity's edge collider. It allows the designer to create a line that can be subdivided into many lines that can be used to approximate the curve. It is the same principle as the rectangles, but it much faster to create as the designer only has to select a midpoint between the two endpoints and move it to where they need it. The only problem is which certain types of collisions in which the object is moving at a great speed. The edge collider has a much smaller room for errors as opposed to the rectangle. This problem doesn't come up to frequently and if there is the possibility of either capping its speed or using a predictive collision to determine if it will hit the edge using discrete steps. This would be much easier than the added buffer that rectangles give especially since the edge collider will cut down the time it will take to set up the walls and it is much easier to fine-tune and fix later on.

The placement of enemies is a very important. An enemy that lies in wait in a corner of the level that is quite away from the player will not only suck up important CPU, but depending their AI will chase the player from across the level. One of the fixes I have for this is by using an enemy trigger. When the designer places an enemy in the level, they can hook the enemy up with a trigger that when activated will create the enemies offscreen and allows the enemy to attack the player saving CPU. The main problem with this is placement of the trigger, especially in a more open-space world. The trigger can only be so big, and it is a rectangle, and creating more than one for the same group of enemies can open up some potential bugs. While it is great in some cases, it is not a catch-all. The other solution, would be to define their behavior if the player is a certain distance away from them. If the enemy can't see them, then they do some default state such as patrol or try to kill each other, and when the player gets close enough they go into their attack state. While this may solve the enemy not going across the level to kill the player, it does have a bunch of enemies that aren't useful taking up CPU. A fix to this would be if they were a certain distance away, then to become disabled so they aren't taking up CPU. This will probably be the best since when the player is far enough away, then they aren't doing anything, and when the player is close enough, but not too close to attack, they are activated and do their default behavior. While it would be nice for the enemies to do their default behavior no matter where the player is, this just isn't feasible in terms of performance. The best bet would to use the trigger where possible and if that doesn't work, then to use the default behaviour if the player is close enough.

Those were the most basic things that I covered so far. There are still some aspect that I haven't talked to anyone else, such as when a level ends, how it decides the next level to go to and where the designer can specify that. The level design is very iterative and will change as we get a better idea how we want our levels to look and feel.