Lighting System

One of the most core elements of our game is the lighting, as such, this post is about how we managed to implement it, and the part I’ve done in getting it working. This is how the lighting system currently works, although we plan to refine it a bit more later on.

The concept “Echo” requires a dark map where the player navigates around and finds stuff. To implement this in any way, a lighting system is necessary. We decided to do this by attaching a light source (controlled by scripts) to a berry, which the player can then pick up, carry around or throw. A problem here is that the 2D sprites don’t interact with lights, and you have to have a sprite diffuse shader on them for them to do so. The different states of the berry were implemented by my fellow programmer, Sebastian, through an internal state machine. I then coded the behaviour of those states: ‘not picked up’, ‘picked up’, ‘thrown’ and ‘broken’.

Starting State
At initialisation, the berry is set to ‘not picked up’. The code


if ((Vector3.Distance(target.position, transform.position) < distance) && ammo == false)
{
     currentState = State.pickedUp;
     ammo=true;
}

checks if the player is near the berry (with no ammo) and if they are, changes state to picked up. It is implemented like this and not through onCollision, because we didn’t want the berry to collide with the player and trigger the corresponding physics behaviors (like pushing the player off or dragging the player down). The player and berry are also on separate non-colliding layers.

notpicked
Not Picked Up State

Picked State
If the player gets close to the berry, it goes into ‘picked up’ state. The berries position now gets constantly updated to a point in front of the player by using a public transform that stores an empty (child) object in front of the player. The child object is just for convenience, since it can be re-positioned easily. The collider of the berry is disabled, to avoid the possibility of using the berry as a shield against the hunters. The light intensity and range are increased.

picked
Picked Up State

Thrown State
Once picked, the berry can be either thrown (towards the mouse cursor) or dropped. If the berry is thrown, it transitions to ‘thrown’ state and then to ‘broken’ state. If it is dropped, it immediately goes into ‘broken’ state. Since Sebastian did the code for the throw, I will not be going into the details of that.

thrown
Thrown State

Broken State
Once in the broken state, the berry’s light intensity is set to max, while the range increases at first, and then decreases to zero. The increasing and then decreasing is to create an effect like a flash of light illuminating the map before it goes out. At range zero, the object is destroyed (for not wasting memory). The code for this is as follows.


m_light.intensity = 8;

if (isIncreasing == true)
{
     m_light.range += 5f;
     if (m_light.range > 100)
     {
           isIncreasing = false;
     }
}
else if (isIncreasing == false)
{
     m_light.range -= 0.5f;
}

if (m_light.range <= 0)
{
     Destroy(this.gameObject);
}

fading
Broken State

Leave a comment