You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何用泛型枚举参数实现模块化动画控制器?

问题描述

我想要制作一个可对任意3D模型播放动画的泛型类,现有AnimationController类的ChangeAnimation方法使用string类型作为第一个参数,代码如下:

public class AnimationController {
    public void ChangeAnimation(string animation, int priority = 0, float crossfadeDuration = 0.2f, float animationSpeed = 1f) {
        if(priority is higher && this animation isn't already playing) {
            model.PlayAnimation(animation);
        }
    }
}

但我希望将第一个参数替换为枚举类型,而非FireballAnimation这类特定枚举:

public void ChangeAnimation(FireballAnimation animation)

否则该类会失去模块化特性。同时我也不想每次调用ChangeAnimation()时都调用.ToString()方法。

我希望在同一代码库中实现如下调用:

// 在火球类的上下文下:
public enum FireballAnimation {
    Casted,
    Flying,
    Impact,
}

AnimationController.ChangeAnimation(FireballAnimation.Impact);

// 在玩家类的上下文下:
public enum PlayerAnimation {
    None,
    Idle,
    Walking,
    StrafingLeft,
    StrafingRight,
    WalkingBackwards,
    Jumping,
    Casting,
}

AnimationController.ChangeAnimation(PlayerAnimation.Jumping);

这要求ChangeAnimation方法的第一个参数为泛型枚举类型,请问这在C#中是否可行?


解决方案

这在C#中完全可行,通过泛型方法搭配枚举类型约束即可实现你的需求,既保留AnimationController的模块化,又无需调用者手动转换字符串。

实现思路

  1. 给ChangeAnimation方法添加泛型参数,并用where T : Enum约束限制参数必须为枚举类型;
  2. 在方法内部完成枚举到字符串的转换(调用者无需关心这一步);
  3. 保留原有的优先级判断、动画播放逻辑。

修改后的完整代码

public class AnimationController {
    // 假设这是你的3D模型实例,根据实际类型替换
    private Model model;

    // 记录当前播放的动画状态
    private string _currentAnimation;
    private int _currentPriority;

    public void ChangeAnimation<T>(T animation, int priority = 0, float crossfadeDuration = 0.2f, float animationSpeed = 1f) 
        where T : Enum {
        // 将枚举值转为对应的动画名称
        string animationName = Enum.GetName(typeof(T), animation);
        
        // 优先级判断+播放状态检查(修正原代码的语法问题)
        if (priority > _currentPriority && !IsAnimationPlaying(animationName)) {
            model.PlayAnimation(animationName);
            // 更新当前状态
            _currentAnimation = animationName;
            _currentPriority = priority;
        }
    }

    // 辅助方法:判断指定动画是否正在播放
    private bool IsAnimationPlaying(string animationName) {
        return _currentAnimation == animationName;
    }
}

调用示例

完全符合你期望的调用方式,直接传入不同枚举类型的值即可:

// 火球类中调用
var controller = new AnimationController();
controller.ChangeAnimation(FireballAnimation.Impact);

// 玩家类中调用
controller.ChangeAnimation(PlayerAnimation.Jumping);

额外优化点

如果枚举成员名称和实际动画文件名不一致(比如枚举是Flying但动画名是fireball_flying),可以给枚举添加自定义属性来映射:

// 自定义属性
public class AnimationNameAttribute : Attribute {
    public string Name { get; }
    public AnimationNameAttribute(string name) => Name = name;
}

// 修改枚举
public enum FireballAnimation {
    [AnimationName("fireball_casted")]
    Casted,
    [AnimationName("fireball_flying")]
    Flying,
    [AnimationName("fireball_impact")]
    Impact,
}

然后在ChangeAnimation方法中通过反射读取属性值,替换Enum.GetName的逻辑,进一步提升灵活性。


内容的提问来源于stack exchange,提问作者MaybeAFish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 22:34:53