Unity Shadows on Windows Phone 8
Due to a driver issue Unity offers currently no realtime shadows on Windows Phone 8 devices.
But you don’t have to give up shadows on WP8.
You can use a combination of
- baked lightmaps of the static environment
- projected shadows for dynamic things, e.g. the main character
to achieve nice shadows in your 3D world.
I’ve created a small downloadable demo using some Unity default assets. I’ve upscaled the character a bit, so that you can see what has to be considered when using larger dynamic shadows, e.g. for vehicles.
Step 1: Lightmap Baking
To achieve something similar as in my example one would use the following workflow:
- open <Windows/Lightmapping>
- select the directional light and switch on the shadows temporarily
- select all static renderes in the scene and switch ‘Lightmap Static’ on
- in the bake tab choose ‘Single Lightmaps’
- set Ambient Occulusion to 0.4
- set Resolution to 16 texels per world unit
- bake Scene
Step 2: Dynamic Shadows using a Projector
The shadow projector is based on Unity’s render texture feature, which means you need Unity Pro to be able to use it.
Basically it works like this: There is a second camera that only renders the character. With the help of a Projector the shadow is then projected onto all objects that intersect its frustum.
Aras Pranckevičius (rendering dude at Unity, see his twitter profile) has created a ready-to-use Unity package for this.
Follow the instructions at http://wiki.unity3d.com/index.php/Character_Shadow.
Basically one only needs
- to assign a specific layer for the character
- add CharacterShadow.cs to an empty game object from where the shadows are cast
In our case the character can move around, so we do the following:
- add an empty GameObject as Child to our character (named ‘Viking’ in the example) and name it ShadowCastPosition
- add the CharacterShadow.cs script to it
- since the shadow should have the direction of the directional light we add an additional simple script with the following content
public class ShadowCastPosition : MonoBehaviour { public Transform lightTransform; public float dist = 12; private Vector3 back; void Awake() { back = lightTransform.TransformDirection(Vector3.back) * dist; } void Update () { transform.position = transform.parent.position + back; } }
The script simply positions the ShadowCastPosition GameObject towards the directional light direction with a certain distance, so the correct shadow is casted.
An important hint: if the thing that should cast a shadow is bigger (e.g. some kind of vehicle), there is an important hard-coded setting in the CharacterShadow.cs script in the method OrientToEncloseTarget.
To demonstrate this in my example, I upscaled the character a little bit. I added the public variable childCamRadius and set it 12 in my example.
To run the working demo on your WP8 device:
- download the demo here
- open the project in Unity
- in the build settings switch to ‘Windows Phone 8’
- click ‘Build And Run’
- enjoy 🙂
Follow me on twitter, if you found this useful.