Unity学习流水账-2-新手教程-横版卷轴动作游戏场景

由于我自身知识的局限,下面Object有可能被称为对象有可能被称为物体,其实都是指的Game Object。

认识基本界面

工具栏, 提供手形工具克控制按钮,如播放暂停等。
scene 场景,应该相当于story board,是集中所有元素的地方。
hierarchy 当前场景下所有物体的堆栈,包括播放器,UI,摄像头,玩家,背景纹理等等
assets 所有资源的管理器,包括纹理,bgm等等
game 游戏预览,通过工具栏的播放按钮,可以在这里
游戏中所有对象都是Game Object,它的表现通过Properties来定义, Inspector窗口可以查看选中对象的所有组件Component, 以及每个组件的属性

项目基本概念

游戏是由一个一个的"场景"组成的。组成场景的基本单位是Game Object,它可以有多个Component,每个Component拥有自己的属性。Game Object可以被存储在Asset里,以在多个地方复用。Prefab就是这样一类物体,它是预制的建筑材料。在Asset里定义的Prefab相当于类文件,而在Hierarchy里的东西相当于类实例,我们可以从Asset里拖动物体到Hierarchy中,这叫做实例化(initiate/clone)。
在示例工程里,从Assets进到PlatformerTemplate文件夹,里面有个Prefabs文件夹,预定义了一套物体,包括砖块平台,按钮等,通过组合这些物体,可以构造出我们的环境场景。

构造好场景,物体,交互之后,需要将游戏导出成可执行文件,以便在Unity以外运行,导出时可选择运行平台,有PC,Android,PS4,XBox等等可选。

试玩

导出了demo工程进行试玩,手感太差了,主要有三个问题:

  1. 贴墙跳和挨着物体跳的判定很难受,无法跳到上方的下个块,会被判定碰撞。在高台边缘也有这种情况,会被判定下落
  2. 开头的隐藏路径是死路,没有任何奖励,这不合理
  3. 要是有加速跑和二段跳就好了
  4. (说好的三个问题呢?)有一个地方浮空砖块的右边块错用成了中间砖块的贴图

下面我们就拿着新手村Lv.1的木剑(+百度buff),试着搞定以上三(si)个问题。

1. 贴墙跳受阻:砖块碰撞判定

猜测挨着砖块边缘跳不起来是因为被判定为碰撞了。查看player属性,发现player就是将一个Controller与动作贴图,实体模型,动作音效,结合在一起组成的物体(顺手改了一下生命值,加速度和最大速度,跳跃的初始速度和重力加速度决定了跳跃的高度,横向速度决定了跳跃距离)。
贴墙跳会顶住砖块而卡住跳不高,是不是因为跟墙壁有摩擦导致上升速度降为0?那我们可不可以当人物跳起来时,墙的边缘摩擦变为0,这样就不卡了。那么一是判断人物跳跃,二是更改摩擦。(网上搜了一下,发现示例的Assets里有代码)找到Assets的Scripts,找到PlayerController,里面有个跳跃状态机,可以看到将跳跃以状态模式进行管理,那么判断人物跳跃只要看其状态即可。我们需要在跳跃时和落地时修改摩擦。新建两个PhysicsMaterial2D材质,分别赋值摩擦系数为0和0.4, 注意属性friction是浮点型,需要在数值后面加F。然后找到Player的碰撞体collider,把他的sharedMaterial赋值为我们创建的材质即可。
打开Unity编辑器,Window->General>Console可以调出控制台窗口,代码里打的Log(Debug.Log)可以在这里看到。
实际上修改了摩擦系数后,现象仍然存在,说明不是摩擦系数的缘故(假设我实现正确)。猜测应该是跳起后碰到墙面时判断为碰撞,将向上运动的速度直接置为了0,那么我们找找看哪里控制上升速度。然后我在KinematicObject里面找到了这段代码:

...
                  else
                    {
                        //We are airborne, but hit something, so cancel vertical up and horizontal velocity.
                        velocity.x *= 0;
                        velocity.y = Mathf.Min(velocity.y, 0);
                    }
...

显然,我们去掉这段就可以了。实际上我们只需要碰墙壁的时候继续保持纵向移动,所以只需要去掉第二行。经测试已经能达到目的了,但是天花板磕脑袋的效果也消失了,显然是因为我们没有判断碰到的是墙壁还是天花板。暂时还不知道怎么区分天花板和墙壁,这个问题就这样吧。

2. 隐藏要素设计不合理

这个比较简单,设置一个弹簧装置和通道,让角色可以弹上出生地。通道其实是背景+物体,可以仿照场景中的隐藏通道来做,也可以直接显示背景。
事实上一条隐藏的死路很有可能就是设计意图,并不是不合理。

3. 加速跑和二段跳

加速跑的关键是按住某个加速按键后,横向速度增加一个随时间衰减的加速度。假设我们以Shift键为加速键,那么我们仿照Jump键的判断,就可以判断Shift键。这里需要做两件事:新增加速按键的定义,以及当加速按下和松开时的逻辑。我们查看Edit->Project Setting->Input,发现预定义的按键已经够用了,left shift按键绑定的名称为Fire3,不需要新增。如果要新增,在Input界面新增按键配置。

// 本段代码未经验证
                if (Input.GetButtonDown("Fire3")) {// this is accelerate key
                    if (!isAcce && acce == 0) {
                        acce = 50;
                        isAcce = true;
                    }
                    velocity.x += acce * 0.001F;
                    acce -= 1;
                } else if (Input.GetButtonUp("Fire3")){
                    acce = 0;
                    isAcce = false;
                }

二段跳的关键是判断身处空中以及是否已经进行过二段跳,我们用一个计数器来解决。修改了两处地方,一处是跳跃状态判断, 当空中再次按跳跃键时判断是否满足二段跳条件。另一处是纵向速度计算的条件,当二段跳时无论处于什么速度,再给一个纵向速度。目标完成,代码片段如下:


        public bool CanJump() {
            return jumpState == JumpState.Grounded || 
            jumpState != JumpState.Grounded && jumpCount < 2;
        }

        protected override void Update() {
        ...
                if (CanJump() && Input.GetButtonDown("Jump")) {
                    jumpState = JumpState.PrepareToJump;
                }
        ...
        }

        void UpdateJumpState()
        {
            jump = false;
            switch (jumpState)
            {
                ...
                case JumpState.Jumping:
                    if (!IsGrounded)
                    {
                        Schedule().player = this;
                        collider.sharedMaterial = p1;
                        jumpState = JumpState.InFlight;
                        jumpCount += 1;
                    }
                    break;
                    ...
                case JumpState.Landed:
                    jumpState = JumpState.Grounded;
                    jumpCount = 0;
                    break;
            }
        }

        protected override void ComputeVelocity()
        {
            if (jump && (IsGrounded || CanJump()))
            {
                velocity.y = jumpTakeOffSpeed * model.jumpModifier;
                jump = false;
            }
            ...
        }
  1. 背景/前景贴图错误
    怎么修改现有的背景贴图还没搞明白(Hierarchy里点击Level它不会显示单独的一块砖的属性,在Assets里看了半天,也试着将Assets里的RightTile拖到Scene中但没有效果),这个跟前面区分天花板,墙壁和地面的问题一起留待后续理解。

上面几个问题搞了接近5个小时, 效果还算满意(也遗留了很多疑问,例如地面判断,斜坡/跳台/异形障碍物时如何判断,弹簧效果/阻尼效果如何实现,不过暂时无法解答),就到此为止吧,明天学习下一个官方示例,查看Unity的API文档,顺便回顾一下C#的基本语法。

你可能感兴趣的:(Unity学习流水账-2-新手教程-横版卷轴动作游戏场景)