| using UnityEngine; | 
| using System.Collections; | 
|   | 
| namespace DynamicShadowProjector { | 
|     public class FollowTargetObject : MonoBehaviour { | 
|         public enum TextureAlignment { | 
|             None = 0, | 
|             TargetAxisX, | 
|             TargetAxisY, | 
|             TargetAxisZ, | 
|         } | 
|         public enum UpdateFunction { | 
|             OnPreCull = 0, | 
|             LateUpdate, | 
|             UpdateTransform, | 
|         } | 
|         // Serialize Fields | 
|         [SerializeField] | 
|         private Transform m_target; | 
|         [SerializeField] | 
|         private Transform m_targetDirection = null; | 
|         [SerializeField] | 
|         private TextureAlignment m_textureAlignment = TextureAlignment.None; | 
|         [SerializeField] | 
|         private UpdateFunction m_updateFunction = UpdateFunction.LateUpdate; | 
|   | 
|         // public properties | 
|         public Transform target | 
|         { | 
|             get { return m_target; } | 
|             set { m_target = value; } | 
|         } | 
|         public Transform targetDirection | 
|         { | 
|             get { return m_targetDirection; } | 
|             set { m_targetDirection = value; } | 
|         } | 
|         public TextureAlignment textureAlignment | 
|         { | 
|             get { return m_textureAlignment; } | 
|             set { m_textureAlignment = value; } | 
|         } | 
|         public UpdateFunction updateFunction | 
|         { | 
|             get { return m_updateFunction; } | 
|             set { m_updateFunction = value; } | 
|         } | 
|   | 
|         public void UpdateTransform() | 
|         { | 
|             if (m_textureAlignment != TextureAlignment.None || m_targetDirection != null) { | 
|                 // rotate projector to align texture parallel to target object. | 
|                 Vector3 up; | 
|                 switch (m_textureAlignment) { | 
|                 case TextureAlignment.TargetAxisX: | 
|                     up = m_target.right; | 
|                     break; | 
|                 case TextureAlignment.TargetAxisZ: | 
|                     up = m_target.forward; | 
|                     break; | 
|                 default: | 
|                     up = m_target.up; | 
|                     break; | 
|                 } | 
|                 Vector3 z = m_targetDirection != null ? m_targetDirection.forward : transform.forward; | 
|                 transform.LookAt(transform.position + z, up); | 
|             } | 
|             Vector3 targetPos = transform.TransformPoint(m_localTargetPosition); | 
|             transform.position += m_target.position - targetPos; | 
|         } | 
|   | 
|         private Vector3 m_localTargetPosition; | 
|   | 
|         // message handlers | 
|         void Awake() | 
|         { | 
|             if (m_target != null) { | 
|                 m_localTargetPosition = transform.InverseTransformPoint(m_target.position); | 
|             } | 
|         } | 
|   | 
|         void LateUpdate() | 
|         { | 
| #if UNITY_EDITOR | 
|             if (!Application.isPlaying) { | 
|                 return; | 
|             } | 
| #endif | 
|             if (m_updateFunction == UpdateFunction.LateUpdate) { | 
|                 UpdateTransform(); | 
|             } | 
|         } | 
|   | 
|         void OnPreCull() | 
|         { | 
| #if UNITY_EDITOR | 
|             if (!Application.isPlaying) { | 
|                 return; | 
|             } | 
| #endif | 
|             if (m_updateFunction == UpdateFunction.OnPreCull) { | 
|                 UpdateTransform(); | 
|             } | 
|         } | 
|     } | 
| } |