UnityVR--EventManager--事件中心3

这篇具有很好参考价值的文章主要介绍了UnityVR--EventManager--事件中心3。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前期准备

事件控制移动

事件控制鼠标点击拖拽物体

添加开火事件

总结


前期准备

  使用事件中心(EventManager)对输入事件进行管理,也就是使用InputSystem中设置的按键,来实现鼠标拖拽、角色移动、发射子弹等功能。

  1. InputSystem的准备:需要设置输入设备并关联事件,比如监听键盘输入"WASD"事件实现角色移动的回调,监听鼠标点击事件实现拖拽物体移动等。详见插件1--新版InputSystem;

  2. 在建立事件中心之前,拖拽、移动等功能已经使用旧版的输入设置实现过了,这里需要使用并修改之前的几个脚本:

    (1)修改Rigidbody--移动控制当中控制角色移动的方法;

    (2)在Ray/Raycast/Linecast/OverlapSphere中点击拖拽物体的方法不再需要了,更新为使用事件监听判断鼠标按键;

    (3)开火的功能,也不需要if去判断按键,修改为监听开火Fire事件。

  以下开始一个一个地实现:

事件控制移动

  在Rigidbody--移动控制当中使用Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")的方式获取键盘WASD的输入数据,在有了事件中心后,改为采用注册移动事件的方式,发送并回传一个位置的参数。写一个HeroMoveEvent.cs脚本:

//注册一个移动的事件
public class HeroMoveEvent : MonoBehaviour
{
    private Rigidbody rb;
    private Vector2 moveInput; //接收回传的参数
    private Vector3 movement;//移动的坐标位置(将之前的二维坐标转成这里的三维)
    private Quaternion targetRotation;
    public float moveSpeed = 2;
    public float rotateSpeed = 2;
    GameObject Bullet;
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        EventManager.Instance.AddEvent(EventType.OnPlayerMove, this, data =>
        { //注册一个移动的事件,监听者是HeroMoveEvent(本类),这个事件由
          //InputManager中的OnMove()发送给场景中的PlayerInput

            var eventData = data as EventDataPlayerMove;
            //EventData参数转为EventDataPlayerMove类型

            moveInput = eventData.position; 
            //移动的距离由EventDataPlayerMove中的position变量决定
        });
    }

    void FixedUpdate()
    {
        //moveInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")); //之前使用Input拿到的水平、垂直方向数据

        //使用事件后,通过回传的EventData数据赋值给moveInput变量
        movement.Set(moveInput.x, 0, moveInput.y);//得到移动的坐标
        movement.Normalize();

        //检测是否有输入
        bool hInput = !Mathf.Approximately(moveInput.x, 0);
        bool vInput = !Mathf.Approximately(moveInput.y, 0);
        if (hInput || vInput)
        {
            movement = Quaternion.Euler(0, Camera.main.transform.eulerAngles.y, 0) * movement;
        }
        Vector3 lookForward = Vector3.RotateTowards(transform.forward, movement, rotateSpeed * Time.fixedDeltaTime, 360);
        targetRotation = Quaternion.LookRotation(lookForward);
        rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
        rb.MoveRotation(targetRotation);
    }

  注册事件后,需要发送事件,以及在PlayerInput中绑定它(详见插件1--新版InputSystem中的添加并绑定移动事件)在脚本中建立一个方法OnMove(),用于发送OnPlayerMove事件:

    public void OnMove(InputAction.CallbackContext context)
    {//绑定PlayerInput中的PlayerMap-Move事件
        EventManager.Instance.SendEvent(EventType.OnPlayerMove, new EventDataPlayerMove()
        {//发送事件
            position=context.ReadValue<Vector2>()  //返回context参数
        });
    }

并且在场景中的PlayerInput->Event->PlayerMap->Move中绑定这个方法:

UnityVR--EventManager--事件中心3

事件控制鼠标点击拖拽物体

  拖拽的方式还是使用Ray/Raycast/Linecast/OverlapSphere中的方法应用2:实现鼠标点击拖拽物体,使用射线检测是否点击到物体,如果以及点击到了,就将鼠标输入的XY坐标位置转换为物体的XZ场景位置。不同的是,这里改为监听鼠标点击的事件,不再在update()中判断鼠标的输入状态。同样,也需要在InputSystem中设置鼠标按键。步骤如下:

  1. 参照新版InputSystem的设置,在InputControl中添加LeftMouseClick、LeftMouseUp和MouseDrag三个Action,设置如下:

UnityVR--EventManager--事件中心3 UnityVR--EventManager--事件中心3

UnityVR--EventManager--事件中心3  UnityVR--EventManager--事件中心3

   2. 注册添加鼠标拖拽事件,并且定义回调函数,回调函数的内容与Ray/Raycast/Linecast/OverlapSphere一文中的应用2:实现鼠标点击拖拽物体类似,主要就是利用从摄像机向鼠标位置射出的射线,判断是否点击到物体:

public class MouseClick : MonoBehaviour
{
    private Ray ray;  //定义射线
    private Transform clicked; //被鼠标点击的物体

    void Start()
    {//注册鼠标输入事件
        EventManager.Instance.AddEvent(EventType.OnMouseInput, this, MoveGameObject);
    }

    //定义回调函数
    void MoveGameObject(EventDataBase data)
    {
        var eventData = data as EventDataMouseInput;
        var state = eventData.State; //检测鼠标状态
        var key= eventData.Key;  //检测鼠标按键

        if(key==EMouseInputKey.Left&&state==EMouseInputState.Down)
        {//当检测到左键、按下
            ray = Camera.main.ScreenPointToRay(eventData.MousePosition);
            //使用事件数据库传入的二维向量参数,做一套从屏幕射向鼠标位置的射线
            Physics.Raycast(ray, out RaycastHit hit, 100, LayerMask.GetMask("Enemy"));
            if (hit.collider != null)
            {//被点击中的物体,赋值给Click变量,准备之后被鼠标拖拽
                clicked = hit.transform; 
                var wPos = Tools.MouseToWorld(clicked.position);
                //使用工具集中的坐标转换,将鼠标坐标转为世界坐标
            }
        }

        if(key == EMouseInputKey.Left && state == EMouseInputState.Stay)
        {//鼠标左键停留持续按下的状态
            if (clicked != null)
            {
                Vector3 pos = Tools.MouseToWorld(clicked.position);
                clicked.position = new Vector3(pos.x , clicked.position.y, 
                    pos.z);
            }
        }
        if (key == EMouseInputKey.Left && state == EMouseInputState.Up)
        {//鼠标抬起
            clicked= null;
        }
    }
}

 3. 发送事件,建立一个新脚本,或者我直接放在InputManager.cs中,管理所有输入事件(详见InputManager),这个脚本挂在场景中的SingleMono上。这里写了三个发送事件方法,“左键点击”、“左键拖拽”、“左键释放”:

public class InputManager : SingleMono<InputManager>
{
    public void OnLeftMouseClick(InputAction.CallbackContext context)
    {
         //Debug.LogError("发送鼠标左键单击世界事件");
         //鼠标点击世界左键按下事件,可以在任何一个地方监听这个事件
         EventDataMouseInput mouseInput= new EventDataMouseInput(EMouseInputKey.Left,
         EMouseInputState.Down,Input.mousePosition);
         EventManager.Instance.SendEvent(EventType.OnMouseInput, mouseInput);
    }
    public void OnMouseDrag(InputAction.CallbackContext context)
    {
         //Debug.LogError("鼠标左键持续点击世界事件");
         EventManager.Instance.SendEvent(EventType.OnMouseInput, new EventDataMouseInput()
        {
          State = EMouseInputState.Stay,
          Key = EMouseInputKey.Left,
          MousePosition = context.ReadValue<Vector2>()
        });
    }
    public void OnLeftMouseUp(InputAction.CallbackContext context)
    {
        //Debug.LogError("发送鼠标左键抬起事件");
        EventManager.Instance.SendEvent(EventType.OnMouseInput, new EventDataMouseInput
            (EMouseInputKey.Left, EMouseInputState.Up, Input.mousePosition));
    }
}

  4. 上面3中定义的“左键点击”、“左键拖拽”、“左键释放”三个方法,在场内的PlayerInput组件中,绑定到上面1中添加的LeftMouseClick、LeftMouseUp和MouseDrag三个Action上,详见新版InputSystem中的方法,这里简单放一下设置结果:

 UnityVR--EventManager--事件中心3

   5. 运行结果,与Ray/Raycast/Linecast/OverlapSphere中应用2:实现鼠标点击拖拽物体相同

UnityVR--EventManager--事件中心3

添加开火事件

  在新版InputSystem中有详细的方法,这里放一下简单的步骤和脚本:

  1. 注册事件:

public class BulletFireEvent : MonoBehaviour
{
        public GameObject bullet;
        void Start()
        {
            EventManager.Instance.AddEvent(EventType.OnPlayerFire, this, callback =>
            {
                bullet = Resload.Instance.LoadPrefab("Bullet");
                bullet.SetActive(true);
                bullet.transform.position = transform.position;
                bullet.transform.rotation = transform.rotation;
                Destroy(bullet, 2);
            });
        }
    }

  2. 发送事件,这里写在上面的InputManager.cs中

    public void OnFire(InputAction.CallbackContext context)
    {//绑定新版InputSystem中的PlayerMap-Fire事件
        EventManager.Instance.SendEvent(EventType.OnPlayerFire, null);
    }

  3. 在场景中PlayerInput组件中绑定OnFire事件,详见新版InputSystem中的设置方法:

UnityVR--EventManager--事件中心3

  效果与之前的开火效果相同,就不放效果图了。

总结

  可以比较一下使用“事件”和不使用“事件”的代码,比如在Ray/Raycast/Linecast/OverlapSphere一篇中的应用2:实现鼠标点击拖拽物体,和本篇的鼠标点击拖拽事件相比较,前者在update()中用了3个If判断鼠标的状态,而后者没有使用update(),因此在节约性能方面,事件中心的建立和使用更胜一筹。

  更重要的是,如果在建立一个较大项目时,事件中心的优点就更能体现出来了,否则代码量会非常庞大。文章来源地址https://www.toymoban.com/news/detail-471642.html

到了这里,关于UnityVR--EventManager--事件中心3的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [Unity] No.3 EventManager事件管理 与 观察者模式

    前文讲到了InputManager,在其后需要一个事件的管理者用于调度任务的执行,包括: ①查看发生了什么事; ②出事后看看都需要通知谁干什么事; 以上两个内容就对应了EventManager中关键的 监听 和 回调 ,而在讲EventManager之前还需要知道,它是符合观察者这一模式的。 此处不

    2024年02月08日
    浏览(42)
  • UnityVR--AudioManager--音频管理中心

    目录 前言 建立音频配置文件AudioConfig 建立音频管理AudioManager 使用AudioManager播放音效 前言   关于音频组件的简单使用请详见VideoPlayerAudioSource,不过在一个工程项目中,会有很多的声音文件,播放的时间和条件也不相同,因此在实际制作中,需要集中管理,这就是建立AudioM

    2024年02月09日
    浏览(37)
  • 使用 Git&GitHub 的前期准备

    本节包含 SSh Key 的设置,从 GitHub 上创建一个仓库,并 clone 到本地,然后对其进行更改,提交,同步到仓库。需要已经下载好了 Git ,并且已经创建了一个 GitHub 账户 1.1 创建 SSH Key 运行这条命令,然后直接敲两次回车就可以。第一次回车是将 SSH 密匙存放在默认的路径下,第

    2024年01月20日
    浏览(40)
  • 使用whisper生成音频字幕——前期准备

    最近我们要写一个把没有字幕的音频生成字幕的APP,前期调研的很多方式,使用whisper可以实现,这篇文章就是说一些前期准备工作,我就不自己再写一篇了,参考以下两篇文章就行了。 whisper安装下载和python环境的准备 安装过程中踩过的坑

    2024年02月11日
    浏览(42)
  • 番外3:下载+安装VMware(前期准备)

    step1: 查看自己笔记本电脑配置; step2: 下载并安装VMware (下载地址www.kkx.net/soft/16841.html)这里选择本地普通下载; step3: 安装VMware过程中需要填写密钥(本人用的最后一个) ; #UU54R-FVD91-488PP-7NNGC-ZFAX6 #YC74H-FGF92-081VZ-R5QNG-P6RY4 YC34H-6WWDK-085MQ-JYPNX-NZRA2

    2024年02月07日
    浏览(35)
  • 【UE Sequencer系列】01-前期准备

    新建一个工程 在虚幻商城中将我们需要的三种资产导入到新建的工程中 打开工程可以看到导入的资产 新建两个文件夹,一个用来存放音频,一个用来存放所有的Sequencer 导入音频(只支持wav格式) 选中声波,创建一个sound cue 打开“Forge”关卡 改变视口布局 第一个视口选择“

    2023年04月09日
    浏览(42)
  • 程序员自由创业周记#2:前期准备

    感恩 上次公开了创业的决定后,得到了很多亲朋好友和陌生朋友的鼓励或支持,以不同的形式,感动之情溢于言表。这些都会记在心里,大恩不言谢~ 创业方向 笔者是一名资质平平的iOS开发程序猿,创业项目也就是开发App卖,类型的话主要以工具类为主,优先会解决一些我的

    2024年02月10日
    浏览(46)
  • 数据清洗:数据挖掘的前期准备工作

    ⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者: 秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们 点赞👍🏻、收藏

    2024年02月07日
    浏览(49)
  • Hyperledger Fabric 应用实战(1)--前期准备

    1.1应用说明 本应用示例基于Hyperledger fabric2.4搭建一个自由房屋租赁区块链系统freerent, 用户可以自由在链上开展合同签订、执行和验真。freerent应用背景相对简单,当前应用搭建示例展示 fabric初级功能。后期将会不断探索 fabric应功能特性,也希望可以结合IPFS实现合同存储,

    2024年01月25日
    浏览(38)
  • DnCNN-matlab版本代码实战前期准备

    一、DnCNN-matlab版本代码实战前期准备 (1)DnCNN-matlab版本代码下载   https://download.csdn.net/download/qq_41104871/87457430 (2)DnCNN的灰度图像数据集下载   https://blog.csdn.net/qq_41104871/article/details/129931884 (3)DnCNN的彩色图像数据集下载   https://blog.csdn.net/qq_41104871/article/details/129932352

    2024年02月11日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包