Luca3317 / TMPEffects

Easily animate Unity text and apply other effects with custom tags
https://luca3317.dev/tmpeffects
MIT License
248 stars 11 forks source link

What's the right away to set a time offset for a wave? #6

Closed Abaudat closed 6 months ago

Abaudat commented 6 months ago

Hi, thanks a lot for the incredible asset. I'm wondering if there is an existing way to specify an offset to the wave tag directly? I didn't find anything in the docs.

For the record my use case is as follows: I have multiple instances of an object which uses wave to animate text that spawn at the same time. I offset the bobbing animation of the card and the idle animation of the animals so they're not in sync, and I would like to do so as well for the text wave animation.

https://github.com/Luca3317/TMPEffects/assets/26631944/9ef5977d-457b-4c14-8ed4-ca253d748898

Luca3317 commented 6 months ago

Hi, the wave tag does not allow specifying a manual offset at the moment, you can only use the different WaveOffsetType values. It might be a good idea to modify WaveOffset parameters to additionally allow manual offsets down the line.

You can make a custom wave animation (or modify the existing one) by just adding a manual offset field and updating the methods to account for it. I went ahead and quickly made this class for you; youll still have to create the asset and add it to your database ofc.
You can set the offset with "offset" or "off".

[CreateAssetMenu(fileName = "new CustomWaveAnimation", menuName = "TMPEffects/Animations/CustomWave")]
public class CustomWaveAnimation : TMPAnimation
{
    [Tooltip("The wave that defines the behavior of this animation. No prefix.\nFor more information about Wave, see the section on it in the documentation.")]
    [SerializeField] Wave wave = new Wave(AnimationCurveUtility.EaseInOutSine(), AnimationCurveUtility.EaseInOutSine(), 0.5f, 0.5f, 1f, 1f, 0.2f);
    [Tooltip("The way the offset for the wave is calculated.\nFor more information about Wave, see the section on it in the documentation.\nAliases: waveoffset, woffset, waveoff, woff")]
    [SerializeField] WaveOffsetType waveOffsetType = WaveOffsetType.XPos;

    [SerializeField] float offset = 0f;

    public override void Animate(CharData cData, IAnimationContext context)
    {
        Data data = (Data)context.CustomData;

        // Evaluate the wave based on time and offset
        float eval = data.wave.Evaluate(context.AnimatorContext.PassedTime, GetWaveOffset(cData, context, data.waveOffsetType) + data.offset).Item1;

        // Move the character up based on the wave evaluation
        cData.SetPosition(cData.InitialPosition + Vector3.up * eval);
    }

    public override void SetParameters(object customData, IDictionary<string, string> parameters)
    {
        if (parameters == null) return;

        Data data = (Data)customData;
        if (TryGetWaveOffsetParameter(out var wot, parameters, "waveoffset", WaveOffsetAliases)) data.waveOffsetType = wot;
        if (TryGetFloatParameter(out var offset, parameters, "offset", "off")) data.offset = offset;
        data.wave = CreateWave(this.wave, GetWaveParameters(parameters));
    }

    public override bool ValidateParameters(IDictionary<string, string> parameters)
    {
        if (parameters == null) return true;
        if (HasNonWaveOffsetParameter(parameters, "waveoffset", WaveOffsetAliases)) return false;
        if (HasNonFloatParameter(parameters, "offset", "off")) return false;
        return ValidateWaveParameters(parameters);
    }

    public override object GetNewCustomData()
    {
        return new Data() { wave = this.wave, waveOffsetType = this.waveOffsetType, offset = this.offset };
    }

    private class Data
    {
        public Wave wave;
        public WaveOffsetType waveOffsetType;
        public float offset;
    }
}
Abaudat commented 6 months ago

Thanks a lot!