Directional light shadow moves w/ player

I’m using the sample First Person Controller prefab in a simple scene along w/ a single directional light that has shadows turned on. For whatever reason, as I move the player around using W,A,S,D, the shadow appears to move as well.

Any thoughts?

Thanks!

Is it possible that you have the directional light childed to the player?

Its in the prefab, and its not under any of the prefab objects in the hiearchy view. This should mean its not a child of anything correct? I tried parenting the directional light w/ another scene model but the shadows still moves w/ the player.

I tried placing a spot light w/ shadows on and that seams to work fine.

Thanks for the response though!

The CharacterShadow script doesn’t move with the player since it’s logic only uses point lights and therefor their positions. You just have to move the light with you’r player on use a different ortographic view.
The side effect is that you’ll get much sharper/detailed shadows with the same texture size.

not sure if you read my question or if I’m misinterpreting your suggestion, but I want nice static shadows as if from a sun (yes, dynamic, not baked) however when I move w/ the FPS prefab the shadows move as well.

Look at my changes in CharacterShadow the changes work fine in my project. The script examines the light type and changes it’s behaviour. When using a dirctinal light the projector (not the light) gets moved with the player.

using UnityEngine;

public class CharacterShadow : MonoBehaviour
{
	public GameObject target;
	public float castingDistance = 10.0f;
	public float lightness = 0.6f;
	public int textureSize = 512;
	public Texture fadeoutTexture;
	public bool blur = false;
	public int blurIterations = 1;
	public LayerMask ignoreLayer; // don't cast shadow on this layers
	public LayerMask targetLayer; // all objects within this layer are used to cast shadows
	public float directionalOffset = 1.0f;
	
	private RenderTexture shadowmap;
	private GameObject child;
	private Projector proj;
	private Camera cam;
	private int savedPixelLightCount;
	
	
	private static string shadowMatString =
@"Shader ""Hidden/ShadowMat"" {
	Properties {
		_Color (""Color"", Color) = (0,0,0,0)
	}
	SubShader {
		Pass {
			ZTest Greater Cull Off ZWrite Off
			Color [_Color]
			SetTexture [_Dummy] { combine primary }
		}
	}
	Fallback off
}";

	static Material m_ShadowMaterial = null;
	protected static Material shadowMaterial {
		get {
			if (m_ShadowMaterial == null) 
				m_ShadowMaterial = new Material (shadowMatString);
			return m_ShadowMaterial;
		} 
	}
	
	private static string projectorMatString =
@"	Shader ""Hidden/ShadowProjectorMultiply"" { 
	Properties {
		_ShadowTex (""Cookie"", 2D) = ""white"" { TexGen ObjectLinear }
		_FalloffTex (""FallOff"", 2D) = ""white"" { TexGen ObjectLinear	}
	}
	Subshader {
		Pass {
			ZWrite off
			Offset -1, -1
			Fog { Color (1, 1, 1) }
			AlphaTest Greater 0
			ColorMask RGB
			Blend DstColor Zero
			SetTexture [_ShadowTex] {
				combine texture, ONE - texture
				Matrix [_Projector]
			}
			SetTexture [_FalloffTex] {
				constantColor (1,1,1,0)
				combine previous lerp (texture) constant
				Matrix [_ProjectorClip]
			}
		}
	}
}";

	private Material projectorMaterial = new Material (projectorMatString);
	
	void Start()
	{
		if( !target )
		{
			Debug.Log("No target assigned! Disabling CharacterShadow script");
			enabled = false;
			return;
		}
		
		if( ignoreLayer == 0 ) {
			Debug.Log("Warning: target layer should use a separate layer (!=default)");
			// still continue...
		}
		
		// create a child camera/projector object
		child = new GameObject("ChildCamProjector");
		cam = (Camera)child.AddComponent("Camera");
		proj = (Projector)child.AddComponent("Projector");
		child.AddComponent("CharacterShadowHelper");
		if (blur) {
			child.AddComponent("BlurEffect"); 
			// adjust iterations as needed or better expose a property 
			((BlurEffect)child.GetComponent(typeof(BlurEffect))).iterations = blurIterations; 
		}
			
		cam.clearFlags = CameraClearFlags.Color;
		cam.backgroundColor = Color.white;
		cam.cullingMask = targetLayer;
		cam.isOrthoGraphic = true;
		
		proj.isOrthoGraphic = true;
		proj.orthoGraphicSize=1.0F;
		proj.ignoreLayers = ignoreLayer;
		proj.material = projectorMaterial;
		proj.material.SetTexture("_FalloffTex", fadeoutTexture);
		
		child.transform.parent = transform;
		if (light.type!=LightType.Directional) {
			child.transform.localPosition = Vector3.zero;
			child.transform.localRotation = Quaternion.identity;
		}
		else {
			proj.transform.rotation = transform.rotation;
		}	
	}
	
	void Update()
	{
		if (!shadowmap) {
			shadowmap = new RenderTexture( textureSize, textureSize, 16 );
			shadowmap.isPowerOfTwo = true;
            shadowmap.wrapMode = TextureWrapMode.Clamp;
			cam.targetTexture = shadowmap;			
			proj.material.SetTexture("_ShadowTex", shadowmap);
		}
		OrientToEncloseTarget();
	}
	
	void OnEnable()
	{	
		if (proj)
			proj.enabled = true;
	}

	void OnDisable()
	{
		if (proj)
			proj.enabled = false;
	}
	
	public void OnPreRender()
	{
		savedPixelLightCount = Light.pixelLightCount;
	}
				
	public void OnPostRender()
	{
		shadowMaterial.color = new Color(lightness,lightness,lightness,lightness);
		
		GL.PushMatrix();
		GL.LoadOrtho();
		// LoadOrtho loads -1..100 depth range in Unity's
		// conventions. We invert it for OpenGL
		// and pu the depth at the very far end.
		const float depth = -99.99f;
		
		for (int i = 0; i < shadowMaterial.passCount; i++)
		{
			shadowMaterial.SetPass (i);
			GL.Begin (GL.QUADS);
			GL.TexCoord2(0,0); GL.Vertex3( 0, 0, depth );
			GL.TexCoord2(1,0); GL.Vertex3( 1, 0, depth );
			GL.TexCoord2(1,1); GL.Vertex3( 1, 1, depth );
			GL.TexCoord2(0,1); GL.Vertex3( 0, 1, depth );
			GL.End();
		}
		GL.PopMatrix ();
		
		Light.pixelLightCount = savedPixelLightCount;
	}
	
	private void OrientToEncloseTarget()
	{
		Vector3 center = target.transform.position;
		// REMARK: radius fails if the mesh data is not found in the target (e.g. mesh is found in childs only)
		float radius = 5.0f; 
		if( target.renderer ) {
			Bounds b = target.renderer.bounds;
			center = b.center;
			radius = b.extents.magnitude;
		}
		
		if (blur)
			radius *= 1.1f;
		else	
			radius *= 1.05f;
			
		if (light.type!=LightType.Directional) {
			float distance = (center - transform.position).magnitude;
			
			child.transform.LookAt( center );
			
			cam.orthographicSize = radius;
			cam.nearClipPlane = distance - radius;
			cam.farClipPlane = distance + radius;
			
			proj.orthoGraphicSize = radius;
			proj.nearClipPlane = distance;
			proj.farClipPlane = distance + castingDistance;
			proj.material.SetTexture("_ShadowTex", shadowmap);
		}
		else { // directional
			radius = 1.2F;
			
			// der Projektor wird einfach mit dem target-Objekt mitgeführt
			child.transform.position = target.transform.position;
            child.transform.Translate(-transform.forward*directionalOffset);  
            
			cam.orthographicSize = radius;
			cam.nearClipPlane = 0.01F;
			cam.farClipPlane = castingDistance;

			proj.orthoGraphicSize = radius;
			proj.nearClipPlane = directionalOffset-0.2F; // capsule radius*2 
			proj.farClipPlane = castingDistance;
			proj.material.SetTexture("_ShadowTex", shadowmap);
		}	
	}
}

[/code]

I’m not sure I understand the problem. You have a character. When it moves, it’s shadow also moves.

Isn’t that what you want? Do you want it’s shadow to stay in the old place instead?

I think he wants roughly the same effect as a blob shadow, actually (but dynamically animating with the model.)

In other words, the light source is SO high (the sun) that the angle of the shadow doesn’t shift and stretch.

So, that’s why the suggestions of moving the light source with the character came up. To keep the shadow at a consistent angle to the player.

That’s how I read it, but he keeps using the word “move” which means 10 different things. :smile:

hahaha, alright, this ‘misunderstanding’ was my fault.
I should have been very specific :-).

I’m using the First Person Controller prefab for basic player movement. As well, I am using a single light source (a directional light) to simulate the sun. In my scene is a basic ground mesh and some props. Now, in editor, the directional light is casting shadows from these props onto my ground mesh and it looks great.

However, as soon as I press play or build the project and test it, as I move my player, all the shadows in the scene move - 3d objects shadows, not just the players shadows.

Does that make better sense? I’m trying to figure out why static objects shadows are moving when the player moves.

Sorry for the confusion and the great help so far!

1 Like

Do they actually move across the ground like the object were moving or do they crawl/sparkle because of aliasing? I’ve seen that, you need to mess with the cascade settings and draw distance if that is the case to tune the shadows for the scene.

It retains the shadows shape and moves them across my ground mesh. Not an AA issue as far as I can tell. Thought it could be clipping plane related?

So it “moves” in a sense “the shadow just ran 10 meters!”, or “moves” in a sense “it stays in the same place, but there’s some crawling and shimmering”?

In the latter case, tweak shadow quality settings to get the resolution right for your scene size. Documentation here.

Sorry for the slow reply - they move as in, whoa, they just moved 10 meters. It doesn’t appear to be a graphical / shadow quality issues, as the shadows look great, but they move.

C’MON!! post screenshots to clarify :smile:

.org

That is strange. Do a small project that reproduces the issue, and send it with Report Bug.app (found next to Unity application, or from Help menu in Unity).

This is going to sound simple, but… does the light source move? Rigidbody accidentally attached or a script you were playing around with once and forgot about? Or is it in the hierarchy of another object that moves somehow?

Probably not… but… it seems like the most likely possibility from what little I know here.

I guess it could be that your entire terrain is moving or something like that, too. I remember dealing with some physics tests and I was tilting my entire “floor” around just by moving a player across it. Might be subtle enough to not see the movement, and the shadows would be the most obvious place it’s noticed… especially if the camera follows the player.

And now, I will stop suggesting stuff that you probably already checked. :slight_smile:

I ended up tweaking my camera clip plane settings to solve this. I was having all kinds of issues - skybox not showing, hall of mirrors effects, graphical oddities and moving shadows.

Thanks for everyone’s feedback. I guess the scale I’m using is smaller than intended as I’ve had to tweak a lot of defaults to get things looking right.

Thanks!

gosh… this post is so old… but it seems to be the only one explaining the exact issue i am facing…
all the worlds shadows are moving with the player/camera…

I tried playing with the cameras. turning all off but one, giving it full clipping range…
I tried turning all the lights off but one, played with its settings…
I checked that the light, nor my buildings/land/world are moving…

still having shadows moving all over the place…
since noone else is reporting this issue… i wonder what i am doing wrong…

1 Like

I’ve the same F****G problem :frowning: only in my mobile android build

Me too, for Oculus and Windows versions on Unity 2020.1