欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity笔记 第一天

程序员文章站 2022-04-04 11:14:09
...

与3D物体交互

  • 思路

    第一步,我们想在Unity3D中交互的时候,首先我们想到的是射线,调用Ray这个API,这样我们就可以用我们的鼠标(键盘)来与3D物体交互了,在这个案例中我用的是鼠标与之交互,如果有兴趣的可以用键盘试一试,我在下一篇中将会使用键盘与之交互,并且制作类似于吃鸡或者APG游戏中拾取物体那样。

    第二步,交互一般都是有UI或者是窗口,当触发一个事件时将UI弹出来。

    第三步,制作UI。

  • 步骤

	 private void MouseClickRay()
	    {
	        
	        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
	
	        if (Physics.Raycast(ray, out hit, 50, ClickCub.value))
	        {
	            WindosOfCube.Instance.ClickCubeisShow();
	            Debug.Log("被检测的物体的名字:" + hit.collider.gameObject.name);
	        }
	    }

我在TouchCube这个类中写了用鼠标控制射线的方法
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
这样就可以将射线与鼠标绑定;下面的ClickCub我定义的是LayerMask,通过给物体设 置不同的层级,也可以用Tag(标签),来区分要交互的物体。

然后,这里我遇到一个坑,我开始想的的在UpDate里面去使用它,然后控制它每次点击只会运行一次,但是在经历的多次尝试以后发现,我无法控制它,只能降低其频率,可能是我的方法不太对,我下来在试一试,如果成功我会在下一篇或者下下篇进行讲解,不过我找到了另一种方法,那就是OnMousexxx,这里有个小知识点
(Event和Input.GetMousexxx事件会被任何gameobject监控到,而OnMousexxx事件只会被该脚本附加上的gameobject监控到),Inpput.GetMousexxx要写在Update中,就会出现每帧调用的现象,而OnMousexxx只会在过载的gameobject中才可以,而且只运行一次。

接下来,就可以开始写UI的逻辑了,这个面板是不是在开始的时候应该隐藏起来,有很多种方法,比如,先将UI移出Canvas,需要的时候在移回来,或者直接让面板开始不可见,然后需要的时候在显示,这样他的位置就不需要移动,还有一种不太可取的方法就是,需要的时候实例化出来,用完就销毁,然后反复这个操作,各有个的特点,不过我用的是第二种方法,将其添加CanvasGroup组件,然后可以修改透明度值,就可以达到这种效果,怎么简单怎么来。

需要隐藏的时候:

canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 0;
canvasGroupWindos.GetComponent<CanvasGroup>().interactable = false;
canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = false;

需要显示的时候:

canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 1;
canvasGroupWindos.GetComponent<CanvasGroup>().interactable = true;
canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = true;

我将另外两个脚本写成单例,调用的时候就比较简单了,写按钮的时候我用了拉姆达表达式,匿名委托来表示回调,也是比较的简单,(写代码,简单明了实现功能就可以了,不需要搞得太复杂)这样一个与3D物体的交互就完成了。

以下是源代码和脚本的名字

ClickManager.cs

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

public class ClickManager : MonoBehaviour
{

    public Button CloseBtn;

    private void Start()
    {
        //lambda(拉姆达)匿名委托
        CloseBtn.onClick.AddListener(()=> {
            WindosOfCube.Instance.ButtonWindosClose();
        });
    }
}

WindosOfCube.cs

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

public class WindosOfCube : MonoBehaviour
{
    //单例,方便其他脚本调用
    public static WindosOfCube Instance;

    private void Awake()
    {
        Instance = this;
    }
    
    public CanvasGroup canvasGroupWindos;

    //设置一个布尔条件保护
    bool isShow;

    void Start()
    {
        isShow = true;
        if (isShow)
        {
            //开始先将窗口UI隐藏起来
            canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 0;
            canvasGroupWindos.GetComponent<CanvasGroup>().interactable = false;
            canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = false;
            
        }
    }

    public void ClickCubeisShow()
    {
        //当isShow为true时将UI显示出来
        if (isShow)
        {
            canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 1;
            canvasGroupWindos.GetComponent<CanvasGroup>().interactable = true;
            canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = true;
        }
    }

    public void ButtonWindosClose()
    {
        if (isShow)
        {
            canvasGroupWindos.GetComponent<CanvasGroup>().alpha = 0;
            canvasGroupWindos.GetComponent<CanvasGroup>().interactable = false;
            canvasGroupWindos.GetComponent<CanvasGroup>().blocksRaycasts = false;
        }
    }
}

TouchCube.cs

using UnityEngine;

public class TouchCube : MonoBehaviour
{

    RaycastHit hit;

    public LayerMask ClickCub;

    private void MouseClickRay()
    {
        
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out hit, 50, ClickCub.value))
        {
            WindosOfCube.Instance.ClickCubeisShow();
            Debug.Log("被检测的物体的名字:" + hit.collider.gameObject.name);
        }
    }

    private void OnMouseDown()
    {
        MouseClickRay();
    }


    /*这个是我之前的错误方法,代码写错了,可以注释掉
    知道整个完成了以后就可以删掉,这样有助于思路的扩展,也会减少代码的书写
    private bool isState = true;
    void Update()
    {
        //if (isState)
        //{
            //Debug.Log("come  2222");

            if (isState && Input.GetKey(KeyCode.Mouse0))
            {
                Debug.Log("come 333");
                
                isState = false;
            }
        isState = true; 
            
        //}
    }
    */
}

效果图

点击前
Unity笔记 第一天
点击后
Unity笔记 第一天
这次没用动图,下次一定~

我用的版本为Unity2018.3.5

https://pan.baidu.com/s/1Xg5el7psfpN2lNzJCC_9oA
提取码:2j2g

相关标签: unity3d 游戏