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

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

作者: hjhjw1991 | 来源:发表于2019-07-15 19:34 被阅读0次

    由于我自身知识的局限,下面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<PlayerJumped>().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-新手教程-横版卷轴动作游戏场景

          本文链接:https://www.haomeiwen.com/subject/lhnwkctx.html