Programmer’s Weekly: So you like them shadows?

Written by: Tomas Sala

So you like them shadows?

As you might know Unity3D now supports realtime shadows on mobile devices, woot!  For those interested here’s the official announcement of 4.2: http://blogs.unity3d.com/2013/07/22/unity-4-2-has-arrived/

But, like us, your first response is probably: “That’s never going to fly in my mobile game, it’ll suck down frame-rate like nobody’s business!”, and you would be partly right. But it’s not the whole story. If used correctly and carefully it is possible to add a whole new layer of visual depth to your game.

First of we need to talk about what type of shadows unity3D allows on mobile devices. This blog post is not about shadow-maps, but about real-time shadows. This means shadows projected from a directional light onto your scene. Shadows that are rendered every frame, and thus dynamically respond to your scene and light..

Some basic rules

  • Only hard shadows are supported, (we can soften them up in the shader pass I’ll discuss later, but that’s not advisable processing wise)
  • Only 1 directional light is allowed in the scene.  
  • Basically, only low-resolution shadows are practical on most devices (even the nexus 7 (2nd gen, 2013) will take a substantial hit from medium resolution shadows)

Now a couple of main problems pop up, specific to most mobile games.

  • Most mobile games don’t use lights due to the added rendering cost, or are based on unlit atlassed textures, vertex colors or shaders optimized to work without light sources.
  • Draw Calls and batching, these related issues are a pain when doing mobile development. It just got a whole lot nastier with real-time shadows.

So in this week’s blog post we’ll be looking at solutions for each of these two problems.

Solution 1:  Differentiate between what needs to cast a shadow and what needs to receive one.

First off all the most basic rule is: Don’t use shadows where it’s not required, and know the difference between a receiver and a caster.

A shadow caster is an object that casts a shadow. You need to minimize the amount of these. The fewer casters, the fewer shadows and the faster the calculations are. This works down to detail. So if you have a building, make sure only the base structure casts a shadow. Don’t do the chimneys, windows, doors, and other details! They have no need to cast a shadow. Make sure they are turned of in the mesh render component in Unity3D.

shadow-caster

 

A shadow receiver is the object that receives the shadows. First of all, make sure that an object that receives shadows does NOT cast shadows. So separate ceilings from floors for instance, and have the floors be shadow receivers, but not the ceiling. (Or not even the walls. Remember, because you have only 1 directional light, it’s practical to make it a top-lit scene).

Now splitting up your objects might result in additional draw calls,but we’ll deal with those later.

Solution 2: Adding real-time shadows to an Unlit or custom-lit scene.  

So a basic trick transferred from the days of yore to modern mobile game development is the use of vertex colors. Vertex colors allow you to not just paint a model, but actually light it (with, for instance, a radiosity solution) and then save it or bake it into the vertex data of the model..

That will look something like this. A basic vertex colored lighting solution, merged with a custom shader.

vc_colors

This gives the Illusion of lights without using any. Add to this light-maps or pre-lighted textures and you get  a static object, that looks like its lit. Additionally, you can shape the visual style to be unrealistic, cartoony or anything else.

 

Now that your game artists have gone through all the effort to make something look nice without light just to save performance, it’s un-logical to simply add a light to have shadows. Basically a double whammy, the shadows need to be rendered, and the light needs to be calculated.

So why not just turn on shadows? 

Here at Little Chicken Game Company our artists write their own shaders in tools like the Strumpy Shader Editor. The disadvantage of this is that you export surface shaders. To turn on shadows, you need to create a shader that has an output to diffuse. This causes the shader to become lit: lighting your object and at the same time creating shadows. The moment you connect an input to emmisive to create an unlit shader, your shadows disappear. And we don’t want to light the object, we only want the shadows.

Solution: Add a renderpass to your unlit surface shader.

If you really want shadows, you’ll need to find a way to add shadows to your emmisive surface shader. (fragment shaders might be faster and simpler, but when you’re stuck to strumpy and don’t know how to code fragment shaders, this will do the trick)

So we’re going to add a shadow pass to an emmisive shader. I’ll be quick and just give the shader code for the second pass.

—————code————————————————————————————————–

Pass
{
Blend DstColor Zero
Fog
{ Mode Off
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma fragmentoption ARB_precision_hint_fastest
#include “UnityCG.cginc“
#include “AutoLight.cginc“
struct appdata
{
fixed4 vertex : POSITION;
fixed4 color : COLOR;
};

struct v2f

{
fixed4 pos : SV_POSITION;
fixed4 color : TEXCOORD0;
LIGHTING_COORDS(1, 2)
};
v2f vert (appdata v)
{
v2f o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
o.color = 1;
TRANSFER_VERTEX_TO_FRAGMENT(o)
return o;
}
fixed4 frag(v2f i) : COLOR

{

fixed atten = LIGHT_ATTENUATION(i);

fixed4 c = i.color;
c.rgb *= atten;
return c;
}
ENDCG
}

—————code ends——————————————————————————————-

 Just paste this after the ENDCG of your regular shader code, in the un-compiled unity3d shader. Make sure you use  FallBack “VertexLit” at the end of your shader. (FallBack “VertexLit” will also enable shadows in your fragment shaders, it’s way easier)

Example, here I’ve only used this additional shading pass on the ground surface. On nothing else. All the shading and colors you see are not created by the directional light, but by the shader, combining fresnel effects, ramps and vertex colors. And finally a shadow pass.

sample_shadows

 

Solution 3:  Batching and drawcalls.

So we now have two things: shadows in our unlit scene and a selection of objects that cast shadows, and an even more limited number of objects that receive shadows.

Doing this separation tightly, will already decrease your drawcalls substantially compared to blindly turning on your directional light with shadows.

But there is an additional problem, materials that are still shadow capable are not batched. In the documentation it states that objects that cast or receive shadows are not batched. But the problem goes deeper, any material capable of casting shadows (or possibly, that is also used for shadows) is not batched!  So in Oberon’s Court I made the mistake of having one solid black material that could cast shadows.

This shader:

—————code————————————————————————————————–

Shader “Oberonscourt/Color”

{

Properties {
_Color (“Color“, Color) = (1,1,1)
}

SubShader {
Color [_Color]
Pass {}
}
Fallback “ VertexLit“, 1
}

—————code ends——————————————————————————————-

Now I stupidly assumed that using this shader on an object that did NOT cast or receive shadows would allow the object to be batched. This is not true! Even objects that do not cast or receive shadows but have shadows enabled in the shader will not batch. (so it seems, I could be wrong, but I’ve got the drawcalls to back it up)

So the final trick was to take any object that receives or casts no shadows, and make sure it had a material that had no shadow capabilities. In the sample case I removed the fallback vertexlit code from the shader

To optimize even further I changed the shader on materials that where on a shadow caster, but did not need to cast a shadow to a non-shadowed version of the same shader.  Practically this means the eyes, the mouth and other small props that where part of the skinned mesh. These are part of a shadow-casting mesh, but now no longer cast any shadows, and reduce the drawcalls. This is especially true for characters with many small un-skinned sub-parts.

Its probably more logical that any material with a shadow capable shader that is also used in an object that does NOT cast or receive shadow(so used also in non shadow, and shadowed objects). Causes the instance of the non casting material to be NOT batched.. (A hunch),,  The solution is the same no matter what the cause. Do not reuse a material you’ve used on a shadow caster or receiver, on an object that is not casting or receiving a shadow. Otherwise the non casting/receiving object will not be batched.

 

Conclusion

Having done these steps, and making sure that only a few objects actually cast shadows, I was able to create the environment for the game and have it run on most android 4.1+devices.  An added advantage by skipping the lighting and keeping the shadow reception shader unlit, I can now turn off the directional light and shadows, and it will look exactly the same (without shadows).  Which is great for an ingame settings menu for instance.

Do remember that shadows are now possible and performance can be maintained, but still if you expect anything less than a doubling of your drawcalls, you will be disappointed.

To finish it off here’s a side by side of with and without real-time shadows. I hope the above solutions and workflow will help you out in implementing shadows on mobile devices.

without-shadows


Cheers,
Tomas

216,972 total views, 15 views today

Programmer’s Weekly: Debugging with ducks

Written by: Mark Bouwman

Eh, what?

Yes, you read it right: Debugging with ducks. Today I wanted to talk about debugging a little. Of course I don’t have to; programmers never create bugs, right? All works as intended! It’s not a bug, it’s a feature! It worked fine just yesterday!

Yeah, sure.

But for that one special case where you just can’t find the bug, there’s the “Rubber duck debugging”. It’s quite simple, really. All you do is explain your code. Line by line. Out loud. To a duck. This might sound silly, but it’s actually a pretty good way to debug your code. There is reason and logic to this method!

 

Rubber duck

It’s a rubber duck. 

Well then, how does it work?

You start off by explaining to the duck what your code is supposed to do. With a clear goal of what you want to explain set out for you, you then explain the code to the duck, line by line. Each line you say out loud, telling the duck exactly what the code does. More often than not you’ll find out what was wrong somewhere halfway along the code.

You might be wondering: “Why does this work?”. The magic lies in explaining. There are so many advantages in doing so.

When you take the time to sit down and really look at your code, you’ll find bugs and errors in your logic quicker. You can stare at code all you want in order to find your bug, but you won’t actually see anything. When you have to explain the code however, you re-read all of it carefully. You actually read it in order to get terms and sentences to use for your explanation, in order to get mental ‘checkpoints’ for the story that you’re about to explain. When doing this, you’ll find flaws in the flow of your code quicker.

Another reason the rubber duck debugging works is because you speak out loud. Saying things out loud helps as you take more time for each separate line of code. Also, when you want to say something out loud you first have to clarify your thoughts. You have to turn all the information you know (and assume to know) into something you can put into words.
Thinking out loud also triggers different parts of your brain. Not only do you think about it, but you also hear your story and talk about it. These are different inputs for your brain, allowing it to process all the data in different ways.

Another thing that’s so great about the rubber ducking method is that you can do it by yourself. You don’t need to bother anyone, and no one will really bother you (I mean, c’mon.. You’re talking to a rubber duck. People should be afraid to bother you). It often helps in finding solutions to the problems you’re facing without having to feel bad about resorting to someone else. And when it doesn’t work out, you’ll have a clear view of the problems and the goals. This helps when you have to explain it to a fellow programmer.

All in all, debugging with a rubber duck is a great way to think about the code you wrote. It helps to clarify your thoughts, it helps to think about the flow of your code, it helps to see things you’ve missed. It’s a great way to debug!

And let’s be honest here: who doesn’t like to have a rubber duck on his desk?

1,859 total views, 1 views today

Programmer’s Weekly: Shadow variables against hackers

Written by: Mark Bouwman

Hacking. It happens. A lot.

I don’t think I have ever played a game that people did not want to hack. Even for the smallest flash games you can find some sort of way to hack them. In (offline) single player games it’s not all that bad though, there’s not really all that much for a developer to worry about. However, when there are highscores or even actual rewards linked to the performance of a player, hacking suddenly gets a pretty important thing.

 

It sucks.

There’s only little ways to completely protect your game against hackers. It’s a pity, but you can at least try to demotivate hackers by making it harder for people without a lot of knowledge to hack your game. This week, I wanted to take some time for the very first line of defence. Something I like to call: shadow variables.

 

So we use shadow variables?

Indeed. And in case you’re wondering what a shadow variable really is: a shadow variable is a variable that lies parallel to the actual variable you use for stuff like keeping track of scores. It might sound vague, but allow me to explain.

Let’s say you have a variable called ‘score’, in which the player’s score is represented. Every time the player picks up an item: score++. When someone uses something simple as Cheat Engine, they can easily track a score that’s visually represented in their own interface. They know the value of their score, so they scan the flash memory for that value. Within a few scans, they got access to the memory and are free to change that variable to something way off the charts.

This is where shadow variables come in.

Other than the variable ‘score’, we also have a variable named ‘sv1’. The name doesn’t mean anything but it’s good practise not to name the variable anything score related, just in case the hacker can see variable names. When score gets increased, we also increase the shadow variable. But not by one, no, we increase it with a set random number, which we generated at the start.

Every time you change score, check it against sv1. If score isn’t sv1 divided by the random number, it means someone tinkered with the score! Then you can either kick them, nullify their score, or just allow them to continue with their actual score.

This way of protecting important variables (life, score, time, bullets… anything gameplay changing really) isn’t all that complicated, but it definitely works as an efficient first barrier!

1,952 total views, 1 views today

Programmer’s Weekly: Making difficulty of levels less difficult

Written by: Mark Bouwman

Implementing difficulty in levels isn’t all that hard! Use random levels and change cut-off values!

Yeah, right. Be like that. “I don’t care about difficulty; I just change cut-off values for spawning things when using math.random!” Even though it does suffice for some situations, you can often find you want just a tad more control over how tough your game really is. Sometimes, you just need that extra bit of control over the situation and need stuff to be a bit more exact. Other times, you just want to manually make a level to keep the best control over the difficulty.

But Mark, how do you decide when to use what?!

Each situation requires a different approach. It really all depends on what you need. During the past few projects I worked on, I have had to implement several different ways of difficulty management: randomly generated levels and manually designed levels. Most of the time you’ll find that if you need infinite gameplay, you need either a randomly spawned level, or a level that confines the player to a small place. When you want short burst of gameplay, it might be better to manually design levels in order to pace the game to your own liking. It’s a pretty important decision to make at the start of development: going for either random levels or pre-set levels makes a huge impact on how you develop the game.

 

Randomly generated (“procedural”) levels

I’ll start with the randomly generated levels. These are used in a lot of games, most often the ‘infinite’ gameplay types. The pros about using random generated levels is that you don’t have to put hours and hours in manually placing assets in order to create a level and it can lead to quick prototyping. The cons about using randomly generated levels are that you have less control over the game’s flow. It’s tougher to manage the difficulty in a level. Small tweaks are harder to make, and you have to test over and over with every adjustment to see if you didn’t just get that ‘lucky round that played perfectly’.

I’ll explain how we used randomly generated levels.

The customer wanted a doodle jump sort of game to show children they have to eat healthier and exercise more. The game had to appeal to kids and had to get increasingly harder as the player progressed. In theory, the game should offer infinite time of gameplay in a single session. Because of this ‘infinite jumping gameplay’ restriction, we knew had to create a randomly generated level.

There were two challenges in creating this type of level. Challenge number one: The level had to get progressively harder, but should be random enough not to really notice. Challenge number two: the system had to be easily tweakable, so that we could playtest often and adjust to the results from these tests quickly. Our target group were children after all, so we didn’t know how hard the game should be. Our own perception of difficulty is completely unlike theirs.

Screenshot of Na-Aapje, a game with randomly generated levels

Screenshot of Na-Aapje, a game with randomly generated levels

The system we used was based on percentages. For every object that could spawn in the world, we had a minimal and maximal spawn chance and minimal and maximal distance between two spawned objects of the same type. Every action the player did (jumping, picking up items, completing challenges) rewarded him with points. These points were then used to measure progress.

The amount of ‘progress-points’ the player had gotten over his session decided the difficulty of the game. We compared the current amount of points with the amount of points needed for the maximum difficulty. The percentage we got from that was then used to spawn all of the objects. If the player was halfway through the ‘progress-points’, the level would be halfway through becomes the maximum difficulty.

Because of this system, we could easily adjust the difficulty of the level. Changing the duration of a single session took just a single variable, changing how difficult the game is at the end only took a few more variables. It saved us so much time in tweaking the game, which allowed us to tweak often, resulting in the best gameplay possible. We eventually tweaked the game to last around 10 minutes for the average player; however it could last up to 20 minutes until the maximum difficulty was reached. The best part: difficulty increased along with the player’s progress, not the time spend in a session. Because of this every child could play at his or her own pace.

 

Manually created levels

I know: it’s something you’d prefer to avoid if possible. It can take really long; you have to really think about positioning stuff, there’s a lot to keep in mind when creating your level. The truth is though, manually creating levels offers a great way of controlling the difficulty and learning curve for a player. Having pre-set levels allow for the best tutorials and are great for oozing in new parts of gameplay. The downside is that all the manual labour you put into creating (each of the) levels can feel repetitive and can take a lot of time to do well.

However, creating levels does not HAVE to be a tedious task. Creating and using tools is the key to surviving here. Of course, it all depends on what kind of game you have, but in most cases you can create a tool to massively improve your workflow. Even though creating tools takes time, almost all of the time it’s a great thing to do.

People often don’t create tools for themselves, thinking it takes up more time than it really gives back. However, the opposite is often true. When you’re able to click a level together way more easily, when adjusting already set level designs gets easier, when using tools to chunk parts together to decrease the time of creating a level all-together. All of these situations allow for the game designer to focus on what really matters: on the actual gameplay, rather than implementation.

Every situation requires different tools. The only thing the programmer can do is listening to what the designer would need and create the tools based on that.

 

A bit of both levels?

Another thing you can do, is mix. You can manually create set chunks and then use these randomly throughout a world. Or use a pre-set level with random assets in it. You’re not set to either of both. Like I said before: it’s an important decision for your development process. Think about what you need before implementing any code.

Don’t rush it. 

3,953 total views, no views today

Programmer’s Weekly: Steering AI in the right direction

Written by: Mark Bouwman

AI? Artificial Intelligence?

Indeed. Artificial Intelligence. You might be wondering, what exactly IS Artificial Intelligence? (Of course you’re not, you’re reading a programmer’s blog on the website of a game company. I’m guessing you got here for game related stuff, and that AI isn’t all that new to you.)

Artificial Intelligence has a wide range of topics, spreading from simulating flocks of birds to computers beating us at a game of chess. However, when we talk about it in the gaming industry, we usually mean just one thing: the illusion of intelligence in a non-player character (NPC). The illusion that the NPC is smart enough to act on his own, the illusion that an actual human being controls him. It’s getting the player to believe the opponents are aiming the same way he does, it’s getting the player to believe the opponents don’t drive the best laps possible, it’s getting the player to believe his opponents are as bad at playing the game as him.

But Mark, when do you need a NPC to be intelligent?!

Well, I’ll give an example. In one of Little Chicken’s current projects, the player can drive around and has to chase enemies, shooting them down in order to continue to the next level. But to create a challenge for the player we don’t want the enemies to feel like they’re just driving randomly (and through buildings). We want the enemies to be smart. We want them to dodge buildings, chase the player and group up with other enemies. This brings us to the topic of this week’s post: Getting the AI to steer.

The challenge: Getting the enemies to NOT crash into a wall
Let’s start by actually getting the AI to drive. I mean, how can we chase the AI if they’re just standing still? Getting them to drive isn’t hard: all you need to do is to move the AI forward and rotate them so that they steer. It’s nothing fancy, nothing special. The tough part though, is getting them to NOT crash into walls (read: not making them look like idiots).

There are tons of ways to implement collision detection and collision prevention. During the development of this game we thought of, and implemented, several different ways to get the AI to detect walls around them, until we finally got to something we agreed to use in the game.

The first method we came up with was traversing the AI over a grid, using A* to find the shortest path to their goal. Buildings were represented by non-traversable tiles in the A* grid. This ‘perfect route’ was then used to create a curved route that the AI followed. We switched to a different method due to numerous things; balancing quality and performance being the main reason. A* can be performance heavy, calculating a lot per frame. If you have three enemies calculating the path to a point about 200 squares away, it can take a LOT of time to actually get the best possible path if there are lots of obstacles in the way. Also, the quality was not as high as we wanted it to be; AI cut corners due to the curved lines they followed. Having no other form of collision detection on the AI, they carelessly drove through walls. Because of this, the grid had to get smaller and more precise. A goal that used to be 200 tiles away, suddenly got 400 tiles away! This more than doubled the amount of possible calculations!

The most efficient way we found to handle collision detection was through using something I like to call the three-point-raycast method. The method is fairly simple, but shows that the simplest solutions sometimes have the best outcome. It’s light on performance and memory, works fast and creates human-like movement.

collision-ray

A visual representation of the three-point-raycast method

How it works: Every NPC has a point at the front of his bike from which a ray is casted. This initial ray detects a possible collision directly in front of the AI. When this possible collision has been detected, two new rays get casted. These new rays are slightly angled (about five degrees) to the left and the right side of the initial ray. These rays give information on which side has an object closest to the AI. The side with the closest collision should be avoided; there is more space at the other side. The AI steers towards that open space, based on how close the collision in front of him is. The closer the object he can collide with, the tighter he steers. Because of this, the AI moves in nice curves, avoiding all collisions.

Voilà, done. The AI now steers like a human being.

All we had to do next was getting the AI to actually steer towards a goal. This is used for chasing the player. With collision detection out of the way, this was actually quite an easy thing to do. All we had to do is create a simple rule: When there’s no collision detection for a second or so, steer towards the goal. With this one rule in action, we were able to have the AI circle around the player, scatter and race away from the player and much, much more. Such a simple rule made the AI a lot more fun to play against.

So, what did you learn?

Getting the AI to steer ended up not being all that hard once we found a good way to implement the collision prevention. It did however, get me to realize something important: Keep it simple. Keeping things simple help a lot. The three-point-raycast method was so much quicker to implement and required less thinking (math) than the method using pathfinding, but gave much better results. Sometimes, the easiest solution is the best solution.

Keep It Simple, Stupid.

1,723 total views, no views today

Programmer’s Weekly: Performance in Minecart Madness

Minecart Madness Logo

Minecart Madness Logo

Written by: Mark Bouwman

Minecart Madness? What’s that?!

One of the newest projects of Little Chicken Game Company: Minecart Madness.
Minecart Madness is an entertainment game for iOS, aiming at casual gamers who play games on their phones and tablets. The game is a 2D racing game with a view from the side.

The entire game is developed using Unity3D, a free program that allows developers to create games on multiple platforms. We however, are using the licensed Unity3D Pro and iOS Pro features, in order to obtain the best gameplay results possible.

This week I would like to talk about performance for iOS. It’s one of the most valuable things to have: good performance. You can easily notice the difference between 10 frames per seconds or 60. Our goal is to keep the game at a steady 60 frames per second.

Minecart Madness, ingame screenshot

Minecart Madness, ingame screenshot

But Mark, how do you do that?!

Well, there’s a lot of ways you can increase the performance in a game. There’s all sorts of things you can do to keep the graphics down, but there’s also some real nice things you can do by programming. I’ll list a few, just to get you started.

Tip #1: Profiler
This is where getting your performance to the best possible starts. The profiler. It tells you exactly what you need to know: What is killing your game’s performance? Unity allows you to dig deep into your scripts, telling you exactly which calls take performance and how much those calls hurts. You’ll quickly find out that those nasty Debug.Logs you’ve been calling take up a lot of performance compared to the rest!

The profiler has two modes, normal and deep profiling. With normal you can get an overview of the actual performance you have, with deep profiling you get more information at the cost of some performance. It’s really nice when you need just that extra information.

Whenever the framerate drops, it’s represented by a big spike in the profiler. You want as little as spikes as possible, with as little difference from the average as possible. If you do this, your game will be running as smoothly as possible!

Unity3D profiler

Unity3D profiler, found under Window –> Profiler

Tip #2: Pools
That’s right. Pools. Not the swimming pool type, no. The ones where you instantiate objects at the start and reuse them. Instantiating and destroying objects at runtime is a killer for any program. Instantiating the objects first and then using them over and over again keeps the overhead of instantiating to a low. You can do this for a lot of objects! You can use it for bullets, audio sources, small graphic effects or even entire randomly spawned worlds!

The math: I’ll explain the math using the audio system we use in Minecart Madness. In MM, we have an average of five sound effects playing every second. Since every sound only lasts a second and a half tops, we can have ten audio files playing at the same time. Knowing this number, we create ten objects at the start of the game. It increases the loading time by around 3ms, but that’s hardly noticeable. Creating a sound object on runtime takes about 0.3ms, removing it around 0.5ms. This might not sound like a lot, but let’s calculate.

We want to reach 60 frames per second. A whole second is 1000ms. This means we have around 16ms for each frame to use. Out of this, we need 10ms for the actual rendering of the game. This leaves us with 6ms to use for coding, or 360ms in a second. With ten objects a second, that takes 8ms. That’s roughly 2% of the calculations we are allowed to make, just from creating an empty gameobject with two scripts (I’m not even talking about playing the actual audio file!). If you instantiate and destroy a lot of objects (or complicated objects, like geometry with scripts on them), consider this neat trick!

Tip #3: Object Culling
Culling happens when an object is outside of your view. By default, every object still calculates the rendering and updates whenever it’s in your world. Always. Even when you don’t need because it’s outside your view. This is where Object Culling helps.

A big part of the culling can be handled by Unity3D itself. There’s a thing called occlusion culling, which handles the culling for the camera in the game. Unity’s website has some pretty nice documentation about it, give it a quick read:
http://docs.unity3d.com/Documentation/Manual/OcclusionCulling.html

Another part of the culling happens in programming. Would you need something to check for precise collisions with a specific part of the player, when they’re miles away? No. Imagine you’re casting a ray to check for a certain collision, but this ray has a high overhead (Let’s say, 2ms each frame). If you first check the distance from the player, which shouldn’t take more than 0.02ms, you save your program from casting this calculation-heavy ray!

Occlusion Culling

Occlusion Culling in Unity3D, found under Window –> Occlusion Culling

Tip #4: Using the cache (save object references for later use)
Wow, this one can save so much time. Imagine you have 20 enemies, all checking if the player is close to them or not. They check their own position and compare the distance to the player. Nothing special, right? Nope. However, you can make this quite heavy on your program. If you don’t save the player’s transform in your script, you have to get it every single frame. GameObject.Find might seem harmless, but you should really take care using this!

The math: Let’s think about this simple calculation: The distance between the player and the current object. If we use GameObject.Find for this it takes around 0.5ms every frame, for each object that calculates the difference. However, if we already declared the player’s object at the beginning of the game, and just use that reference each frame it takes just around… 0.002ms. That’s. 250 times better!

Alright, I believe you.

There’s a lot of small tricks like these to increase the performance of your game. Feel like you want to share yours? Just reply to this post!

3,494 total views, 1 views today