养成基本完毕,新UI,修bug,装备初步,
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[RequireComponent(typeof(Image))]
|
||||
public class idolMaterialController : MonoBehaviour
|
||||
{
|
||||
public enum SweepSide
|
||||
{
|
||||
FromLeft = 0,
|
||||
FromRight = 1,
|
||||
}
|
||||
|
||||
[Header("Material")]
|
||||
public Material materialTemplate;
|
||||
|
||||
[Header("Animation")]
|
||||
public SweepSide enterDirection = SweepSide.FromLeft;
|
||||
public SweepSide exitDirection = SweepSide.FromRight;
|
||||
public float enterDuration = 0.35f;
|
||||
public float exitDuration = 0.25f;
|
||||
[Range(0f, 1f)]
|
||||
public float hiddenAmount = 0f;
|
||||
[Range(0f, 1f)]
|
||||
public float shownAmount = 1f;
|
||||
public bool playEnterOnEnable = false;
|
||||
|
||||
private Image image;
|
||||
private Material runtimeMaterial;
|
||||
private Coroutine transitionCoroutine;
|
||||
private Sprite pendingSprite;
|
||||
|
||||
private static readonly int DissolveAmountId = Shader.PropertyToID("_DissolveAmount");
|
||||
private static readonly int DirectionId = Shader.PropertyToID("_Direction");
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
image = GetComponent<Image>();
|
||||
EnsureRuntimeMaterial();
|
||||
ApplyInstantState(shownAmount, GetShaderDirectionForEnter(enterDirection));
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
EnsureRuntimeMaterial();
|
||||
if (playEnterOnEnable && image != null && image.sprite != null)
|
||||
{
|
||||
PlayEnter();
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyInstantState(shownAmount, GetShaderDirectionForEnter(enterDirection));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (transitionCoroutine != null)
|
||||
{
|
||||
StopCoroutine(transitionCoroutine);
|
||||
transitionCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (runtimeMaterial != null)
|
||||
{
|
||||
if (image != null && image.material == runtimeMaterial)
|
||||
{
|
||||
image.material = null;
|
||||
}
|
||||
|
||||
Destroy(runtimeMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSpriteImmediate(Sprite sprite)
|
||||
{
|
||||
EnsureRuntimeMaterial();
|
||||
if (image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
image.sprite = sprite;
|
||||
ApplyInstantState(shownAmount, GetShaderDirectionForEnter(enterDirection));
|
||||
}
|
||||
|
||||
public void PlayEnter()
|
||||
{
|
||||
EnsureRuntimeMaterial();
|
||||
if (image == null || runtimeMaterial == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (transitionCoroutine != null)
|
||||
{
|
||||
StopCoroutine(transitionCoroutine);
|
||||
}
|
||||
|
||||
transitionCoroutine = StartCoroutine(AnimateAmount(hiddenAmount, shownAmount, Mathf.Max(0.01f, enterDuration), GetShaderDirectionForEnter(enterDirection), null));
|
||||
}
|
||||
|
||||
public void PlayExit()
|
||||
{
|
||||
EnsureRuntimeMaterial();
|
||||
if (image == null || runtimeMaterial == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (transitionCoroutine != null)
|
||||
{
|
||||
StopCoroutine(transitionCoroutine);
|
||||
}
|
||||
|
||||
transitionCoroutine = StartCoroutine(AnimateAmount(shownAmount, hiddenAmount, Mathf.Max(0.01f, exitDuration), GetShaderDirectionForExit(exitDirection), null));
|
||||
}
|
||||
|
||||
public void TransitionToSprite(Sprite sprite)
|
||||
{
|
||||
EnsureRuntimeMaterial();
|
||||
if (image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pendingSprite = sprite;
|
||||
|
||||
if (transitionCoroutine != null)
|
||||
{
|
||||
StopCoroutine(transitionCoroutine);
|
||||
}
|
||||
|
||||
bool hasCurrentSprite = image.sprite != null;
|
||||
bool spriteChanged = image.sprite != sprite;
|
||||
transitionCoroutine = StartCoroutine(TransitionRoutine(hasCurrentSprite, spriteChanged));
|
||||
}
|
||||
|
||||
private IEnumerator TransitionRoutine(bool hasCurrentSprite, bool spriteChanged)
|
||||
{
|
||||
if (runtimeMaterial == null || image == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (hasCurrentSprite && spriteChanged)
|
||||
{
|
||||
yield return AnimateAmount(shownAmount, hiddenAmount, Mathf.Max(0.01f, exitDuration), GetShaderDirectionForExit(exitDirection), null);
|
||||
}
|
||||
|
||||
image.sprite = pendingSprite;
|
||||
if (pendingSprite == null)
|
||||
{
|
||||
ApplyInstantState(hiddenAmount, GetShaderDirectionForEnter(enterDirection));
|
||||
transitionCoroutine = null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return AnimateAmount(hiddenAmount, shownAmount, Mathf.Max(0.01f, enterDuration), GetShaderDirectionForEnter(enterDirection), null);
|
||||
transitionCoroutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator AnimateAmount(float from, float to, float duration, float directionValue, System.Action onComplete)
|
||||
{
|
||||
if (runtimeMaterial == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
runtimeMaterial.SetFloat(DirectionId, directionValue);
|
||||
runtimeMaterial.SetFloat(DissolveAmountId, from);
|
||||
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.unscaledDeltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
runtimeMaterial.SetFloat(DissolveAmountId, Mathf.Lerp(from, to, t));
|
||||
yield return null;
|
||||
}
|
||||
|
||||
runtimeMaterial.SetFloat(DissolveAmountId, to);
|
||||
onComplete?.Invoke();
|
||||
}
|
||||
|
||||
private void ApplyInstantState(float amount, float directionValue)
|
||||
{
|
||||
EnsureRuntimeMaterial();
|
||||
if (runtimeMaterial == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
runtimeMaterial.SetFloat(DirectionId, directionValue);
|
||||
runtimeMaterial.SetFloat(DissolveAmountId, Mathf.Clamp01(amount));
|
||||
}
|
||||
|
||||
private void EnsureRuntimeMaterial()
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
image = GetComponent<Image>();
|
||||
}
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Material source = materialTemplate != null
|
||||
? materialTemplate
|
||||
: image.material;
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (runtimeMaterial != null && runtimeMaterial.shader == source.shader)
|
||||
{
|
||||
if (image.material != runtimeMaterial)
|
||||
{
|
||||
image.material = runtimeMaterial;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (runtimeMaterial != null)
|
||||
{
|
||||
Destroy(runtimeMaterial);
|
||||
}
|
||||
|
||||
runtimeMaterial = new Material(source);
|
||||
runtimeMaterial.name = source.name + " (idol runtime)";
|
||||
image.material = runtimeMaterial;
|
||||
}
|
||||
|
||||
private static float GetShaderDirectionForEnter(SweepSide side)
|
||||
{
|
||||
return side == SweepSide.FromLeft ? 0f : 1f;
|
||||
}
|
||||
|
||||
private static float GetShaderDirectionForExit(SweepSide side)
|
||||
{
|
||||
return side == SweepSide.FromLeft ? 1f : 0f;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user