Last active
February 6, 2020 19:46
-
-
Save jackphelps/f507d949a84c53457f570c5009bcb6d4 to your computer and use it in GitHub Desktop.
CharacterFade
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
namespace RPG.FX { | |
public class CharacterFade : MonoBehaviour | |
{ | |
public static void Out(GameObject target, Materials dissolveMaterialToUse, Action callback, float duration = 1.5f) | |
{ | |
CharacterFade fade = target.AddComponent<CharacterFade>(); | |
fade.duration = duration; | |
fade.fadeOut = true; | |
fade.AssignMaterials(dissolveMaterialToUse); | |
fade.currentDissolutionLevel = 0; | |
fade.currentEdgeWidth = 0; | |
fade.SetValues(0,0); | |
SequenceTimer.Call(duration, callback); | |
} | |
// hack: I don't like that I'm including the dissolve material here but if the object was already dissolved out it won't actually be used | |
// but I don't want to NOT include it, you shouldn't have to worry about whether the thing was dissolved out or not | |
// I could re-map the materials but I'm lazy and I don't think that will ever be used | |
public static void In(GameObject target, Materials dissolveMaterialToUse, Action callback, float duration = 1.5f) | |
{ | |
var existing = target.GetComponent<CharacterFade>(); | |
if (existing != null) { existing.Cleanup(); } | |
CharacterFade fade = target.AddComponent<CharacterFade>(); | |
fade.duration = duration; | |
fade.fadeOut = false; | |
fade.AssignMaterials(dissolveMaterialToUse); | |
fade.currentDissolutionLevel = 1; | |
fade.currentEdgeWidth = 1; | |
fade.SetValues(1,1); | |
SequenceTimer.Call(duration, callback); | |
} | |
// map of renderers to original materials so we can put them back | |
public Dictionary<Renderer, Material[]> materialsMap = new Dictionary<Renderer, Material[]>(); | |
// list of each copy of the dissolve material added so we can loop through and update their dissolve levels | |
public List<Material> dissolveMaterials = new List<Material>(); | |
public float duration; | |
public bool fadeOut; | |
public float currentDissolutionLevel; // 1 is fully out, 0 is fully in | |
public float currentEdgeWidth; // 1 is fully greyed out, 0 is fully colored in | |
void AssignMaterials(Materials dissolveMaterialToUse) | |
{ | |
var renderers = gameObject.GetComponentsInChildren<Renderer>().ToList(); | |
var thisRenderer = gameObject.GetComponent<Renderer>(); | |
if (thisRenderer != null) { renderers.Add(thisRenderer); } | |
// loop through each renderer in the object | |
foreach (var renderer in renderers) { | |
if (renderer.materials.Length == 0) { continue; } | |
// add the component to the materials map so we can put things back later | |
materialsMap.Add(renderer, renderer.materials); | |
// assign each material a dissolve-ready equivalent, preserving the texture where relevant | |
var materialsCopy = renderer.materials; | |
for (var i = 0; i < renderer.materials.Length; i++) { | |
// make an instance of the dissolve material and assign its main texture from the original material | |
var originalMat = materialsCopy[i]; | |
var dissolveMat = Asset.Load(dissolveMaterialToUse); | |
dissolveMat.mainTexture = originalMat.mainTexture; | |
materialsCopy[i] = dissolveMat; | |
// add the new material to our list so we can easily update the shader dissolve values | |
dissolveMaterials.Add(materialsCopy[i]); | |
} | |
renderer.materials = materialsCopy; | |
} | |
} | |
void SetValues(float edge, float level) | |
{ | |
foreach (var mat in dissolveMaterials) { | |
mat.SetFloat("_Edges", edge); | |
mat.SetFloat("_Level", level); | |
} | |
} | |
void Update() | |
{ | |
if (fadeOut) { | |
if (currentEdgeWidth >= 0.99f) { | |
if (currentDissolutionLevel >= 0.99f) { | |
} else { | |
currentDissolutionLevel += Time.deltaTime / duration * 2; | |
} | |
} else { | |
currentEdgeWidth += Time.deltaTime / duration * 2; | |
} | |
} else { | |
if (currentDissolutionLevel <= 0.01f) { | |
if (currentEdgeWidth <= 0.01f) { | |
Cleanup(); | |
} else { | |
currentEdgeWidth -= Time.deltaTime / duration * 2; | |
} | |
} else { | |
currentDissolutionLevel -= Time.deltaTime / duration * 2; | |
} | |
} | |
SetValues(currentEdgeWidth, currentDissolutionLevel); | |
} | |
void Cleanup() | |
{ | |
foreach (var pair in materialsMap) { | |
if (pair.Key != null && pair.Key is Renderer renderer && pair.Key.gameObject.activeInHierarchy) { renderer.materials = pair.Value; } | |
} | |
Destroy(this); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment