【Unity3D】人机交互Input

1 前言

Input 是 Unity3D 中用于人机交互的工具类,用户可以调用其 GetKey、GetMousePosition、GetMouseButton、GetAxis、GetButton 等方法获取键盘和鼠标的状态信息,再通过这些状态信息控制游戏对象,从而实现人机交互。

1)键盘输入

// 按住按键
public static bool GetKey(KeyCode key)
// 按下按键
public static bool GetKeyDown(KeyCode key)
// 抬起按键
public static bool GetKeyUp(KeyCode key)

KeyCode 的取值有:

A~Z
F1~F15
// 键盘顶部的数字
Alpha0~Alpha9
Left、RightArrow、UpArrow、DownArrow
LeftCtrl、LeftShift、LeftAlt、LeftWindows、RightCtrl、RightShift、RightAlt、RightWindows
Tab、Space、Backspace、Return
// 加号、减号、星号、斜杠、反斜杠、左括号、右括号、小于号、大于号、等于号、上尖号
Plus、Minus、Asterisk、Slash、Backslash、LeftBracket、RightBracket、Less、Greater、Equals、Caret
// 逗号、点号、问号、分号、冒号、单引号、反引号、双引号、感叹号
Comma、Period、Question、Semicolon、Colon、Quote、BackQuote、DoubleQuote、Exclaim
// @符号、$符号、&符号、下划线
At、Dollar、Ampersand、Underscore
Insert、Delete、Home、End、PageUp、PageDown、Print
CapsLock、Numlock、ScrollLock
Keypad0~Keypad9、KeypadPeriod
KeypadPlus、KeypadMinus、KeypadMultiply、KeypadDivide
KeypadEquals、KeypadEnter
// 鼠标左键、鼠标右键、鼠标中间
Mouse0、Mouse1、Mouse2

2)鼠标输入

// 按住鼠标
public static bool GetMouseButton(int button)
// 按下鼠标
public static bool GetMouseButtonDown(int button)
// 抬起鼠标
public static bool GetMouseButtonUp(int button)
// 鼠标坐标
Vector3 position = Input.mousePosition

说明:button 取值为 0、1、2,分别表示鼠标左键、右键、中键。

3)虚拟轴输入

在【Edit→Project Settings→Input】中可以打开 InputManager 配置界面,用户可以在此配置虚拟轴信息。

// 按左右箭头或A、D键,hor在-1~1之间变化
float hor = Input.GetAxis("Horizontal");
// 按上下箭头或W、S键,hor在-1~1之间变化
float ver = Input.GetAxis("Vertical");
// 获取鼠标在水平方向上的移动
float mouseX = Input.GetAxis("Mouse X");
// 获取鼠标在竖直方向上的移动
float mouseY = Input.GetAxis("Mouse Y");
// 获取滚轮信息, 上滑为正, 下滑为负
float scroll = Input.GetAxis("Mouse ScrollWheel");

4)虚拟按键输入

InputManager 配置界面配置虚拟按键,如下:

// 按住虚拟按键
public static bool GetButton(string buttonName)
// 按下虚拟按键
public static bool GetButtonDown(string buttonName)
// 抬起虚拟按键
public static bool GetButtonUp(string buttonName)
// 按以上配置,按住Q键或鼠标左键返回true,表示开火了
bool fire = Input.GetButton("Fire");

5)鼠标回调方法

using UnityEngine;
 
public class MouseEventTest : MonoBehaviour {
    private void OnMouseEnter() { // 鼠标进入碰撞体时回调
        Debug.Log("OnMouseEnter");
    }
 
    private void OnMouseOver() { // 鼠标悬浮在碰撞体上回调
        Debug.Log("OnMouseOver");
    }
 
    private void OnMouseExit() { // 鼠标离开碰撞体时回调
        Debug.Log("OnMouseExit");
    }
 
    private void OnMouseDown() { // 鼠标在碰撞体上按下了左键时回调
        Debug.Log("OnMouseDown");
    }
 
    private void OnMouseUp() { // 鼠标在碰撞体上按下了左键, 并且抬起时回调(此时不一定悬浮在碰撞体上)
        Debug.Log("OnMouseUp");
    }
 
    private void OnMouseUpAsButton() { // 鼠标按下和抬起都在同一个碰撞体上, 并且抬起了鼠标左键时回调
        Debug.Log("OnMouseUpAsButton");
    }
 
    private void OnMouseDrag() { // 鼠标在碰撞体上按下, 并拖拽时回调(拖拽过程中不一定悬浮在碰撞体上)
        Debug.Log("OnMouseDrag");
    }
}

说明:MouseEventTest 挂在需要触发鼠标事件的对象上,并且该对象有碰撞体组件,2D UI 需要添加 BoxCollider2D 组件。

2 应用

本节将实现坦克对战游戏。

1)实现需求

  • 绘制2个坦克,一个表示己方,一个表示敌方;
  • 用户可以通过上下箭头按键控制己方坦克前后移动,通过左右箭头按键控制己方坦克左右移动或左右转向;
  • 用户可以通过鼠标左键发射炮弹;
  • 敌方坦克可以自动转向瞄准己方坦克,但是有延时,转向先快后慢,延时插值系数为 0.6;
  • 敌方坦克瞄准己方坦克后(允许有5°误差),自动开炮,开炮间隔需要大于1秒。

2)创建游戏对象

游戏对象的 Transform 组件参数如下:

name type position Rotation scale Color/Texture
MyTank Empty (0, 0.25, -5) (0, 0, 0) (1, 1, 1) ——
Button Cube (0, 0, 0) (0, 0, 0) (2, 0.5, 2) #228439FF
Top Cube (0, 0.5, 0) (0, 0, 0) (1, 0.5, 1) #228439FF
Gun Cylinder (0, 0, 1.5) (90, 0, 0) (0.2, 1, 0.4) #228439FF
FirePoint Empty (0, 1.15, 0) (0, 0, 0) (1, 1, 1) ——
MyBullet Sphere (0, 0, -2) (0, 0, 0) (0.2, 0.2, 0.2) #82EA4FFF
Plane Plane (0, 0, 0) (0, 0, 0) (10, 10, 10) GrassRockyAlbedo
EnemyTank Empty (0, 0.25, 5) (0, 180, 0) (1, 1, 1) 15D3F9FF
EnemyBullet Sphere (0, 0, 2) (0, 0, 0) (0.2, 0.2, 0.2) #4C55F8FF

说明: EnemyTank 由 MyTank复制而来,只是修改了它自己及其子对象的颜色属性;EnemyBullet 由 MyBullet 复制而来,然后修改了颜色属性;将 MyBullet 和 EnemyBullet 拖拽至 Assets 窗口的 Resources/Prefabs 目录下,生成预设体(prefab),再删除 Hierarchy 窗口下 MyBullet 和 EnemyBullet 对象。

游戏对象的层级结构如下:

游戏界面如下:

3)脚本组件

MyTank.cs

using UnityEngine;

public class MyTank : MonoBehaviour {
    private Transform firePoint; // 开火点
    private GameObject bulletPrefab; // 炮弹预设体

    void Start() {
        firePoint = transform.Find("Top/Gun/FirePoint");
        bulletPrefab = (GameObject) Resources.Load("Prefabs/MyBullet");
        Debug.Log(bulletPrefab);
    }

    void Update () {
        float hor = Input.GetAxis("Horizontal");
        float ver = Input.GetAxis("Vertical");
        move(hor, ver);
        if (Input.GetMouseButtonDown(0)) { // 开炮
            GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity); // 通过预设体创建炮弹
            bullet.GetComponent<Bullet>().setMoveDir(transform.forward); // 设置炮弹飞出方向
        }
    }

    private void move(float hor, float ver) {
        // 移动方案一:上下箭头控制前后移动,左右箭头控制左右移动
        // transform.Translate(hor * Time.deltaTime * 3, 0, ver * Time.deltaTime * 3);

        // 移动方案二:上下箭头控制前后移动,左右箭头控制左右拐弯
        transform.Translate(0, 0, ver * Time.deltaTime * 3);
        transform.Rotate(Vector3.up * hor * Time.deltaTime * 120f);
    }
}

说明:MyTank.cs 脚本组件挂载在 MyTank 游戏对象上。

EnemyTank.cs

using UnityEngine;

public class EnemyTank : MonoBehaviour {
    private Transform target; // 目标
    private Transform top; // 炮头
    private Transform firePoint; // 开火点
    private GameObject bulletPrefab; // 炮弹预设体
    private float fireInternal = 0; // 开炮间隔

    void Start () {
        target = GameObject.Find("MyTank/Top").transform;
        top = transform.Find("Top");
        firePoint = transform.Find("Top/Gun/FirePoint");
        bulletPrefab = (GameObject) Resources.Load("Prefabs/EnemyBullet");
    }

    void Update () {
        Quaternion dir = Quaternion.LookRotation(target.position - top.position);
        top.rotation = Quaternion.Lerp(top.rotation, dir, Time.deltaTime * 0.6f); // 敌军转向己方
        float angle = Vector3.Angle(target.position - top.position, top.forward);
        if (angle < 5 && fireInternal > 1) {
            GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity); // 通过预设体创建炮弹
            bullet.GetComponent<Bullet>().setMoveDir(top.forward); // 设置炮弹飞出方向
            fireInternal = 0;
        }
        fireInternal += Time.deltaTime;
    }
}

说明:EnemyTank.cs 脚本组件挂载在 EnemyTank 游戏对象上。

Bullet.cs

using UnityEngine;

public class Bullet : MonoBehaviour {
    private Vector3 moveDir; // 炮弹飞出方向

    void Start () {
        Destroy(gameObject, 2); // 2秒后自动销毁
    }

    void Update () {
        if (moveDir != null) {
            transform.Translate(moveDir * Time.deltaTime * 6);
        }
    }

    public void setMoveDir(Vector3 dir) {
        moveDir = dir;
    }
}

说明:Bullet.cs 脚本组件挂载在 MyBullet 和 EnemyBullet 预设体上。

4)运行效果

左右箭头按键控制己方坦克左右移动

左右箭头按键控制己方坦克左右转向

声明:本文转自【Unity3D】人机交互Input

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容