Skip to content

输入事件系统

本篇文档我们将介绍在 Cocos Creator 中对全局输入事件的处理。

全局输入事件是指与节点树不相关的各种输入事件,由 input 来统一派发,目前支持了以下几种事件

  • 鼠标事件

  • 触摸事件

  • 键盘事件

  • 设备重力感应事件

定义输入事件

上文提到的输入事件都可以通过input.on(type,callback,target)来监听,其中 type 是事件类型,callback 是事件回调函数,target 是回调函数的 this 上下文。

鼠标事件

type 类型

  • Input.EventType.MOUSE_DOWN

  • Input.EventType.MOUSE_UP

  • Input.EventType.MOUSE_MOVE

  • Input.EventType.MOUSE_WHEEL

触摸事件

type 类型

  • Input.EventType.TOUCH_START

  • Input.EventType.TOUCH_MOVE

  • Input.EventType.TOUCH_END

  • Input.EventType.TOUCH_CANCEL

键盘事件

type 类型

  • Input.EventType.KEY_DOWN 键盘按下

  • Input.EventType.KEY_UP 键盘释放

  • Input.EventType.KEY_PRESSING 持续按下

设备重力感应事件

type 类型

  • Input.EventType.DEVICEMOTION

指针事件

指针事件包括 鼠标事件触摸事件

使用方法如下

ts
import { _decorator, Component, input, Input, EventTouch } from "cc";
const { ccclass } = _decorator;

@ccclass("Example")
export class Example extends Component {
  onLoad() {
    input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
  }

  onDestroy() {
    input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
  }

  onTouchStart(event: EventTouch) {
    console.log(event.getLocation()); // Location on screen space
    console.log(event.getUILocation()); // Location on UI space
  }
}

键盘事件

使用方法如下

ts
import {
  _decorator,
  Component,
  input,
  Input,
  EventKeyboard,
  KeyCode,
} from "cc";
const { ccclass } = _decorator;

@ccclass("Example")
export class Example extends Component {
  onLoad() {
    input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
    input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
  }

  onDestroy() {
    input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
    input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
  }

  onKeyDown(event: EventKeyboard) {
    switch (event.keyCode) {
      case KeyCode.KEY_A:
        console.log("Press a key");
        break;
    }
  }

  onKeyUp(event: EventKeyboard) {
    switch (event.keyCode) {
      case KeyCode.KEY_A:
        console.log("Release a key");
        break;
    }
  }
}

设备重力感应事件

使用方法如下

ts
import { _decorator, Component, input, Input, log } from "cc";
const { ccclass } = _decorator;

@ccclass("Example")
export class Example extends Component {
  onLoad() {
    input.setAccelerometerEnabled(true);
    input.on(Input.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this);
  }

  onDestroy() {
    input.off(Input.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this);
  }

  onDeviceMotionEvent(event: EventAcceleration) {
    log(event.acc.x + "   " + event.acc.y);
  }
}

3D 物体的触摸检测

3D 物体的触摸检测需要通过射线检测来实现。

具体做法是通过渲染 3D 物体的 Camera 到触点的屏幕坐标,生成一条射线,判断射线是否穿过想要检测的对象。具体代码实现如下:

ts
import {
  _decorator,
  Component,
  Node,
  Camera,
  geometry,
  input,
  Input,
  EventTouch,
  PhysicsSystem,
} from "cc";
const { ccclass, property } = _decorator;

@ccclass("Example")
export class Example extends Component {
  // Specify the camera rendering the target node.
  @property(Camera)
  readonly cameraCom!: Camera;

  @property(Node)
  public targetNode!: Node;

  private _ray: geometry.Ray = new geometry.Ray();

  onEnable() {
    input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
  }

  onDisable() {
    input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
  }

  onTouchStart(event: EventTouch) {
    const touch = event.touch!;
    this.cameraCom.screenPointToRay(
      touch.getLocationX(),
      touch.getLocationY(),
      this._ray
    );
    if (PhysicsSystem.instance.raycast(this._ray)) {
      const raycastResults = PhysicsSystem.instance.raycastResults;
      for (let i = 0; i < raycastResults.length; i++) {
        const item = raycastResults[i];
        if (item.collider.node == this.targetNode) {
          console.log("raycast hit the target node !");
          break;
        }
      }
    } else {
      console.log("raycast does not hit the target node !");
    }
  }
}