关于面向对象封装的问题,求助求助,逻辑有点乱


我现在需要在游戏里即时显示如下信息:
等级,经验,杀敌,总输出,总承受伤害,数据已全部显示出来了。
我是把这些全封装到一个即时显示类里(字段,属性,方法,不继承MONO),然后写一个全局单例模式的脚本,每个需要记录数据的地方就调用一次类里的方法。
这样就实现即时显示了, 但是我还需要根据主角等级升级时各项属性的提升(比如攻击力,防御力等),那这些属性我又应该写在哪里了?
我现在是和即时显示类放一块了,但是还没使用,因为我有点郁闷, 而且这些属性是需要进行保存的,这样下次再开游戏的时候就可以继续原来的进度了,即时显示类的信息我也想保存, 又应该保存到哪里呢?
现在卡在这里了, 请问我该怎么解决呢? 先谢谢各位前辈~!
已邀请:

boboshaw - 放荡不羁爱萝莉

赞同来自: hnlyfy 君莫笑 admin 崇慕 zhaoxk88 mertenlin a8546820更多 »


我是这样做的 希望能够对你有帮助,我分为实体和属性类,UI完全基于事件。实体负责逻辑处理以及事件派发,属性类就只包含属性。

public class Property
{
public int level;
public int hp;
public int maxHP;
.....
}

属性独立分出来的好处是方便保存,简单的到在C#中我只需要序列化和反序列化。

public class GameEntity
{
public Property property { get;private set;}//属性只读
public GameEnity( Propery property )
{
this.property = property;
}
public EventHandler PropertyChanged;//定义一个属性改变事件
public void InvokePropertyChanged( )//派发属性改变事件
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke( this, EventArgs.Empty );
}
}
//某件事情导致了角色升级
protected virtual void OnLevelUp()
{
//升级属性变化
property.level = property.level + 1;
property.maxHP = XXXX; //血量上限提升,这依据你的策划公式
property.hp = property.maxHP;
.....
InvokePropertyChanged();//派发事件
}
}


你的主角就是GameEntity的实例,一般放在一个单例的Game类里面,Game这个类作为一个负责资源加载初始等等操作,主角的创建也放在这里。

public calss Game
{
private static Game _instance;
public static Game instance
{
get
{
return _instance;
}
}
GameEntity _mainPlayer;
public void CreateMainRole()
{
//创建主角的操作,我在这里简单的实例化它
Property property = XXX;// 通过存档数据获取
_mainPlayer = new GameEntity( initProperty );
}
public Character mainPlayer { get { return _mainPlayer;} }
}


显示数据,也就是一些UI逻辑。假如你的UI脚本是MonoBehaviour的话,你可以这样做

UILabel _lblLevel; //等级
void Start()
{
UILabel _lblLevel = 获取显示等级的UILabel;
// 监听角色属性变更事件
Game.instance.mainPlayer.PropertyChanged -= OnPropertyChanged;
Game.instance.mainPlayer.PropertyChanged += OnPropertyChanged;
}
//角色属性变更事件监听函数
private void OnPropertyChanged( object send, EventArgs args )
{
//控制UI变化,比如说
_lblLevel.Text = Game.instance.mainPlayer.property.level;
.....
}

再加上合理的利用封装,继承,多态,设计模式一般的项目足以。

说一下我的想法,不知能否提供一种思路。

你的问题在于将实体属性与逻辑操作混起来了,一个类的用处应该尽量唯一,这样在以后做出变动时,变化会对当前类和其他类带来的影响尽可能缩小。

针对你的具体问题,我认为可以将角色的所有属性,写在一个类中(比如攻击力,防御里,血量),并且提供统一的对外接口(C#中请尽量都使用属性来实现,不要修改字段的访问权限为public,以便以后可以在属性中增加一些相关逻辑而不影响之前的代码,比如你可能需要在 设置 血量的属性里面,加上一段逻辑,用于检查当前血量是否为0, 为0就发送消息或者触发事件等等,这段逻辑也许你刚开始编写代码并没有想到,写成属性可以方便的增加而不改变原有逻辑)。那么现在,游戏中的所有有属性的角色都可以使用该类来保存其中的属性。

不过这个保存是临时的,我们还需要一个类来提供数据持久化的功能,用于保存和读取这写属性。比如该类提供一个Save方法,接受上述的属性类型对象作为参数,将它保存在本地,也提供一个Load方法读取数据。

现在属性解决了,当角色升级,你当然可以在一大片方法中,加上一段代码来增加攻击力,增加防御里,计算当前经验,计算下级经验,等等,可是这样的代码很难维护,以后规则变了 你得在大片代码中找到这一句真的很难,也容易出错。这时候,得考虑一个类,功能就是专门用于控制角色的属性,比如,其中有一个LevelUp方法调用后就会根据自己定义的规则来提升角色的所有能力,比如,有一个Buff方法,传递一个Buff,可以为角色增加Buff属性,等等,这就是 门面模式,通过一个统一的入口用来管理一系列相关逻辑,而不需要每次自己都自己依次调用。
这写都是我临时想的,真正开发过程中也许并不如上述这么简单,但是原则类似。

愿有助于你。--无言

Vital

赞同来自: admin 崇慕


我觉得你的问题在于数据如何保存吧!

你可以用Unity自带的PlayerPrefs游戏存档API。
如果不喜欢的话可以自己写XML或者MYSQL存储!

至于对象封装,这个要自己去领悟了,看看设计模式吧,应该对你有帮助的!

zhang247124629 - 专注于移动互联网的开发,坚信移动技术可以改变我们的生活方式。

赞同来自: zhang247124628 zhang527405132


楼上的回复好多哟。写得内容也好多哟。

如果是我让来设计这个东东,我说下我个人的看法。
搞一个Hero类即可。所有的属性,所有的行为。全部放在这个方法里。

存储数据和加载数据的方法也在此类定义一下。

这样我个人感觉是特别清楚的。也容于维护。

上面的回复我看好多使用设计模式进行去搞,我感觉有点儿复杂了。因为上层的业务是经常改变的。不容易于维护及修改的。。。

君莫笑

赞同来自: admin


我现在是升级属性提升也挂在即时显示类里了 好郁闷 这个实例化一次所有属性都得重置, 只能从那里继承。。

海洋

赞同来自: 崇慕


升级属性逻辑可以单独拿出来处理,专门用于与服务器通信使用。

csh305244459

赞同来自:


1.可以定义一个枚举,用来保存经验,战力等等;
public enum Propertys
{
EXP = 1,
HP = 2
}

然后玩家身上携带一个静态Dictionary用来保存所有的属性值。另外,也不用每一处都计算这些属性,可以由服务器发送这些值。前端只要做保存就可以了。

要回复问题请先登录注册