76
Support / Our per-object Motion Blur solution: use it if you want!
« on: June 18, 2013, 10:30:07 am »
So, we've been working on an object-independent motion blur for sprites. We've reached a somehow useful solution, so we are posting it here for you guys, in case that someone needs something similar. It only works with the next 2DToolkit 2.2.
First, the Motion Blur script (component of the object to be blurred):
And the other one. This is a script that the previous one adds at runtime to each copy:
What this system does is fairly simple: the first script instantiates copies of the original sprite with a very tiny offset, and gives them a certain amount of alpha. This creates an illusion of blurriness over the gameobject, and it only works when it is moving. The second script just handles some fading effect for the copies.
Hope you guys find it useful!
First, the Motion Blur script (component of the object to be blurred):
Code: [Select]
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MotionBlurHandler : MonoBehaviour
{
//Will it be a blur over the object, or a trail behind it?
public bool front = true;
//How much speed does the object need before blurring?
public float startSpeed = 0.005f;
//How much time does it take for each 'copy' to fade?
public float copyFadeTime = 0.1f;
//The sprite object that will be duplicated (could be changed to 'tk2dSprite')
public GameObject trailMotionSpriteObject;
//The script handles this
public Material fadeMaterial;
//How many copies does the trail create?
public float maxCopies = 5.0f;
//How many offset between copies?
public float offsetCopies = 0.01f;
//How much time does it take to each copy to spawn?
public float timeBetweenCopies = 0.02f;
//The alpha of the first copy
public float initAlpha = 0.5f;
//The amount of alpha substracted between copies
public float alphaOffset = 0.15f;
private tk2dSprite _mySprite;
private float _timer;
private bool _createNow;
private int _currentCopies;
private int _currentLayer;
private Vector3 _currentOffset;
private float _currentAlpha = 1.0f;
private List<GameObject> _copyList;
void Start()
{
_copyList = new List<GameObject>();
_currentOffset = Vector3.zero;
_currentAlpha = initAlpha;
_mySprite = GetComponent<tk2dSprite>() as tk2dSprite;
}
void Update()
{
if(_timer <= timeBetweenCopies)
{
_createNow = false;
_timer += Time.deltaTime;
}
else
{
_createNow = true;
_timer = 0.0f;
}
if(Mathf.Abs (Vector3.Magnitude(rigidbody.velocity)) > startSpeed )
{
if(_currentCopies < maxCopies)
{
if(_createNow)
{
Vector3 tmpVelocity = rigidbody.velocity;
tmpVelocity.y = 0.0f;
_currentOffset += (Vector3.Normalize(tmpVelocity) * offsetCopies);
_currentAlpha -= alphaOffset;
Vector3 tmp = Vector3.zero;
tmp.x = transform.localPosition.x-_currentOffset.x;
tmp.y = transform.localPosition.y-_currentOffset.y;
tmp.z = transform.localPosition.z-_currentOffset.z;
GameObject go = Instantiate(trailMotionSpriteObject,transform.localPosition-_currentOffset, transform.rotation) as GameObject;
_copyList.Add(go);
++_currentCopies;
if(front)
++_currentLayer;
else
--_currentLayer;
FadeInTime fit = go.AddComponent("FadeInTime") as FadeInTime;
(go.GetComponent<tk2dSprite>() as tk2dSprite).RenderLayer = _currentLayer;
go.renderer.material = renderer.material;
fit.SetInitAlpha(_currentAlpha, this);
go.transform.parent = gameObject.transform;
}
}
}
else
{
if(_currentCopies != 0)
{
(_copyList[_currentCopies-1].GetComponent<FadeInTime>() as FadeInTime).StartFading(copyFadeTime);
_copyList.RemoveAt(_currentCopies-1);
--_currentCopies;
if(_currentCopies == 0)
{
_currentOffset = Vector3.zero;
_currentAlpha = initAlpha;
_currentLayer = 0;
}
}
}
}
And the other one. This is a script that the previous one adds at runtime to each copy:
Code: [Select]
using UnityEngine;
using System.Collections;
public class FadeInTime : MonoBehaviour
{
public float fadeTime = 0.5f;
public Transform followPosition;
private bool _ready = false;
public tk2dSprite mySprite;
private float _timePassed = 0.0f;
private float _initAlpha;
private MotionBlurHandler _motionHandler;
void Start ()
{
//mySprite = gameObject.GetComponent<tk2dAnimatedSprite>() as tk2dAnimatedSprite;
mySprite = gameObject.GetComponent<tk2dSprite>() as tk2dSprite;
}
void Update ()
{
if(_ready)
{
_timePassed += Time.deltaTime;
if(_timePassed < fadeTime)
{
Color myColor = new Color();
myColor.r = mySprite.color.r;
myColor.g = mySprite.color.g;
myColor.b = mySprite.color.b;
myColor.a = Mathf.Lerp (_initAlpha,0.0f,_timePassed/fadeTime);
mySprite.color = myColor;
//Movement
// delayed follower
/*float distance = Vector3.Distance(transform.position, followPosition.position);
if(distance>0)
{
Vector3 nextPosition = Vector3.Lerp (transform.position, followPosition.position, _timePassed/fadeTime);
transform.position = nextPosition;
}*/
}
else
{
Destroy (gameObject);
}
}
}
public void StartFading(float fTime)
{
fadeTime = fTime;
_ready = true;
}
public void SetInitAlpha(float initAlpha,MotionBlurHandler mh )
{
_initAlpha = initAlpha;
_motionHandler = mh;
//mySprite = gameObject.GetComponent<tk2dAnimatedSprite>() as tk2dAnimatedSprite;
mySprite = gameObject.GetComponent<tk2dSprite>() as tk2dSprite;
Color myColor = new Color();
myColor.r = mySprite.color.r;
myColor.g = mySprite.color.g;
myColor.b = mySprite.color.b;
myColor.a = _initAlpha;
mySprite.color = myColor;
//MeshRenderer m = gameObject. GetComponent<MeshRenderer>() as MeshRenderer;
//renderer.sharedMaterial = mat;
}
}
What this system does is fairly simple: the first script instantiates copies of the original sprite with a very tiny offset, and gives them a certain amount of alpha. This creates an illusion of blurriness over the gameobject, and it only works when it is moving. The second script just handles some fading effect for the copies.
Hope you guys find it useful!