zoukankan      html  css  js  c++  java
  • Unity5 官方教程笔记(2D Rogue Like)03 —— Moving Object

    除了特殊类型的游戏(比如某些GalGame等)以外,都要有可以由玩家或者AI控制进行移动的单位。在本例中,便是玩家(Player)和敌方单位(Enemy)。这些单位本身在游戏的进行过程中,会触发一些事件,因此如果将这些单位单独抽象出来,将可以在比较统一的地方对这些事件以及涉及到的数值进行管理。

    无论是Player还是Enemy,他们都有一些共同点,比如:他们都会动(废话)、他们都有可能在移动过程中遭遇到阻挡(还是废话)等等。由于在这个层面上他们的共同点更多的表现在移动的方面,所以我们可以为其创建一个共同的基类用来继承,在这里给它起名叫“MovingObject”。

    惯例,还是先看一下代码的基础结构:

     

    可以看到这个类的功能很简单:

    1. 尝试移动
    2. 为了使移动不那么突兀而播放一个过渡效果
    3. 若不能移动则触发不能移动的事件
    4. 为不能移动的事件留下一个接口交给子类实现(由于Player和Enemy在尝试移动失败后的处理方式是不一样的,所以需要交给它们自己按照需求去实现)

    Move()方法:

     

    这个方法主要是判断在移动方向是否有其它碰撞体,如果是则返回不能移动、如果不是则播放移动的动画。

    需要注意的是这里使用了Linecast来检测碰撞。这种方式是通过在起点和终点间拉一条线,判断在这条线上是否有碰撞体,如果有则判定为会发生碰撞,没有则相反。因为无论是Enemy也好Player也好,都拥有自己的碰撞体,如果因为自己的碰撞体被判断为碰撞的话肯定不是我们想要的结果,所以在判断之前要先把自己的碰撞体禁用,判断之后再重新启用即可。同时由于每个单位的行动是顺序进行的,因此你不用担心在自己的碰撞体被禁用的时候别的物体撞了过来。

    碰撞的判断信息最终会被存放在RaycastHit2D类型的数据结构里,不过在这里我们只需要判断碰撞是否会发生,因此只需要判断碰撞是否为null即可。

    由于RaycastHit2D是一个值类型的结构体,因此为了把碰撞结果传递给外层方法,在这里需要使用out关键字,这样既可以保证传递了引用,也可以使得数据不会受到外层方法数据的污染(好像是这样的)。

    SmoothMovement()方法是用来使得移动更自然,也就是播放一段动画:

     

    使用的依旧是“协程”这种方式来实现,可以注意到这里面返回值是yield return null,也就意味着将会无条件执行下面的部分,但是这并不会导致这句话像没有写一样,因为只有每一次刷新的时候才会继续执行下面的部分(好像是这样)

    AttemptMove <T>()方法中:

     

    首先执行了Move()方法来判断是否可以移动,若可以移动的情况下则直接退出方法,若发生了碰撞,则需要判断和什么东西发生了碰撞。由于可能和很多种物体发生碰撞比如:内墙,围墙,玩家敌方单位、食物、出口等,因此需要将需要判断发生碰撞的物体的类型通过泛型T传递进方法之后,执行OnCantMove所对应的方法再处理对应的逻辑。

    以上就是MovingObject的内容,接下来将会对Enemy和Player进行分开讲解,借此了解不同的物体对同样的事件会如何进行不同的处理。

  • 相关阅读:
    OSI模型白话
    并发
    初始化与清理
    多线程
    recyclerview Adapter
    recyclerview刷新
    surfaceview
    viewgroup绘制流程
    view配置
    项目遇到的问题
  • 原文地址:https://www.cnblogs.com/nmsuper86/p/5610323.html
Copyright © 2011-2022 走看看