unity3D游戏开发实战(四)——使用道具与密码锁

改进

对话代码

之前的对白显示代码有一点小问题,需要稍作修改。

        if (Time.time - instantiateTime >= continueTime && !spanning)
            disappearing = true;

如图所示,之前是没有spanning的判定条件的,这会导致脚本不断把disappear值设为真,导致后续对话无法显示。

鼠标指针

在游戏中,我们用准星来代替鼠标指针,所以我们需要隐藏指针并将其锁定,在角色移动代码的Start函数中加入如下两行代码:

        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;

当然,为了方便测试,我们在测试过程中会暂时将这两行代码注释掉。

获得当前道具

有时我们需要获得当前道具编号,但是getItem函数存在一种特殊情况——当前没有任何道具,按照我们之前编写的代码,会造成indexOut类型的error,所以我们要稍加修改:

    public int GetItem()
    {
        if (items.Count == 0)
            return 0;
        return items[num];
    }

完成喷泉房间

置物架

上一次我们已经编写好了交互物体的脚本,这次我们直接将脚本拖动到需要互动的物体上即可。
首先是置物架,我们将脚本添加后修改参数如下:
在这里插入图片描述
值得注意的是,由于shelf本身是一个用来容纳各个组件的空物体,所以我们要手动添加Collider,才能让它被Raycast检测到,同时要修改其tag为Untouched。
之后我们要为架子上的部分物体添加玻璃材质,新建material,设置参数如下:
在这里插入图片描述
注意,一定要修改渲染模式为Fade,不然无法实现透明效果。
将材质赋予架子上的部分物体后,我们进入游戏检查一下:
在这里插入图片描述
我们如愿以偿得到了道具,点亮了灯光,并让特殊的玻璃杯消失,也出现了对白,置物架的实例摆放宣告成功。

喷泉

话不多说,先放上参数图:
在这里插入图片描述
如图,交互后出现的三个灯光分别是喷泉的有阴影灯光,无阴影灯光,以及隔壁房间保险柜的照明灯光。
另外因为喷泉下子物体的collider会影响射线检测,所以我们需要将子物体的collider移动到spring物体下。
喷泉灯光效果如下:
在这里插入图片描述
之后我们进入游戏看一看实际效果:
在这里插入图片描述
在这里插入图片描述
实际效果很成功,但是我们会发现一个问题——道具栏中的道具只有一个时,没有自动填充满,我们需要稍作修改。

道具添加代码修改

打开Item脚本的AddItem函数部分,修改部分代码如下:

if (items.Count == 1)
        {
            itemNowImg.sprite = img;
            itemNextImg.sprite = img;
            itemPrevImg.sprite = img;
        }

这样道具个数变成一个时,就会填充满道具栏图标了。

密码解锁获得道具

用UI来实现输入密码

我们的保险柜为密码锁,所以我们需要实现密码解锁保险柜获得钥匙的功能,然而只使用我们之前所编写的Contact脚本无法完成这个功能,需要专门为它编写新的脚本。
首先我们还是把脚本添加给保险柜,但是由于我们点击保险柜不会得到任何道具,所以选择类型4,也不会有对话产生,我们唯一需要让交互做的就是生成UI界面。
因此我们需要制作一张新的画布命名为Password,将其拖动到保险柜的ShowObject数组下,剩下的就是设置好UI界面后编写脚本了!

设置UI界面

关于UI界面,我想要做出四个拨盘的密码锁效果,图片如下:
在这里插入图片描述

密码锁代码

图中有几个需要实现的功能,我将一一列举出来并附上代码。
首先是挂载在canvas画布上的脚本需要声明的变量:

[Header("Manu")]
    public GameObject character;
    public GameObject item;
    public GameObject itemBox;
    public GameObject dialogPrefeb;
    [Header("ChangeBtnArea")]
    public GameObject[] textObjNows;
    public GameObject[] textObjNews;
    public Transform[] up;
    public Transform[] middle;
    public Transform[] down;
    [Header("SureBtnArea")]
    public string password;
    public Text wrongMsg;

    private Text textNow;
    private Text textNew;
    private NumberMove moveNow;
    private NumberMove moveNew;
    private MoveController moveController;
    private bool ifShowing = false;

其中ChangeBtnArea部分是利用提前放置好的位置用Lerp移动数字来实现数字拨盘滚动效果,我们还需要在数字Text对象上编写一个移动脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NumberMove : MonoBehaviour
{
    [HideInInspector] public Transform targetPos;
    [HideInInspector] public bool ifMoving = false;

    private float moveSpeed = 0.05f;

    void Update()
    {
        if (ifMoving)
        {
            transform.position = Vector3.Lerp(transform.position, targetPos.position, moveSpeed);
            if (Vector3.Distance(transform.position, targetPos.position) < 0.05f)
                ifMoving = false;
        }

    }
}

将这个脚本挂载之后,我们只需要修改targetPos和ifMoving就可以控制数字移动了,之后向上翻与向下翻的代码如下:

 public void PageUp(int btnOrder)
    {
        GameObject objNow = textObjNows[btnOrder];
        GameObject objNew = textObjNews[btnOrder];
        textNow = objNow.GetComponent<Text>();
        textNew = objNew.GetComponent<Text>();
        moveNow = objNow.GetComponent<NumberMove>();
        moveNew = objNew.GetComponent<NumberMove>();

        textNew.text = ((int.Parse(textNow.text) + 1) % 10).ToString();

        objNew.transform.position = down[btnOrder].position;
        moveNow.targetPos = up[btnOrder];
        moveNew.targetPos = middle[btnOrder];
        moveNow.ifMoving = true;
        moveNew.ifMoving = true;
        RollNum(btnOrder);
    }

    public void PageDown(int btnOrder)
    {
        GameObject objNow = textObjNows[btnOrder];
        GameObject objNew = textObjNews[btnOrder];
        textNow = objNow.GetComponent<Text>();
        textNew = objNew.GetComponent<Text>();
        moveNow = objNow.GetComponent<NumberMove>();
        moveNew = objNew.GetComponent<NumberMove>();

        textNew.text = ((int.Parse(textNow.text) + 9) % 10).ToString();

        objNew.transform.position = up[btnOrder].position;
        moveNow.targetPos = down[btnOrder];
        moveNew.targetPos = middle[btnOrder];
        moveNow.ifMoving = true;
        moveNew.ifMoving = true;
        RollNum(btnOrder);
    }
        private void RollNum(int btnOrder)
    {
        GameObject tmpObj;
        tmpObj = textObjNows[btnOrder];
        textObjNows[btnOrder] = textObjNews[btnOrder];
        textObjNews[btnOrder] = tmpObj;
    }

遮罩与按钮响应挂载

首先,数字不能显示在仪表盘之外的地方,所以需要做一个遮罩层,而制作方法也很简单,先将数字设为遮罩图片的子物体,再为遮罩添加Mask组件,如下图:
请添加图片描述
请添加图片描述
而按钮响应则需要将挂载了脚本的canvas画布拖给按钮的Onclick列表,再选择刚刚编写的脚本中的对应点击触发函数:
在这里插入图片描述

返回与输入密码

因为玩家不一定能正确输入密码,所以我们还要给玩家退出按钮,也要对输入的密码作出相应,其脚本分别如下:

    public void ExitBtn()
    {
        moveController.enabled = true;
        itemBox.tag = "Untouched";
        wrongMsg.color = new Color(1, 0, 0, 0);
        dialogPrefeb.SendMessage("ShowDialog", "看上去你遇到了一些麻烦,为什么不看看置物架呢?");
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
        ifShowing = true;
        gameObject.SetActive(false);
    }

在退出时要复原玩家的移动脚本,并重新锁定光标。

    public void SureBtn()
    {
        string inputPass = "";
        foreach (GameObject textObj in textObjNows)
            inputPass += textObj.GetComponent<Text>().text;
        if (inputPass.Equals(password))
        {
            item.GetComponent<Item>().AddItem(3);
            moveController.enabled = true;
            dialogPrefeb.SendMessage("ShowDialog", "哦!一把钥匙,你一定在想,保险柜用来装钥匙也真是太滑稽了。");
            Cursor.visible = false;
            Cursor.lockState = CursorLockMode.Locked;
            gameObject.SetActive(false);
        }
        else
        {
            wrongMsg.color = new Color(1, 0, 0, 1);
        }
    }

首先获取密码,之后进行比对,如果一致则不再重设保险箱的tag,防止第二次接触,并进行一系列响应。
如果不对,除了显示“密码错误!”的信息外不做任何处理。
每次打开密码锁都要锁定视角和打开鼠标,因此我们在脚本上添加如下代码:

    private void Start()
    {
        moveController = character.GetComponent<MoveController>();
    }

    private void Update()
    {
        if (ifShowing)
        {
            Cursor.visible = true;
            Cursor.lockState = CursorLockMode.None;
            moveController.enabled = false;
            ifShowing = false;
        }
    }

之后我们来实际进入游戏看看效果。
在这里插入图片描述
在这里插入图片描述
一切正常,下一次我们就可以开始最后的制作了!

  • 6
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值