我在 Unity 中创建了一个新的空项目,并假装是一台计算机,结果空项目的重量非常大 - 67mb。我附上了所有软件包和日志,请在此处输入图片描述,输入...
我在 Unity 中创建了一个新的空项目,并假装是一台计算机,结果空项目的重量非常大 - 67mb。我附上了所有软件包和日志 在此处输入图片说明 在此处输入图片说明
我尝试禁用一些软件包,但构建重量最多减少了 2 MB
背景我使用 Unity 编写代码,使用 C#8.0。我正在制作一款游戏,玩家通过打出具有不同效果的卡牌与敌人战斗(比如 Slay the Spire)。玩家选择卡牌,然后
我在 Unity 中使用 C#8.0 进行编码。
我正在制作一款游戏,玩家通过打出具有不同效果的卡牌与敌人战斗(例如 Slay the Spire )。玩家选择卡牌,然后选择卡牌的目标,然后(如果目标有效)调用卡牌的效果。
许多不同的游戏对象都可以成为卡片的目标:敌人、玩家角色、其他卡片、回合计数器、天空等。对于每个可以作为目标的对象,我都有它的类实现一个接口:
public interface ICardTarget
{
public bool IsValidTarget(Card targetingCard);
}
类似地,许多不同的游戏对象可以打牌:玩家角色、敌人、障碍物等等。对于每个可以使用牌的对象,我让它的类实现一个接口:
public interface ICardUser
{
//I don't have anything in here, this is really more of just a tag to group together any card users. Am I using interfaces right?
}
因此我的场景中的某些对象可能是:
public class Enemy : ICardTarget, ICardUser
{
public bool IsValidTarget(Card targetingCard) {/*...*/}
public string Species {get;set;}
}
public class PlayerCharacter : ICardTarget, ICardUser
{
public bool IsValidTarget(Card targetingCard) {/*...*/}
public float AttackSpeed {get;set;}
public int Health {get;set;}
}
public class Weather : ICardTarget
{
public bool IsValidTarget(Card targetingCard) {/*...*/}
public bool IsCloudy {get;set;}
}
public class Boulder: ICardUser
{
public int Mass {get;set;}
}
ETC。
每张卡牌都定义了哪些类型的目标有效。当玩家(或任何卡牌用户)选择一个对象作为卡牌的目标时,卡牌会将自身传递给 IsValidTarget 函数并接收布尔响应,以判断这是否是该卡牌的有效目标。
public class Card
{
private ICardUser _user; //reference to this card's user, set somewhere else
private ICardTarget _target; //reference to this card's target, set somewhere else
public void CheckTarget()
{
if (_target.IsValidTarget(this))
{
PerformCardEffect();
}
}
private void PerformCardEffect() {/*whatever the card does*/}
}
到目前为止一切顺利!现在卡牌需要对目标对象产生效果,并且还可能对卡牌使用者产生影响。
目前,卡牌对该目标对象唯一知道的是,它是一个有效目标(毕竟,ICardTarget 接口保证了这一切)。那么,我该如何执行 取决于目标类型的 ,而无需检查类型和向下转型?同样的问题也适用于卡牌用户:我只知道卡牌来自卡牌用户,我该如何与它交互而不进行向下转型?或者,向下转型并不是我认为的恶魔?
我并不担心它,并在运行 PerformCardEffect() 时将目标/用户向下转换为实现它的类之一:
public class Card
{
private ICardUser _user;
private ITarget _target;
public PerformCardEffect()
{
if (_target is Weather w)
{
w.IsCloudy = true;
}
if (_target is Enemy e)
{
print(e.Species);
}
if (_target is PlayerCharacter p)
{
p.AttackSpeed *= 2;
}
if (_user is PlayerCharacter p)
{
p.Health -= 3;
}
if (_user is Enemy e)
{
e.Health -= 5;
}
//etc.
}
}
对于我来说,这是目前最容易进行迭代的,但我 知道 这是不受欢迎的。
我修改了 ICardTarget/ICardUser,以便调用正确函数的责任从 Card 转移到它们身上:
public interface ICardTarget
{
//...
public void SelectCardEffectTarget(Card targetingCard);
//...
}
public interface ICardUser
{
public void SelectCardEffectUser(Card targetingCard);
}
public class Enemy : ICardTarget, ICardUser
{
//...
public void SelectCardEffectTarget(Card targetingCard)
{
targetingCard.PerformCardEffectTarget(this);
}
public void SelectCardEffectUser(Card targetingCard)
{
targetingCard.PerformCardEffectUser(this);
}
//...
}
public class PlayerCharacter : ICardTarget, ICardUser
{
//...
public void SelectCardEffectTarget(Card targetingCard)
{
targetingCard.PerformCardEffectTarget(this);
}
public void SelectCardEffectUser(Card targetingCard)
{
targetingCard.PerformCardEffectUser(this);
}
//...
}
public class Weather : ICardTarget
{
//...
public void SelectCardEffectTarget(Card targetingCard)
{
targetingCard.PerformCardEffectTarget(this);
}
//...
}
public class Card
{
private ICardUser _user;
private ITarget _target;
public void CheckTarget()
{
if (_target.IsValidTarget(this))
{
_target.SelectCardEffectTarget(this);
_user.SelectCardEffectUser(this);
}
}
public void PerformCardEffectTarget(Weather w)
{
w.IsCloudy = true;
}
public void PerformCardEffectTarget(Enemy e)
{
print(e.Species);
}
public void PerformCardEffectTarget(PlayerCharacter p)
{
p.AttackSpeed *= 2;
}
public void PerformCardEffectUser(Enemy e)
{
e.Health -= 5;
}
public void PerformCardEffectUser(PlayerCharacter p)
{
p.Health -= 3;
}
//I have to include these calls so that any objects not caught by the above overloaded parameters default to doing nothing.
public void PerformCardEffectTarget(ICardTarget t) {}
public void PerformCardEffectUser(ICardUser u) {}
}
这似乎更好,但需要来回传递大量引用,这不是坏事,但对我来说感觉有点过分。我还必须在 Card 和接口上公开许多方法。
PS 有没有更简洁的编写 SelectCardEffectTarget()/SelectCardEffectUser() 的方法,这样我就不必在每个子类中重复相同的代码块了?我知道我可以将 ICardTarget/ICardUser 变成一个类,并在那里设置函数,这样它就可以被继承,但这似乎不是适合这种情况的层次结构。
我试图利用通用类来指定目标/用户类型,但我无法找到一种方法来包含它并从中获取有用的功能。
public class CardEffectDetails<T,U> where T : ICardTarget where U : ICardUser
{
T Target {get;set;}
U User {get;set;}
}
public class Card
{
private ICardTarget _target;
private ICardUser _user;
private void CreateEffectDetails()
{
CardEffectDetails<_target.GetType(), _user.GetType()> effectDetails = new();
//what can I even do with this thing?
}
}