Skip to content

Instantly share code, notes, and snippets.

@Kurante2801
Last active February 16, 2023 20:27
Show Gist options
  • Save Kurante2801/531915a8a6d6d5d9c7ea390cd00ffc73 to your computer and use it in GitHub Desktop.
Save Kurante2801/531915a8a6d6d5d9c7ea390cd00ffc73 to your computer and use it in GitHub Desktop.
Implement Unity's AnimationCurve in Java by precalculating the values a curve can have in Unity and then pasting the values in Java
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using UnityEngine;
[ExecuteAlways]
public class AnimationCurveBaker : MonoBehaviour
{
public AnimationCurve curve;
public void Bake(int length, float multiplier, string separator)
{
var values = new float[length + 1];
var l = (float)length;
for (int i = 0; i <= length; i++)
values[i] = curve.Evaluate(i / l) * multiplier;
var list = new List<string>();
for (int i = 0; i <= length; i++)
list.Add(values[i].ToString(CultureInfo.InvariantCulture));
var str = string.Join(separator, list.ToArray());
Debug.Log(str);
GUIUtility.systemCopyBuffer = str;
Debug.Log("Copied values to clipboard");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
// Goes in an Editor folder
[CustomEditor(typeof(AnimationCurveBaker))]
public class AnimationCurveBakerEditor : Editor
{
int length = 60;
float multiplier = 100f;
string separator = "#";
public override void OnInspectorGUI()
{
DrawDefaultInspector();
length = EditorGUILayout.IntField("Length", length);
multiplier = EditorGUILayout.FloatField("Multiplier", multiplier);
separator = EditorGUILayout.TextField("Separator", separator);
if (GUILayout.Button("Bake"))
{
var script = target as AnimationCurveBaker;
script.Bake(length, multiplier, separator);
}
}
}
// Example:
// val curve = BakedAnimationCurve.valueOf("0#100") // Linear func
public class BakedAnimationCurve {
float[] values;
public float multiplier;
public BakedAnimationCurve(float[] values) {
this.values = values;
this.multiplier = 100f;
}
public BakedAnimationCurve(float[] values, float multiplier) {
this.values = values;
this.multiplier = multiplier;
}
public static BakedAnimationCurve valueOf(String string) {
return BakedAnimationCurve.valueOf("#", string);
}
public static BakedAnimationCurve valueOf(String separator, String string) {
return BakedAnimationCurve.valueOf(separator, string, 100f);
}
public static BakedAnimationCurve valueOf(String separator, String string, float multiplier) {
String[] separated = string.split(separator);
float[] values = new float[separated.length];
for (int i = 0; i < separated.length; i++)
values[i] = Float.parseFloat(separated[i]);
return new BakedAnimationCurve(values, multiplier);
}
public float evaluate(float t) {
if (values.length < 2)
throw new IllegalArgumentException("Values array must have at least 2 values");
float percent = Math.max(0f, Math.min(1f, t)) * (values.length - 1f);
float rem = percent % 1f;
// We have a baked value already
if (rem == 0f)
return values[(int)percent] / multiplier;
// We're trying to get a value in between two baked values, interpolate between them
float a = values[(int)Math.floor(percent)];
float b = values[(int)Math.ceil(percent)];
return (rem * (b - a) + a) / multiplier;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment