服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - Unity制作游戏自定义按键详解

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

2022-12-22 14:32被代码折磨的狗子 C#

这篇文章主要介绍了在Unity中如何实现游戏自定义按键,文中的示例代码讲解详细,对我们学习Unity有一定帮助,感兴趣的可以跟随小编学习一下

一、效果图

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

 

二、布局

1.场景布局

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

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

2.设置面板布局

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 

三、脚本思路

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

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

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对象,我们在面板中设置他的初始化按键

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

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对象。如下图 :

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

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制作游戏自定义按键详解的详细内容,更多关于Unity的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/qq_42345116/article/details/122582745

延伸 · 阅读

精彩推荐
  • C#c# 实现获取汉字十六进制Unicode编码字符串的实例

    c# 实现获取汉字十六进制Unicode编码字符串的实例

    下面小编就为大家带来一篇c# 实现获取汉字十六进制Unicode编码字符串的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过...

    C#教程网8982021-04-28
  • C#C#统计C、C++及C#程序代码行数的方法

    C#统计C、C++及C#程序代码行数的方法

    这篇文章主要介绍了C#统计C、C++及C#程序代码行数的方法,较为详细的分析了C#统计文本文件的原理与相关实现技巧,具有一定参考借鉴价值,需要的朋友可以参...

    北风其凉7852021-10-19
  • C#如何用WindowsForm给窗口添加一些简单的动画效果

    如何用WindowsForm给窗口添加一些简单的动画效果

    这篇文章主要介绍了如何用WindowsForm给窗口添加一些简单的动画效果,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    zhuanghamiao11852022-09-21
  • C#C#后台调用前台JS函数方法

    C#后台调用前台JS函数方法

    今天小编就为大家分享一篇关于C#后台调用前台JS函数方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看...

    chenqiangdage11072022-03-08
  • C#深入理解StringBuilder的使用方法

    深入理解StringBuilder的使用方法

    下面小编就为大家带来一篇深入理解StringBuilder的使用方法。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    编程之家5602021-11-22
  • C#c#预处理指令分析

    c#预处理指令分析

    这篇文章主要介绍了c#预处理指令的相关资料,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...

    编码者频道5882022-10-08
  • C#c#基础系列之ref和out的深入理解

    c#基础系列之ref和out的深入理解

    有过C#基础知识的都应该清楚Ref和Out的使用方法,所以下面这篇文章主要给大家介绍了关于c#基础系列之ref和out的相关资料,文中通过示例代码介绍的非常详...

    大菜5392022-03-01
  • C#CefSharp如何进行页面的缩放(Ctrl+滚轮)

    CefSharp如何进行页面的缩放(Ctrl+滚轮)

    CefSharp简单来说就是一款.Net编写的浏览器包,本文主要介绍了CefSharp如何进行页面的缩放,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    吴志兴4572022-11-21