Flow Map Shader for Unity Sprites

Hello there, it has been quite a long time since I wrote something on my blog:)

Today I have got a small neat thing to share – simple Flow Map Shader for Unity3D Sprites. To understand what I am talking about just have a look at this gif.

I also have a small repository on GitHub where I study shaders in Unity. This shader can be found there with example of usage.

flowmap

This kind of shader is usually used with two normal maps to simulate water and was first presented at SIGGRAPH 2010 by Valve. More information about the shader can be fount here. There is a nice tool out there for creating flow maps.

In this case, this is the texture that controls which parts of the image will be moving.

Flow Map Texture

So this is the shader code. I am not good at writing shaders and it can be not very efficient, but it does its job:

Shader "Custom/Flow Map"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        // Flow
        _FlowMap ("Flow Map", 2D) = "white" {}
        _FlowSpeed ("Flow Speed", float) = 0.05

        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }

    SubShader
    {
        Tags
        { 
            "Queue"="Transparent" 
            "IgnoreProjector"="True" 
            "RenderType"="Transparent" 
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ PIXELSNAP_ON
            #include "UnityCG.cginc"
            
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
            };
            
            fixed4 _Color;

            v2f vert(appdata_t IN)
            {
                v2f OUT;

                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;
            sampler2D _FlowMap;
            float _FlowSpeed;

            fixed4 frag(v2f IN) : SV_Target
            {
                float3 flowDir = tex2D(_FlowMap, IN.texcoord) * 2.0f - 1.0f;
                flowDir *= _FlowSpeed;

                float phase0 = frac(_Time[1] * 0.5f + 0.5f);
                float phase1 = frac(_Time[1] * 0.5f + 1.0f);

                half3 tex0 = tex2D(_MainTex, IN.texcoord + flowDir.xy * phase0);
                half3 tex1 = tex2D(_MainTex, IN.texcoord + flowDir.xy * phase1);

                float flowLerp = abs((0.5f - phase0) / 0.5f);
                half3 finalColor = lerp(tex0, tex1, flowLerp);

                fixed4 c = float4(finalColor, 1.0f) * IN.color;
                c.rgb *= c.a;
                return c;
            }
            ENDCG
        }
    }
}
Advertisements

Simple Pool of Prefabs for Unity3D Game Engine

Recently I faced a pooling problem in my game. My prefabs were instantiated at run time and it caused some performance issues. Thats why I decided to implement a simple pool of prefabs myself as other pools had a significant overhead in functionality for my project.

The implementation is ported from Nicolas Gramlich’s Andengine pool implementation. The project below also contains an example of how to use this pool.

 

Simple Pool of Prefabs for Unity3D Game Engine on GitHub.

 

The usage is extremely simple. First you create an instance of PrefabPool (there are overloaded constructors for flexibility). The constructor with all parameters:

// Create pool of cubes containing instantiated cubePrefabs
PrefabPool cubesPool =
    new PrefabPool(cubePrefab, parent, initialPoolSize, growth, maxPoolSize);

What we have now is a set of instantiated and inactive objects. We do this when our game is loading to avoid further runtime prefab instantiations. We also pass a parent transform to constructor to avoid all these clones being located in Hierarchy root.

Ok, now when out pool of cubes is ready to use we are ready to obtain items from it.

        // position, rotation and scale for prefab obtained from the pool
        Vector3 pos = new Vector3(2, 2, 2);
        Quaternion rotation = Quaternion.Euler(45.0f, 45.0f, 45.0f);
        Vector3 scale = new Vector3(2, 2, 2);

        Transform retrievedCubeInstance1 = cubesPool.ObtainPrefab(pos, rotation, scale);
        Transform retrievedCubeInstance2 = cubesPool.ObtainPrefab(pos * 2, rotation, scale);
        Transform retrievedCubeInstance3 = cubesPool.ObtainPrefab(pos * 3, rotation, scale);

As you can see in the hierarchy these three cubes were retrieved from the pool and not instantiated:

If you try to obtain instance from the pool when it is full, the pool will grow by the growth value specified in the constructor. Now the only thing that is left is to recycle instances. Their position and scale will be reset to Vector3.zero , rotation to Quaterniont.identity and they will become inactive. Code to recycle items:

         cubesPool.RecyclePrefab(retrievedCubeInstance1);
        cubesPool.RecyclePrefab(retrievedCubeInstance2);

This is what the picture looks like after recycling:

Summary: This project provides a simple implementation for pool of prefabs to avoid performance issues with run-time prefab instantiation.

Scriptable Objects in Unity3D – Creating a holder for game level for simple board tile based game.

In this tutorial we will create a simple level holder for a board tile based game and construct a level from the holder object.

Suppose we have a game that consists of a square board (like Flow) and multiple different elements. In our case elements will be small and large cubes and spheres.

Before starting this tutorial you might want to look at the following articles:

(In this article file and directory names from Unity are formatted like this – MainGameScene, class and method names are formatted like this – GameLevelHolder)
When editing the particular level all the information about the level will be immediately stored into .asset file. For this purpose we use Unity3D Scriptable Objects which are most useful for assets which are only meant to store data.
Let’s assume our level will be a square board consisting of different elements of different colors. For instance size can be 3×3, 4×4, 5×5.

Create new Unity project. Save the scene, name it MainGameScene. Make the following folder structure for convenience:

We will have board tiles of different types and colors, so lets create folder called Enums inside Scripts folder and create two enums representing tile type and tile color.
// ElementTypes.cs
public enum ElementTypes
{
 SmallCube,
 LargeCube,
 SmallSpere,
 LargeSphere
}
// ElementColors.cs
public enum ElementColors
{
 NoColor,
 Red,
 Green,
 Blue
}

Now let’s create a class that will represent a single tile of our board and a class representing level of our game. We have to make our tile Serializable for it to be displayed in the Unity inspector the same way other Unity objects are (e.g. Vector3)

// BoardTile.cs

[System.Serializable]
public class BoardTile
{
    public int tileId;
    public ElementTypes elementType;
    public ElementColors elementColor;
}
// GameLevelHolder.cs

using UnityEngine;
using System.Collections.Generic;

public class GameLevelHolder : ScriptableObject
{
    public string levelName = "Default Level Name";
    public int boardSize = 3;

    public List<BoardTile> tiles;
}
As you can see GameLevelHolder inherits from ScriptableObject which allows us to save GameLevelHolder objects as .asset files.

Let’s also create a custom MenuItem to create a holder for our game level any time we need to. We will store our game levels inside Resources/Levels directory for convenience. CreateGameLevelMenuItem.cs creates an instance of GameLevelHolder, initializes the list of tiles and saves it as an .asset file that represents our game level.

// CreateGameLevelMenuItem.cs

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public static class CreateGameLevelMenuItem
{
 [MenuItem("Custom/Game Levels/Create New Game Level Holder")]
 public static void CreateGameLevelHolder()
 {
  GameLevelHolder levelHolder =
   ScriptableObject.CreateInstance<GameLevelHolder>();
  levelHolder.tiles = new List<BoardTile>();

  int numberOfElements = levelHolder.boardSize * levelHolder.boardSize;

  for (int i = 0; i < numberOfElements; i++)
  {
   levelHolder.tiles.Add(new BoardTile());
  }

  AssetDatabase.CreateAsset(levelHolder,
   "Assets/Resources/Levels/NewGameLevelHolder.asset");
  AssetDatabase.SaveAssets();

  EditorUtility.FocusProjectWindow();
  Selection.activeObject = levelHolder;
 }
}

Now we can test our game level creation menu item.

After clicking on our custom menu item a new file inside Resources/Levels directory should appear. The first step is done – now we have a container to store a game level. We will able to make changes to this file through the wizard GUI. When playing a game we will be able to read this file and build the level using this .asset file.

Now let’s read this level we have just created. Create a static class Utils which will provide us a method to retrieve our newly created level. Change “Level Name” field to “First Level” in the inspector tab.

// Utils.cs

using UnityEngine;

public static class Utils
{
 private const string _levelsPath = "Levels/";
 private const string _defaultLevelName = "NewGameLevelHolder";

 public static GameLevelHolder ReadDefaultGameLevelFromAsset()
 {
  object o = Resources.Load(_levelsPath + _defaultLevelName);
  GameLevelHolder retrievedGameLevel = (GameLevelHolder) o;
  return retrievedGameLevel;
 }
}

Now let’s create the class that will construct our game level using the info retrieved from the .asset file. Let’s name this class BoardConstructor and retrieve our game level inside Start()method. Also create an empty GameObject, reset its transform and drag the BoardConstructor script onto it. Now rename it to “pref_BoardConstructor” and drag into the “Prefabs” folder.

// BoardConstructor.cs

using UnityEngine;

public class BoardConstructor : MonoBehaviour
{
 private GameLevelHolder _currentGameLevel;

 void Start()
 {
  _currentGameLevel = Utils.ReadDefaultGameLevelFromAsset();
  Debug.Log("Game Level Name: " + _currentGameLevel.levelName +
   ", board size is " + _currentGameLevel.boardSize);
 }
}

You can now press “Play” button and have a look at the Console tab. If you have done everything right you should see the name of our game level displayed there.

We have successfully read the level so let’s try to use our BoardConstructor to create it’s visual representation.

First we need to prepare prefabs which our board will consist of. Create the following GameObjects and save them as prefabs inside Prefabs/BoardElements directory (reset each element position to 0, 0, 0):

  • A cube with scale (1, 1, 0.1) and name it pref_BoardFoundation
  • A cube with scale (0.7, 0.7, 0.7) and name it pref_CubeLarge
  • A cube with scale (0.3, 0.3, 0.3) and name it pref_CubeSmall
  • A sphere with scale (0.7, 0.7, 0.7) and name it pref_SphereLarge
  • A sphere with scale (0.3, 0.3, 0.3) and name it pref_SphereSmall
Also create a black material named mat_Foundation and assign it to pref_BoardFoundation.
Now update our script so it could construct the board from our NewGameLevelHolder.asset file.
// BoardConstructor.cs

using UnityEngine;
using System.Collections.Generic;

public class BoardConstructor : MonoBehaviour
{
 public Transform foundationPrefab;

 public Transform smallCubePrefab;
 public Transform largeCubePrefab;
 public Transform smallSpherePrefab;
 public Transform largeSpherePrefab;

 private const float _elementSize = 1.0f;

 private IDictionary<ElementTypes, Transform> _elementPrefabs;
 private IDictionary<ElementColors, Color> _elementColors;
 private GameLevelHolder _currentGameLevel;

 private float _offset;

 void Start()
 {
  _currentGameLevel = Utils.ReadDefaultGameLevelFromAsset();
  Debug.Log("Game Level Name: " + _currentGameLevel.levelName +
   ", board size is " + _currentGameLevel.boardSize);
  // we need this offset to position elements correctly
  _offset = (_currentGameLevel.boardSize / 2f) - (_elementSize / 2f);

  InitPrefabsDictionary();
  InitColorsDictionary();

  BuildBoardFoundation();
  BuildBoardTiles();
 }

 private void InitPrefabsDictionary()
 {
  _elementPrefabs = new Dictionary<ElementTypes, Transform>();
  _elementPrefabs.Add(ElementTypes.SmallCube, smallCubePrefab);
  _elementPrefabs.Add(ElementTypes.LargeCube, largeCubePrefab);
  _elementPrefabs.Add(ElementTypes.SmallSpere, smallSpherePrefab);
  _elementPrefabs.Add(ElementTypes.LargeSphere, largeSpherePrefab);
 }

 private void InitColorsDictionary()
 {
  _elementColors = new Dictionary<ElementColors, Color>();
  _elementColors.Add(ElementColors.NoColor, Color.white);
  _elementColors.Add(ElementColors.Red, Color.red);
  _elementColors.Add(ElementColors.Green, Color.green);
  _elementColors.Add(ElementColors.Blue, Color.blue);
 }

 // creates board foundation the same size as the board
 private void BuildBoardFoundation()
 {
  Transform boardFoundation =
   Instantiate(foundationPrefab, Vector3.zero, Quaternion.identity) as Transform;
  int boardSize = _currentGameLevel.boardSize;
  boardFoundation.transform.localScale =
   new Vector3(boardSize, boardSize, boardFoundation.localScale.z);
 }

 private void BuildBoardTiles()
 {
  int boardSize = _currentGameLevel.boardSize;
  List<BoardTile&gt; tiles = _currentGameLevel.tiles;

  for (int row = 0; row < boardSize; row++)
  {
   for (int column = 0; column < boardSize; column++)
   {
    int elementIndex = CalculateElementIndex(row, column, boardSize);
    BoardTile element = tiles[elementIndex];

    // Choose element prefab
    Transform elementPrefab = _elementPrefabs[element.elementType];

    Vector3 elementPosition = CalculateElementPosition(row, column);
    Transform elementTransform =
     Instantiate(elementPrefab, elementPosition, Quaternion.identity) as Transform;

    // Set element color
    Color elementColor = _elementColors[element.elementColor];
    elementTransform.renderer.material.color = elementColor;
   }
  }
 }

 private int CalculateElementIndex(int row, int column, int boardSize)
 {
  return row * boardSize + column;
 }

 private Vector3 CalculateElementPosition(int row, int column)
 {
  float x = row - _offset;
  float y = column - _offset;
  return new Vector3(x, y, 0);
 }
}

The script looks big but there is nothing complicated in it. First we declare public Transform variables to be able to set them in Inspector tab. After this we declare dictionaries with element types and colors for convenient access to prefabs and Color values and initialize them. After this we construct our board using information read from NewGameLevelHolder.asset file.

Drag and drop element prefabs created before to corresponding empty slots of BoardConstructor script.

After you finish the script and drag-and-drop prefabs press “Play” button and you will see the simple board constructed. The result should look like this (depends on your changes in the .asset file, here I’ve changed some colors and element types):

Now try to edit level file and change element types and colors. Press “Play” button again and you will see that your updates are visible after the board is constructed.

So we now we have constructed a board using information that was read from the .asset file. This shows how Scriptable Objects can be useful when you need to store object data.

Download zipped Unity3D project. Please leave comments if you have any issues. SyntaxHighlighter.highlight();

Unity3d Fundamentals. Part 1 – Basic Terminology (3D Buzz)

If you are a complete beginner, one awesome resource for getting into Unity3d game engine and getting the idea of what it is capable of is 3D Buzz. There is a section Unity Fundamentals which provides lots of videos explaining different aspects of the game engine. This article’s content is mostly from videos in the link above.

You can quickly get acquainted with basic Unity3d terminology below.

The purpose of this post is to give you the essence of these videos for your reference. So you could just look up the key points and knowledge from the desired video. You can also use this post to when watching video to get an overview of it.

Basic Unity3d Terminology

  • Project – everything you need to create a game (Assets – sounds, textures, models, scripts, prefabs, etc.) wrapped together. For the most time one project is one game. Project is an organizational system for your game (folder structure).
Folder structure inside your Unity3d project corresponds to the folder structure on your hard drive. Changes to files on your hard drive are reflected on your project files. Modifying some project files outside unity is not a good idea, especially those that are not showed inside unity, it may break your game.
Important. Try not to make any adjustments to your project at the OS level. Make all the changes to your game from the project panel inside unity.
  • Scene – is like a level of the game but a little different, it is more robust. Each scene is used to create a part of your game. The game usually contains of several scenes. Each scene is saved to a file with .asset extension.

To sum up – it is and area of 3d space that contains a series of GameObjects.

  • Package – you can think of them like compressed file such as .zip or .rar but they are special for unity. Package allows you grouping your project files along with their metadata and save them. You can import some files from Unity3d website or Asset Store.
To import a package inside unity go to Assets -> Import Package… You can also export your own packages by selecting Assets -> Export Package… You can import lots of useful packages shipped with unity when creating a new project.
  • Prefab – (prefabricated object) generally speaking, is a container or a way to group assets an their settings together. It is sort of a template that we can use to instantiate multiple copies of this grouping of assets.
There will be two ways you will be applying prefabs:
  • as a level designer – make multiple copies of GameObjects by dragging them into scene
  • as game programmer – instantiating prefabs with scripts
Changes on your prefab will be reflected on its instances. The cool thing about prefabs is that the relationship is not one-directional. You can change the child and make it a completely unique object. You can then save these unique changes to a master prefab.
  • GameObject – pretty much everything that is in your scene. GameObject is a container that depicts something inside of the scene. Everything in your Hierarchy view is a GameObject.
What can you do with a GameObject:
    • Move, Rotate and Scale (Every GameObject has Transform component)
    • Name it
    • Hierarchy
    • Defined via Components
    • You can apply Tags and Layers to your GameObject
To create empty GameObject go to GameObject -> Create Empty or press ctrl (cmd) + Shit + N.
  • Component – Grouping of functionality and parameters to define what a GameObject does. Components define GameObjects. For instance, a Point Light is a GameObject with a Light Component attached. You can enable and disable components attached to GameObject.
Generally speaking, components are modular definitions of functionality that you can add to your GameObjects.
  • Assets – You can think of an asset as an aspect (building block) of your game that will be referenced by some component/asset.
Examples of external Assets (Created outside of unity):
    • 3D Models
    • Textures
    • Sound Effects
    • Scripts
Examples of internal Assets (Created inside unity):
    • Materials
    • Shaders
    • Cube Maps
    • Prefabs
    • Physic Materials
  • Scripts – script is a type of an Asset that adds functionality to GameObjects. A Script is not a program and is only functional in terms of unity. You MUST have scripts to make a playable game.
Now you are familiar with basic Unity3d terminology. Good luck in further learning!