Unity制作游戏自定义按键详解

目录
  • 一、效果图
  • 二、布局
    • 1.场景布局
    • 2.设置面板布局
  • 三、脚本思路
    • 1.KeyItem脚本
    • 2.SetKeyPanle脚本
    • 3.player移动脚本

一、效果图

二、布局

1.场景布局

创建一个Panel 创建三个cube,Panel地板 两个cube设置一个绿色材质,调整Scale大小让其成为柱子形状,一个cube改名为player设置一个红色材质,当作玩家(用来演示操作的),修改相机位置就可以了。

2.设置面板布局

2.1新建一个空节点名字改为SetKeyPanle,修改属性

2.2在SetKeyPanle下新建一个image,修改名字为root,调整大小,如下图

2.3 在root下 新建Text ,修改名为Title当作标题

2.4在root下新建Scroll View组件修改属性

2.5 选择Scroll View—>Viewport—>Content对象,添加Grid Layout Group组件并修改属性

2.6 在上一步的Content下创建一个按钮改名Item,然后在这个Item下在创建两个Text,修改Item的Button组件属性

两个Text自己修改一下位置就好了,注意两个Text在父物体的孩子子级不要搞错了,第一个Text是前进,第二个是W

弄好后在吧item复制3个,有了Content的Grid Layout Group组件新建的item就不用布局了,他自动给你排列了

三、脚本思路

我们需要一个移动脚本(Player)、按键数据脚本(KeyItem)和设置面板脚本(SetKeyPanle),KeyItem脚本主要用于存储按键信息和触发修改 具体修改功能在SetKeyPanle脚本中

1.KeyItem脚本

3.1.1 获取组件 和 设置初始化按键

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

public class KeyItem : MonoBehaviour
{
    Text key;       //按下的按键名称
    Button btn;     //开启按钮

    [SerializeField] KeyCode keyCode;//初始化按键 需要在面板自己选择

    void Start()
    {
        //获取组件
        key = transform.GetChild(1).GetComponent<Text>();//这里我用了子物体的孩子子级来获取
        btn = GetComponent<Button>();//按钮就获取他自己本身

    }

}

将这个脚本赋值给item对象,我们在面板中设置他的初始化按键

3.1.2添加修改key值、修改按钮颜色、更新失败还原按键名称 方法

 //修改key值
    void SetKeyItemValue()
    {
        //当前有修改的key值
        if (SetKeyPanle.GetIntance().CurrentKeyItem!=null)
        {
            return;
        }

        //当前keyitem为空时,就让它等于自己
        SetKeyPanle.GetIntance().CurrentKeyItem = this; //这个要从SetKeyPanle脚本获取,是下面要讲的

        //当前状态改为true 这样就可以修改按键了
        SetKeyPanle.GetIntance().IsSet = true; //可修改  //这个要从SetKeyPanle脚本获取,是下面要讲的
        SetBtnColor(new Color32(202, 138, 138, 255));//修改按钮颜色
        key.text = "";//修改的时候text值为空
    }

    //修改按钮颜色
    public void SetBtnColor(Color32 color)
    {
        btn.image.color = color; //修改颜色
    }

    //更新失败还原按键名称
    public void Restore()
    {
        key.text = keyCode.ToString();
    }

3.1.3最终代码

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

public class KeyItem : MonoBehaviour
{
    Text key;       //按下的按键名称
    Button btn;     //开启按钮

    [SerializeField] KeyCode keyCode;

    public KeyCode KeyCode { get { return keyCode; }
        set {
            keyCode = value; //修改按键值
            key.text = keyCode.ToString(); //修改按键面板要显示的Text值
        } }

    void Start()
    {
        key = transform.GetChild(1).GetComponent<Text>();
        btn = GetComponent<Button>();

        btn.onClick.AddListener(SetKeyItemValue);

    }

   //修改key值
    void SetKeyItemValue()
    {
        //当前有修改的key值
        if (SetKeyPanle.GetIntance().CurrentKeyItem!=null)
        {
            return;
        }

        //当前keyitem为空时,就让它等于自己
        SetKeyPanle.GetIntance().CurrentKeyItem = this; //这个要从SetKeyPanle脚本获取,是下面要讲的

        //当前状态改为true 这样就可以修改按键了
        SetKeyPanle.GetIntance().IsSet = true; //可修改  //这个要从SetKeyPanle脚本获取,是下面要讲的
        SetBtnColor(new Color32(202, 138, 138, 255));//修改按钮颜色
        key.text = "";//修改的时候text值为空
    }

    //修改按钮颜色
    public void SetBtnColor(Color32 color)
    {
        btn.image.color = color; //修改颜色
    }

    //更新失败还原按键名称
    public void Restore()
    {
        key.text = keyCode.ToString();
    }

}

上面有几个报错的句子先不管,写完SetKeyPanle脚本的对应方法就没错了。

2.SetKeyPanle脚本

这个脚本稍微复杂,因为逻辑处理都在这里。脚本中有详细解释

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

//序列化按键节点
[Serializable]
public class KeyItemNode
{
    public string keyName;//按键功能名称
    public KeyItem keyItem; //按键item
}

public class SetKeyPanle : MonoBehaviour
{
    KeyItem currentkeyItem=null; //当前要修改的Item
    //封装 用于判定当前是否有修改的按钮 没有为空
    public KeyItem CurrentKeyItem { get => currentkeyItem; set => currentkeyItem = value; }

    [SerializeField] List<KeyItemNode> keyItemList; //这个需要到面板赋值

    Dictionary<string, KeyItem> keyItemDic; //字典存放 键值参数 (玩家移动要用,玩家脚本后面写)
    public Dictionary<string, KeyItem> KeyItemDic { get => keyItemDic; set => keyItemDic = value; } //封装可以进行外部调用

    [SerializeField] Transform root; //面板节点 用于控制开启关闭面板  是上面创建设置面板UI SetKeyPanle下的root

    //单例 这样就可以获取这个脚本的方法进行使用了
    static SetKeyPanle intance;
    public static SetKeyPanle GetIntance()
    {
        return intance;
    }

    void Awake()
    {
        intance = this; //将自己赋值给intance
    }

    void Start()
    {
        keyItemDic = new Dictionary<string, KeyItem>();//初始化字典

        //将存储的按键值 添加到字典中
        for (int i = 0; i < keyItemList.Count; i++)
        {
            keyItemDic.Add(keyItemList[i].keyName, keyItemList[i].keyItem);
        }

        ClosePanel(); //关闭设置面板
    }

    bool isCurrentOpenState = true; //当前设置面板开启的状态 true 代表开启状态
    public bool IsCurrentOpenState { get => isCurrentOpenState; set => isCurrentOpenState = value; } //封装可以进行外部调用

    void Update()
    {
        //按下esc键开启关闭设置面板
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            //判断面板的开启状态
            if (isCurrentOpenState)
            {
                OpenPanel(); //开启面板
            }
            else
            {
                //判断当前是修改状态,但是你没有按下按键修改而是直接esc退出时,恢复上一次按键
                if (isSet)
                {
                    //关闭后恢复当前修改键值
                    CurrentKeyItem.Restore();
                }

                ClosePanel();//关闭面板
            }

            isCurrentOpenState = !isCurrentOpenState;
        }

    }

    #region 按键修改

    bool isSet = false; //是否可以修改
     public bool IsSet { get => isSet; set => isSet = value; }

    void OnGUI()
    {
        //可以修改
        if (isSet)
        {
            Event e = Event.current;//获取当前事件
            if (e != null && e.isKey && e.keyCode != KeyCode.None)
            {
                KeyCode currentKey = e.keyCode;

                //当前按键等于 ESC 时 恢复上一次按键
                if (currentKey==KeyCode.Escape)
                {
                    CurrentKeyItem.Restore();
                    return;
                }

                //判断是否按键冲突
                if (IsRepeat(currentKey))
                {
                    Debug.Log("按键重复!!");
                    CurrentKeyItem.Restore(); //还原按键名称
                }
                else
                    CurrentKeyItem.KeyCode = currentKey; //不重复 修改按键

                CurrentKeyItem.SetBtnColor(new Color32(173, 173, 173, 255)); //还原颜色
                IsSet = false;//不是修改状态
                CurrentKeyItem = null; //当前没有选择按键item
            }
        }
    }

    //是否重复 true 有重复
    bool IsRepeat(KeyCode keyCode)
    {
        //循环查找是否有相同的按键
        for (int i = 0; i < keyItemList.Count; i++)
        {
            if (keyItemList[i].keyItem.KeyCode== keyCode)
            {
                return true;
            }
        }

        return false;
    }

    #endregion

    #region 开启关闭面板

    public void OpenPanel()
    {
       root.gameObject.SetActive(true);
    }

    public void ClosePanel()
    {
       root.gameObject.SetActive(false);
    }
    #endregion
}

将这个脚本拖到SetKeyPanle的UI上 设置keyItemList值和root对象。如下图 :

3.player移动脚本

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

public class player : MonoBehaviour
{
    public Text txt; //这个text是用来显示你按下的按键名称的,你可以随便创建在任何位置,只要赋值给他就好
    public float speed = 10f; //定义一个速度
    void Start()
    {

    }

    void Update()
    {
        //没有开启设置面板时 可移动
        if (SetKeyPanle.GetIntance().IsCurrentOpenState)
        {
            //前进
            if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["前进"].KeyCode))
            {
                transform.Translate(Vector3.forward * Time.deltaTime * speed);
                txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["前进"].KeyCode.ToString();
            }

            //后退
            if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["后退"].KeyCode))
            {
                transform.Translate(Vector3.back * Time.deltaTime * speed);
                txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["后退"].KeyCode.ToString();

            }

            //向左
            if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["向左"].KeyCode))
            {
                transform.Translate(Vector3.left * Time.deltaTime * speed);
                txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["向左"].KeyCode.ToString();

            }

            //向右
            if (Input.GetKey(SetKeyPanle.GetIntance().KeyItemDic["向右"].KeyCode))
            {
                transform.Translate(Vector3.right * Time.deltaTime * speed);
                txt.text = "按下:" + SetKeyPanle.GetIntance().KeyItemDic["向右"].KeyCode.ToString();

            }
        }

    }
}

将这个脚本拖给player (场景中红色cube)赋值

好的这样我们的自定义按键功能就完成了,赶紧试试吧~~

以上就是Unity制作游戏自定义按键详解的详细内容,更多关于Unity的资料请关注我们其它相关文章!

(0)

相关推荐

  • Unity3D获取当前键盘按键及Unity3D鼠标、键盘的基本操作

    获取当前键盘按键,代码如下: using UnityEngine; using System.Collections; public class GetCurrentKey : MonoBehaviour { KeyCode currentKey; void Start () { currentKey = KeyCode.Space; } void OnGUI() { if (Input.anyKeyDown) { Event e = Event.current; if (e.isKey) {

  • Unity实战之FlyPin(见缝插针)小游戏的实现

    目录 一.简单介绍 二.FlyPin (见缝插针)游戏内容与操作 三.游戏代码框架 四.知识点 五.游戏效果预览 六.实现步骤 七.工程源码地址 八.延伸扩展 一.简单介绍 Unity 游戏实例开发集合,使用简单易懂的方式,讲解常见游戏的开发实现过程,方便后期类似游戏开发的借鉴和复用. 本节介绍,FlyPin (见缝插针) 休闲小游戏快速实现的方法,希望能帮到你,若有不对,请留言. 二.FlyPin (见缝插针)游戏内容与操作 1.游戏开始,针 Pin 自动准备好, 2.鼠标点击左键发射 Pin

  • Unity2D实现游戏回旋镖

    本文实例为大家分享了Unity2D游戏回旋镖实现的具体代码,供大家参考,具体内容如下 以下我举出2种同使用情况的回旋镖 那么回旋镖需要怎么做呢? 任务清单如下 回旋镖会自我旋转 回旋镖达到一定距离会飞回来 回旋镖对敌人造成伤害 回旋镖会飞回玩家手里 带着这些任务我们来依次实现这两种情况的回旋镖吧 1.在2D平面游戏上的回旋镖 实现一个丢出回旋镖后,会缓慢减速,然后再直接收回手里,碰到怪马上返回的效果 先创建一个回旋镖实体,并在上面添加如下脚本 public float Speedrotate;

  • Unity3D实现甜品消消乐游戏

    目录 前言 项目效果展示 项目概况 素材展示 场景展示 场景元素 玩法介绍 版本说明 项目源码 前言 解释: 之前用的ScreenToGif录屏,因为上传的.gif最大不超过5MB,所以做了不少删帧和色彩弱化等处理,这才导致色彩看上去不是很舒服,不要盯着它看太久,不然会有点难受... 由于使用的素材是现成的,没有花时间精力去扒,所以细节方面可能不是做的很好. 说明: 这次的甜品消消乐虽然看上去好像挺简单普通的,但是相对于之前的坦克大战,某种程度上已然提升难度了,归类到了算法类层的游戏. 拉到最后

  • Unity实现3D射箭小游戏

    Unity 小游戏:3D射箭,供大家参考,具体内容如下 前两周因为实训太忙,再加上自己对老师所讲的设计模式并不是很理解,所以就没有写博客.这次博客是记录3D射箭游戏的实现过程. 1. 准备资源 我是在网上找的弓与箭的资源,至于靶子,创建五个不同大小的同心圆柱体,如图所示: 需要注意的是,五个圆柱体并不在同一个平面上,这样才能够看清每一环的颜色,并且在检测碰撞时不会出现各种问题. 另外,如果靶子放得离相机太近,就没有射箭的感觉了:离相机太远,好像又看不清靶子了,然后我试着把靶子Material的S

  • Unity3D实现经典小游戏Pacman

    目录 项目概况 整体布局 地图介绍 玩法介绍 相关知识 版本说明 项目源码 项目概况 整体布局 地图介绍 除了音效,游戏地图上的元素有: 普通糖豆(玩家通过移动,经过的普通糖豆会被吃掉,获得积分)  特殊糖豆(玩家吃到后,可以让所有敌方停止移动,产生幻影效果) 隔离墙(相当于迷宫的墙,在两堵墙之间的间隙才能移动)  剩余游戏时间Remain(共设300s,时间一到,游戏结束) 截止到现在花费的游戏时间Now(设在0~300之间) 截止到目前为止的游戏得分Score(越高越好) 敌方人机(分为四种

  • Unity制作游戏自定义按键详解

    目录 一.效果图 二.布局 1.场景布局 2.设置面板布局 三.脚本思路 1.KeyItem脚本 2.SetKeyPanle脚本 3.player移动脚本 一.效果图 二.布局 1.场景布局 创建一个Panel 创建三个cube,Panel地板 两个cube设置一个绿色材质,调整Scale大小让其成为柱子形状,一个cube改名为player设置一个红色材质,当作玩家(用来演示操作的),修改相机位置就可以了. 2.设置面板布局 2.1新建一个空节点名字改为SetKeyPanle,修改属性 2.2在

  • 使用Matlab制作大富翁小游戏的过程详解

    目录 1.自定义头像及名称 2.买地.收费.破产 3.部分代码展示 gui_init.m self_init.m 4.修改记录 5.下载地址 大富翁大家都玩过,走到建筑的位置可以买地,第二圈走到买过的地可以升级,别人经过后需要付过路费,每次经过起点都会获得一定资金,玩到最后还没破产的就是胜者,这里我用MATLAB制作了一款MATLAB版的大富翁小游戏: 1.自定义头像及名称 点击方框内加号可换头像,点击文本区域可改昵称: 当然即使不换头像点击开始后,也会自动分配头像和名称: 2.买地.收费.破产

  • 基于Python制作炸金花游戏的过程详解

    目录 前言 一.思路 二.解决方案 三.总结 前言 <诈金花>又叫三张牌,是在全国广泛流传的一种民间多人纸牌游戏.比如JJ比赛中的诈金花(赢三张),具有独特的比牌规则.游戏过程中需要考验玩家的胆略和智慧.--<百度百科> 前几天在交流群里边,有个叫[^-^]的粉丝分享了一道扑克牌诈金花的题目,要求用Python实现,题目如下: 自己写一个程序,实现发牌.比大小判断输赢. 游戏规则: 一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢. 有以下几种牌: 豹子:三张一样的牌,

  • 原生js实现贪食蛇小游戏的思路详解

    先不多说先上图 下面是代码部分(这里你可以根据需要改变蛇头和身体还有食物的图片,然后默认的样式是使用纯颜色的如果没有更改我的背景图片的话------改这些图开始是想搞笑一下朋友哈哈哈,请不要在意哈),还有操作键是使用 ↑ ↓ ← → ) <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>贪食蛇</title>

  • python制作抽奖程序代码详解

    实现制作抽奖程序,需要认知到我们可以看到一般抽奖程序界面上是有很多按钮的,比如中奖区域,按键开始区域等等,所以我们先要设置界面,然后把这些按钮添加到界面中去,想必这对于学过tkinter的同学应该不难.下面结合实现步骤:设计界面.利用循环.多线程来完成抽奖程序设置吧. 实现代码: import random #导入内置的random模块 list1=list(range(0,15)) #将range元素进行列表转换并赋值给列表list1 print("抽奖号码是:",list1) #打

  • Java实现经典大富翁游戏的示例详解

    目录 前言 主要设计 功能截图 代码实现 总结 前言 大富翁,又名地产大亨.是一种多人策略图版游戏.参与者分得游戏金钱,凭运气(掷骰子)及交易策略,买地.建楼以赚取租金.英文原名monopoly意为“垄断”,因为最后只得一个胜利者,其余均破产收场. <大富翁>游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想. 主要需求 可多人参与的大富翁游戏,玩家有初始资金,通过掷骰子,玩家移动指定骰子点数步骤,根据对应格子上的交易策略,来决定是赚钱还是亏钱,其他玩家破

  • Pygame坦克大战游戏开发实战详解代码

    导语 哈喽!哈喽——我是木木子 今天来升级下之前写的坦克大战游戏嘛,哈哈哈 其实也不算是修改,就是稍微的调试一下!​​ 因为之前写的界面都是英文的 ,有的小伙伴儿英文一点儿都不会的可能看着别扭,今天来一款中 文版的给大家嘛! 俗话说的好:“雨露均沾”.哈哈哈.jpg 小简介: <坦克大战>,1985年由日本开发商南梦宫(Namco)开发,是第一款可以双打的红白机游戏. 当时使用的还是小霸王. 很多小朋友以学习的名义买了以后偷偷打的打游戏还被家长发现了有 没得! <坦克大战>红白机原

  • Pygame实现游戏最小系统功能详解

    目录 前言 一.什么是pygame 1.1 学习pygame的用处 1.2 pygame里的游戏世界 二.pygame简单讲解 2.1 安装pygame 2.2 游戏最小系统 前言 “我有一个梦想,那就是有生之年做出一款属于自己的游戏.” 不知道屏幕前的你是否曾经有和我一样的想法,总觉得市面上的游戏不完全符合你的胃口,想要自己开发出一款属于自己的独有的游戏. 此时,如果你正好学了Python,那么你的机会来了,python也是可以做游戏的!本篇文章将介绍Python一个非常有趣又功能强大库,它所

  • Flutter开发之对角棋游戏实现实例详解

    目录 前沿 演示效果 对角棋规则 实现思路 具体实现 1. 绘制棋盘 2. 绘制棋子 3. 手势处理 4. 游戏规则 优化 总结 前沿 关于对角棋相信大家都不陌生,其凭借着规则简单又灵活多变成为我们童年不可缺少的益智游戏. 今天我将用Flutter来实现一个对角棋游戏,即巩固自己Flutter的绘制和手势知识,也希望这篇文章对大家有所帮助. 演示效果 老规矩,我们先演示下实现的最终效果: 对角棋规则 首先我们还是回顾下对角棋游戏的规则,这里借用 百度百科 的规则说明: 棋盘:象棋棋盘中,将士所在

  • Vue自定义事件(详解)

    前面的话 父组件使用props传递数据给子组件,子组件怎么跟父组件通信呢?这时,Vue的自定义事件就派上用场了.本文将详细介绍Vue自定义事件 事件绑定 每个 Vue 实例都实现了事件接口 (Events interface),即 使用 $on(eventName) 监听事件 使用 $emit(eventName) 触发事件 [注意]Vue 的事件系统分离自浏览器的EventTarget API.尽管它们的运行类似,但是 $on 和 $emit 不是addEventListener 和 disp

随机推荐