C# 约束类型为的属性

C# 约束类型为的属性,c#,unity3d,types,constraints,C#,Unity3d,Types,Constraints,我正在使用一个类作为我正在设计的游戏中实体的数据模型。它存储有关实体外观、大小、触发碰撞规则的信息。本质上,任何关于渲染对象或引发其事件的静态信息 我还想让我的通用定义包括一个可互换的定义,用于在加载对象时发生什么,以及在更新对象时每次勾选发生什么 这是一个我打算在整个游戏中实现的架构,但解释我的问题的最好例子是咒语 当在我的游戏中施放咒语时,玩家包含对存储在我游戏中的资源的引用。该资产是类SpellData的实例。它包含有关其粒子、大小、外观等的所有字段。我也希望它能包含咒语的功能。要明确的是

我正在使用一个类作为我正在设计的游戏中实体的数据模型。它存储有关实体外观、大小、触发碰撞规则的信息。本质上,任何关于渲染对象或引发其事件的静态信息

我还想让我的通用定义包括一个可互换的定义,用于在加载对象时发生什么,以及在更新对象时每次勾选发生什么

这是一个我打算在整个游戏中实现的架构,但解释我的问题的最好例子是咒语

当在我的游戏中施放咒语时,玩家包含对存储在我游戏中的资源的引用。该资产是类
SpellData
的实例。它包含有关其粒子、大小、外观等的所有字段。我也希望它能包含咒语的功能。要明确的是,我不希望咒语的执行发生在
咒语数据
的范围内,咒语数据是完全静态的。它只是一段数据,其他事物从中读取,以确定要做什么

目前,我处理这个问题的方式是,我有一个名为
ISpellEffect
的界面,它为该法术需要执行的
OnStart
OnUpdate
方法设置签名

然后我有一系列从
ISpellEffect
继承的类,比如
HealSpellEffect
,它们实际上包含这些函数的定义。My
SpellData
包含的字段和属性

私有类型SpellEffectRef=SpellEffect

在实际资源中,将该
SpellEffectRef
设置为一个值,例如
HealSpellEffect
,然后将其存储起来

然后施法的过程是

  • 玩家请求服务器生成一个新的空咒语对象,并将引用传递给它打算使用的咒语数据资源
  • 服务器将注入该资源和施放该资源的玩家,以及一些其他有关类似于咒语的目标位置和目标轨迹的信息。该法术现在完全超出玩家的范围
  • 然后,该咒语读取
    咒语数据
    ,作为
    咒语效果
    类的参考。它创建一个
    法术效果类的实例,并注入所有与持续时间、伤害值相关的信息,或从先前传入的角色获得的其他信息
  • 将调用
    法术效果
    OnStart()
    ,并将其
    OnUpdate()
    设置为该法术自己的
    Update()
    调用上的协同程序
  • 整个设计的唯一问题是,我无法找到一种方法来约束
    SpellData
    中的
    SpellEffectRef
    仅接受从
    ISpellEffect
    继承的值。我需要它,否则每当我尝试与此属性交互或传递它时,就会出现生成错误,因为创建它的实例不会显式创建
    ISpellEffect
    请帮助

    为了保持关注点的分离、低网络流量和高效的模块化代码,我的所有功能和数据都必须像这样可插入,这一点非常重要

    编辑:建议的MCV示例

    public class SpellData \\ Instances of this class are saved as Assets
    {
        string AssetId;
        ParticleSystem particleSystem;
        Mesh collisionModel;
        Type SpellEffectRef; \\ Here is where I'd love to have something like where SpellEffectRef : ISpellEffect or something like that
    }
    
    public abstract class SpellEffect
    {
        Spell parent;
        Character caster;
        SpellData spellData;
        float duration;
        float ticksPerProc
    
        private float tickEnumerator;
        private flaot procDeltaTime;
        private List<Character> targets;
    
        public void OnStart();
        public IEnumerator OnUpdate();
    }
    
    public class HealSpellEffect : SpellEffect;
    {
        public void OnStart()
        {
            parent.Destroy(Duration); //Set the spell to self destruct after its duration
            parent.Transform = caster.Transform; //Moves the Spell to be centered on its caster
        }
        public IEnumerator OnUpdate()
        {
            targets = parent.Collider.GetAllColliders().Where(n=>n is Character && n.Faction == caster.Faction)
            tickEnumerator += 1;
            procDeltaTime += Time.DeltaTime;
            if(tickEnumerator == ticksPerProc)
            {
                foreach member in targets
                {
                    member.ApplyDamage(this, .1 * procDeltaTime, Damage.DamageTypeEnum.Healing);
                }
            }
            tickEnumerator = 0;
            procDeltaTime = 0;
            yeild;
        }
    }
    
    public class Spell : MonoBehaviour
    {
        public Spell(SpellData _spellData)
        {
            spellData = _spellData;
            spellEffect = CreateInstance(_spellData.SpellEffectRef)
        }
        SpellData spellData;
        SpellEffect spellEffect;
    
        Start()
        {
            spellEffect.OnStart();
        }
    
        Update()
        {
            StartCoRountine(spellEffect.OnUpdate());
        }
    }
    
    public class SpellData\\n此类的实例保存为资产
    {
    字符串AssetId;
    粒子系统;
    网格碰撞模型;
    键入SpellEffectRef;\\我希望在这里输入类似于where SpellEffectRef:ISpellEffect或类似的内容
    }
    公共抽象类拼写效应
    {
    拼写父母;
    字符铸造机;
    拼写数据拼写数据;
    浮动持续时间;
    浮点数
    私人浮动分子;
    私人flaot procDeltaTime;
    私人名单目标;
    public void OnStart();
    公共IEnumerator OnUpdate();
    }
    公共职业法术效果:法术效果;
    {
    public void OnStart()
    {
    parent.Destroy(持续时间);//在持续时间后将法术设置为自毁
    parent.Transform=caster.Transform;//将法术移动到施法者的中心
    }
    公共IEnumerator OnUpdate()
    {
    targets=parent.Collider.GetAllColliders()。其中(n=>n是角色和&n.partition==caster.partition)
    分子+=1;
    procDeltaTime+=Time.DeltaTime;
    if(tickEnumerator==ticksPerProc)
    {
    目标中的每个成员
    {
    成员.ApplyDamage(这是.1*procDeltaTime,Damage.DamageTypeEnum.Healing);
    }
    }
    分子=0;
    procDeltaTime=0;
    耶尔德;
    }
    }
    公共课咒语:单一行为
    {
    公共拼写(拼写数据_拼写数据)
    {
    拼写数据=_拼写数据;
    spellEffect=CreateInstance(\u spellData.SpellEffectRef)
    }
    拼写数据拼写数据;
    法术效果;
    开始()
    {
    spellEffect.OnStart();
    }
    更新()
    {
    StartContine(拼写效果.OnUpdate());
    }
    }
    
    我已经解决了这个问题,对于任何一个偶然发现这个问题的人来说,解决方案是使用访问器(特别是它的set方法)执行检查
    值是否为SpellEffect
    。然后,在所有实现情况下,您必须在创建实例后简单地强制转换它。

    将SpellEffect作为从ScriptableObject派生的抽象类如何?然后,您可以将SpellEffect类型的字段放在SpellDataIt确实从scriptableobject继承的字段上,但我希望直接传递该类型,因为我实际上将其用作对象委托。我还想在其他项目中利用对象委托的功能,这些项目没有令人敬畏的单元ScriptableObject库。此外,与使用