c#, Unity -单个函数接受多个不同的对象

本文关键字:对象 Unity 单个 函数 | 更新日期: 2023-09-27 17:52:33

我需要你的帮助。我正在安排一个脚本,可以在RPG游戏中执行技能之前检查各种条件。

所有这些技能都属于单独的职业(火球,治疗,毒药),都派生自另一个抽象类(远程技能,治疗技能,DOT技能),它们都是抽象类(技能)的父类。

为了避免创建多个函数,处理每一个单一的能力:

void condition(Fireball f){//test}; 
void condition(Heal f){//test}; 
void condition(Poison f){//test};

我正在尝试创建一个可以接受所有类型能力的单一函数调用。

void condition(Ability f){//test}

到目前为止,我已经成功地创建了一个Fireball对象并将其传递给函数。

Fireball _fire = new FireBall();
condition(_fire);
void condition(Ability f){//test}

从这里我可以访问在技能类中初始化的所有公共变量,但我不能访问在派生类中初始化的公共变量(远程技能,治疗技能,DOT技能)。

是我忘记了什么,还是我看问题的角度不对?(我不擅长利用继承和抽象类)

c#, Unity -单个函数接受多个不同的对象

在不了解条件函数的更多细节的情况下,您有两个选择。

第一,你可以这样做

if (f.GetType() == typeof(FireBall))
{
  fireBall = (FireBall)f;
  fireBall.FireTheFireBall();
}
else if (f.GetType() == typeof(Heal))
...

或者,你的能力可以有一个抽象的激活方法,所有的派生类都需要重载它:

class Fireball
{
   public override void Activate()
   {
       //do fireball specific things
       this.FireTheFireBall();
   }   
   public void FireTheFireBall() {...}    
}
class Heal
{
   public override void Activate()
   {
       //do healing specific things
       this.ApplyTheBandage();
   }
   ...
}
abstract class Ability
{
  public abstract void Activate();
}
void condition(Ability f){
   f.Activate(); //runs the version of Activate of the derived class
}

那么任何与Ability相关的东西都可以调用someAbility.Activate(),并且派生类提供的实现将被执行。

你还应该研究接口,它有点像抽象类。接口的好处是可以实现多个接口,而只能从一个基抽象类继承。想想一个IKnob界面,它有Turn和Pull功能。你可能有一个实现IKnob的Drawer类,一个Door类,一个实现Turn和激活陷阱的TrappedDoor类。玩家走到一扇门前,点击使用按钮,你将对象open (IKnob knob)

传递给open函数
void Open(IKnob knob)
{
   knob.Turn();
   knob.Pull();
}
class TrappedDoor:IKnob,IMaterial,ISomethingElse,IHaveTheseOtherCapabilitiesAsWell
{
  private bool TrapAlreadySprung{get;set;}
  //more complex properties would allow traps to be attached either to the knob, or the door, such that in one case turning the knob activates the trap, and in the other, Pull activates the trap
  public Turn() { 
    if(! TrapAlreadySprung)
    {
      MessageBox("You hit your head, now you're dead");
    }
  }
}

有方法来检查是否有一个接口,所以如果一些玩家走到一个项目,并试图与它交谈,你可以检查对象是否有ICanTalk接口,如果它然后调用object. getreply ("Hello")和对象可以响应。所以如果你愿意,你可以有会说话的门和石头。你得到所有处理与事物对话/显示响应等的代码,与ICanTalk接口方法一起工作,然后其他类可以实现ICanTalk,它们各自决定如何响应被交谈。这个概念被称为"关注点分离",可以帮助您创建更多的可重用代码。

重要的是,你可以编写一段代码,一个算法,函数等,只与该接口工作,这样一旦你让代码与接口工作,你就可以在任何类上使用该接口,而该类可以利用现有的代码。

。你的condition函数,如果它接受了一个IAbility接口,一旦你让代码工作,那么你创建的任何实现IAbility的类都可以传递给条件函数。条件函数负责做它应该做的任何事情,而实现IAbility的类则负责在它所实现的方法中特定于它的任何事情。

当然,实现抽象类或接口的类必须实现所需的方法,所以有时您可能会觉得自己在复制代码。例如,如果你有类似的类,如TrappedDoor和Door,如果陷阱没有设置/已经弹起,则TrappedDoor的行为可能就像普通的Door一样。因此,在这种情况下,您可以继承Door,或者拥有一个私有的Door属性(称为"composition")。如果陷阱已经启动,那么你可以调用基本的Door类或私有的Door属性并调用。turn,这样你就可以在陷阱没有激活的情况下重用普通门的默认行为。

测试对象是否实现接口

我个人主要使用接口和组合,而不是继承。并不是说继承很糟糕,而是继承层次结构很快就会变得非常复杂。