随时间推移设置C#属性动画的方法?

随时间推移设置C#属性动画的方法?,c#,animation,properties,interpolation,keyframe,C#,Animation,Properties,Interpolation,Keyframe,我目前正在尝试在某些对象上设置一组公共属性的动画。通常它们的类型是float或vectors(该类型在编译时已知)。我希望能够: 为它们指定一个静态值(MyObject.Duration=10f;)或 通过指定最小值和最大值以及可选的权重(MyObject.Duration=new RandomFloat(5f、20f、2f);)为其指定随机值,或 将此属性“绑定”到另一个对象的属性(设想一个子对象将其某些属性绑定到其父对象,如颜色、大小或其他)或 为它们指定关键帧动画的排序,使用时间代码指定可

我目前正在尝试在某些对象上设置一组公共属性的动画。通常它们的类型是float或vectors(该类型在编译时已知)。我希望能够:

  • 为它们指定一个静态值(MyObject.Duration=10f;)或
  • 通过指定最小值和最大值以及可选的权重(MyObject.Duration=new RandomFloat(5f、20f、2f);)为其指定随机值,或
  • 将此属性“绑定”到另一个对象的属性(设想一个子对象将其某些属性绑定到其父对象,如颜色、大小或其他)或
  • 为它们指定关键帧动画的排序,使用时间代码指定可变数量的关键帧,并指定该特定时间点的属性值,以及有关如何在这些帧之间插值的信息
  • 关键帧应该能够接受每个帧的随机值,包括时间和属性值

    对于这种系统,什么是一种实用的方法?目前我正在考虑多态性:使用公共值属性和/或GetValue(float time)-方法实现基类或接口,然后创建不同的子类,如StaticValue、RandomValue、BindingValue和AnimatedValue来实现这个基类或接口。不过,这看起来并不十分优雅,即使是简单对象的初始化也变得有点乏味

    另一个想法是将这些属性实现为常规浮点或向量,并创建绑定到这些属性的特殊“修饰符”类型。要检索属性的“真实”值,我首先调用绑定到属性的任何修饰符,这将反过来更新实际对象的属性,以便稍后检索。这很可能意味着在某个时刻使用反射,这可能对性能非常不利,因为我可能每秒要更新数千个属性几十次

    有什么建议吗?作为一个新手,我(希望)错过了一些比我已经玩过的更优雅和/或实用的解决方案:(

    编辑:
    可能应该在前面提到这一点,但WPF不是一个选项-它不适用于所有目标平台,因此我不能依赖它。我知道它强大的数据绑定和动画功能,但我需要自己开发(或找到其他满足我需要的轻量级替代品).

    我认为您描述的多态解决方案是实现这一点的最优雅的面向对象方法。您觉得它有什么不雅之处

    至于使用实际的数据类型和修饰符类型,我建议您考虑使用隐式运算符重载

    您可以使用所需的所有行为定义类,但提供与“值”类型之间的转换,以便您可以像获取/分配该类型的值一样获取/分配值。示例将有助于:

    public class MyFloat
    {
        float innerValue;
    
        // private constructor; instantiate using a float directly
        private MyFloat(float innerValue) { this.innerValue = innerValue; }
    
        public string Description { get { return "some metadata"; } }
    
        public int NumberOfFrames { get; set; }
    
        // conversion from MyFloat to float
        public static implicit operator float(MyFloat mine)
        {
            return mine.innerValue; // you can access private members here
        }
    
        // conversion from float to MyFloat
        public static implicit operator MyFloat(float val)
        {
            return new MyFloat(val); // use the private constructor
        }
    }
    
    在使用过程中,您可以执行以下操作:

    MyFloat mine = 9f; 
    mine.NumberOfFrames = 15;
    
    或者

    至于实例化的繁琐,我认为这种场景是内部DSL/fluent接口的完美候选

    你可以编一些表达力强且简洁的东西,比如:

    var animatedObject = Sprite.with(RandomMotion.animatated_between(0f).and(10f))
        .lasts(4).seconds;
    var otherObject = Sprite.with<NoMotion>().starts_at(100, 0);
    var yetAnother = Sprite.with(SteadyMotion.at(7f))
        .starts_at(100, 200)
        .weighing(.5f)
        .lasts(15).frames;
    
    var animatedObject=Sprite.with(RandomMotion.animated_介于(0f.)和(10f)之间)
    .持续(4)秒;
    var otherObject=Sprite.with()。从(100,0)开始;
    var yetAnother=雪碧(在(7f)下的稳定运动)
    .从(100200)开始
    .称重(.5f)
    .最后(15)帧;
    
    我认为您描述的多态解决方案是实现这一点的最优雅的面向对象方法。您觉得它有什么不雅之处

    至于使用实际的数据类型和修饰符类型,我建议您考虑使用隐式运算符重载

    您可以使用所需的所有行为定义类,但提供与“值”类型之间的转换,以便您可以像获取/分配该类型的值一样获取/分配值。示例将有助于:

    public class MyFloat
    {
        float innerValue;
    
        // private constructor; instantiate using a float directly
        private MyFloat(float innerValue) { this.innerValue = innerValue; }
    
        public string Description { get { return "some metadata"; } }
    
        public int NumberOfFrames { get; set; }
    
        // conversion from MyFloat to float
        public static implicit operator float(MyFloat mine)
        {
            return mine.innerValue; // you can access private members here
        }
    
        // conversion from float to MyFloat
        public static implicit operator MyFloat(float val)
        {
            return new MyFloat(val); // use the private constructor
        }
    }
    
    在使用过程中,您可以执行以下操作:

    MyFloat mine = 9f; 
    mine.NumberOfFrames = 15;
    
    或者

    至于实例化的繁琐,我认为这种场景是内部DSL/fluent接口的完美候选

    你可以编一些表达力强且简洁的东西,比如:

    var animatedObject = Sprite.with(RandomMotion.animatated_between(0f).and(10f))
        .lasts(4).seconds;
    var otherObject = Sprite.with<NoMotion>().starts_at(100, 0);
    var yetAnother = Sprite.with(SteadyMotion.at(7f))
        .starts_at(100, 200)
        .weighing(.5f)
        .lasts(15).frames;
    
    var animatedObject=Sprite.with(RandomMotion.animated_介于(0f.)和(10f)之间)
    .持续(4)秒;
    var otherObject=Sprite.with()。从(100,0)开始;
    var yetAnother=雪碧(在(7f)下的稳定运动)
    .从(100200)开始
    .称重(.5f)
    .最后(15)帧;
    
    您研究过WPF吗?它是一种支持动画的C#GUI技术。但它需要您重新设计整个GUI。不幸的是,在这种情况下,WPF不是一个选项,要设置动画的属性甚至不一定存在于UI中,而是底层模拟的一部分。是否考虑使用IValueConverter对象在绑定中?这样,您的绑定对象不一定需要了解有关动画的任何信息。WPF允许您定义自己的(非UI)可以进行数据绑定和动画的类和属性。它的依赖属性系统是为满足您的需求而构建的。正如我已经说过的,WPF不是一个选项。它不适用于所有目标平台,因此我不能依赖它。我也不确定它的性能,因为它的数据绑定机制比其他平台更强大、更灵活我在这里需要什么。你研究过WPF吗?它是一种支持动画的C#GUI技术。但它需要你重新设计整个GUI。不幸的是,在这种情况下,WPF不是一个选项,要动画的属性甚至不必驻留在UI中,而是底层模拟的一部分。使用IValueConver有什么想法吗绑定中的对象?这样,绑定对象就不一定需要了解任何有关动画的信息。WPF允许您定义自己的(非UI)类和属性,这些类和属性可以进行数据绑定和动画。它的依赖属性系统是为满足您的要求而构建的。正如我前面所说,