C# 约束类型为的属性
我正在使用一个类作为我正在设计的游戏中实体的数据模型。它存储有关实体外观、大小、触发碰撞规则的信息。本质上,任何关于渲染对象或引发其事件的静态信息 我还想让我的通用定义包括一个可互换的定义,用于在加载对象时发生什么,以及在更新对象时每次勾选发生什么 这是一个我打算在整个游戏中实现的架构,但解释我的问题的最好例子是咒语 当在我的游戏中施放咒语时,玩家包含对存储在我游戏中的资源的引用。该资产是类C# 约束类型为的属性,c#,unity3d,types,constraints,C#,Unity3d,Types,Constraints,我正在使用一个类作为我正在设计的游戏中实体的数据模型。它存储有关实体外观、大小、触发碰撞规则的信息。本质上,任何关于渲染对象或引发其事件的静态信息 我还想让我的通用定义包括一个可互换的定义,用于在加载对象时发生什么,以及在更新对象时每次勾选发生什么 这是一个我打算在整个游戏中实现的架构,但解释我的问题的最好例子是咒语 当在我的游戏中施放咒语时,玩家包含对存储在我游戏中的资源的引用。该资产是类SpellData的实例。它包含有关其粒子、大小、外观等的所有字段。我也希望它能包含咒语的功能。要明确的是
SpellData
的实例。它包含有关其粒子、大小、外观等的所有字段。我也希望它能包含咒语的功能。要明确的是,我不希望咒语的执行发生在咒语数据
的范围内,咒语数据是完全静态的。它只是一段数据,其他事物从中读取,以确定要做什么
目前,我处理这个问题的方式是,我有一个名为ISpellEffect
的界面,它为该法术需要执行的OnStart
和OnUpdate
方法设置签名
然后我有一系列从ISpellEffect
继承的类,比如HealSpellEffect
,它们实际上包含这些函数的定义。MySpellData
包含的字段和属性
私有类型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库。此外,与使用