Skip to content

Instantly share code, notes, and snippets.

@green224
Created November 18, 2021 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save green224/d6334bf17e4a66015098f3ad503eed7c to your computer and use it in GitHub Desktop.
Save green224/d6334bf17e4a66015098f3ad503eed7c to your computer and use it in GitHub Desktop.
UnityのAnimationCurveを自前でシリアライズするためのクラス
using System;
using UnityEngine;
using System.Linq;
[Serializable]
public struct AnimCurveKey
{
#pragma warning disable 0414
[SerializeField] byte serializedVersion; // これは3固定
public float time, value;
public float inSlope, outSlope;
[SerializeField] int tangentMode;
public WeightedMode weightedMode;
public float inWeight, outWeight;
#pragma warning restore 0414
public enum TangentMode
{
Free = 0,
Auto = 1,
Linear = 2,
Constant = 3,
ClampedAuto = 4
}
public TangentMode LeftTangentMode {
get => new TangentModeDetail(tangentMode).LeftTangentMode;
set {
var tmd = new TangentModeDetail(tangentMode);
tmd.LeftTangentMode = value;
tangentMode = tmd.value;
}
}
public TangentMode RightTangentMode {
get => new TangentModeDetail(tangentMode).RightTangentMode;
set {
var tmd = new TangentModeDetail(tangentMode);
tmd.RightTangentMode = value;
tangentMode = tmd.value;
}
}
public bool TangentIsBroken {
get => new TangentModeDetail(tangentMode).IsBroken;
set {
var tmd = new TangentModeDetail(tangentMode);
tmd.IsBroken = value;
tangentMode = tmd.value;
}
}
// UnityのKeyframeにコンバートする
public Keyframe Convert()
{
return new Keyframe(
time, value,
inSlope, outSlope,
inWeight, outWeight
) {
#pragma warning disable 0618
tangentMode = tangentMode,
#pragma warning restore 0618
weightedMode = weightedMode,
};
}
// シリアライズバージョンを決める必要があるので、必ずこれ経由で作成すること
public AnimCurveKey(
float time, float value,
float slope, TangentMode tangentMode
) {
serializedVersion = 3;
this.time = time;
this.value = value;
inSlope = outSlope = slope;
this.tangentMode = new TangentModeDetail{
LeftTangentMode = tangentMode,
RightTangentMode = tangentMode,
IsBroken = false,
}.value;
weightedMode = WeightedMode.None;
inWeight = outWeight = 0;
}
public AnimCurveKey(
float time, float value,
float inSlope, float outSlope,
TangentMode leftTangentMode, TangentMode rightTangentMode
) {
serializedVersion = 3;
this.time = time;
this.value = value;
this.inSlope = inSlope;
this.outSlope = outSlope;
tangentMode = new TangentModeDetail{
LeftTangentMode = leftTangentMode,
RightTangentMode = rightTangentMode,
IsBroken = true,
}.value;
weightedMode = WeightedMode.None;
inWeight = outWeight = 0;
}
/** TangentModeのint型から、中身の細かいデータを得るためのもの */
struct TangentModeDetail
{
public int value;
public TangentMode LeftTangentMode {
get => (TangentMode)( (value>>1) & 0b111 );
set => this.value =
(this.value & 0b1111_0001) |
((int)value << 1);
}
public TangentMode RightTangentMode {
get => (TangentMode)( (value>>5) & 0b111 );
set => this.value =
(this.value & 0b0001_1111) |
((int)value << 5);
}
public bool IsBroken {
get => (value & 1) != 0;
set => this.value =
(this.value & 0b1111_1110) |
(value ? 1 : 0);
}
public TangentModeDetail(int value) => this.value = value;
}
}
[Serializable]
public struct AnimationCurveWrapper
{
#pragma warning disable 0414
[SerializeField] byte serializedVersion; // これは2固定
[SerializeField] AnimCurveKey[] m_Curve;
// TODO : これらの使い道を調査する
[SerializeField] byte m_PreInfinity;
[SerializeField] byte m_PostInfinity;
[SerializeField] byte m_RotationOrder;
#pragma warning restore 0414
static public AnimationCurveWrapper InitValue =>
new AnimationCurveWrapper(
new[] {
new AnimCurveKey(0, 0, 1, AnimCurveKey.TangentMode.Auto),
new AnimCurveKey(1, 1, 1, AnimCurveKey.TangentMode.Auto),
}
);
public AnimCurveKey[] Keys {
get => m_Curve;
set {
m_Curve = value;
_nativeAC = null;
}
}
public float Evaluate(float time) => _nativeAC.Evaluate(time);
// デフォルト値。シリアライズバージョンを決める必要があるので、必ずこれ経由で作成すること
public AnimationCurveWrapper( AnimCurveKey[] keys ) {
serializedVersion = 2;
m_Curve = keys;
m_PreInfinity = 2;
m_PostInfinity = 2;
m_RotationOrder = 4;
_nativeAC = null;
}
AnimationCurve _nativeAC;
AnimationCurve NativeAC { get {
if (_nativeAC == null)
_nativeAC = new AnimationCurve(
m_Curve.Select(i => i.Convert()).ToArray()
) {
};
return _nativeAC;
} }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment