• Ray射线


    射线的机制相当于碰撞;

    创建射线: 

    1 Ray ray=new Ray();
    origin : 射线发射的原点;
    direction: 射线发射的方向;
    distance: 射线的长度;
    hitInfo: 如果返回true,hitInfo将包含碰撞器碰撞的更多信息;
    Layer: gameObject的层;
    LayerMask: 只选定LayerMask层内的碰撞器,其他层内碰撞器忽略;返回bool类型,当射线与任何碰撞器碰撞时为真,反之为假;
     
    射线碰撞的应用:
    使用Physics类方法Raycast方法实现射线碰撞检测功能;
    射线的添加方法:
    1 bool Raycast(Ray ray,out RaycastHit hitInfo);       // Ray ray是要发射的射线, hitInfo是碰撞信息;
    2 // 从主摄像头到鼠标点击位置创建一条射线;
    3 Ray ray=Camera.main.ScreenPiontToRay(Input.mousePosition);

    实际运用如代码所示:

     1 using Sysytem.Collections;
     2 using System.Collections.Generic;
     3 using UnityEngine;
     4 public class RayScript:MonoBehaviour{
     5        public float speed;  // 外联速度值
     6        
     7        Ray ray;  //   射线
     8        RaycastHit hit;   //   射线的碰撞信息
     9        LayerMask mask;   //   用来接收LayerMask的value值;
    10 void Start(){
    11         // 1<<10打开第10层,当前射线只能检测到第十层上的碰撞体;
    12         // ~(1<<10)打开除10层以外的所有层;
    13         //~(1<<0)打开所以层, 或者不写LayerMask;
    14         // (1<<8)|(1<<10) 同时打开第8层和第10层;
    15         mask = ~(1 << LayerMask.NameToLayer ("Cube"));
    16     }
    17  void Update(){
    18        CubeMove();     //  调用CubeMove的方法
    19        
    20        // 从自身位置发射射线;
    21        // 发射一条射线,返回检测到的第一个物体;返回值为bool;
    22        ray=new Ray(transform.position,transform.forward);
    23        if(Physics.Raycast(ray,out hit,10)){
    24        // 给射线添加颜色,只能在scene场景中显示,game场景中不会显示;
    25        // 因为没有没有添加刚体,所以这里用collider来获取碰撞位置;
    26        Debug.DrawLine(transform.position,hit.collider.transform.position,Color.red);  //碰撞物体中心的位置;
    27  //    Debug.DrawLine(transform.position,hit.point,Color.red);       //  point是射线碰撞点的位置;
    28   
    29         //  可以用Debug来调试看看 本方法是否运行;
    30         Debug.Log("调试");
    31          }
    32          //
    33          #region
    34          //
    35          //  得到射线范围内的所有游戏物体;
    36          //返回的是一个游戏物体的数组;所以定义一个数组来接收得到的游戏物体;
    37          RaycastHit[]  hits=Physics.RaycastAll(ray,10);      //  这里代入的参数为射线和射线的距离;
    38          if(hits.Length>0){
    39          // 打印,检查是否运行了次方法;
    40         
    41          Debug.Log(hits.Length);
    42           }
    43          #endregion
    44          
    45          //
    46          #region
    47          //
    48         //  一般我们采用摄像头来发射线;
    49        if (Input.GetMouseButtonDown(0)) {
    50             //屏幕坐标转换成射线位置;
    51             Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    52             if (Physics.Raycast (ray, out hit)) {
    53                 //   缓动  Lerp
    54                 transform.position = Vector3.Lerp (transform.position, hit.point, Time.deltaTime);
    55             }
    56         }
    57          Ray ray2 = new Ray (transform.position, transform.forward);
    58         //   通过LayerMask.NameToLayer方法 来找寻 层名为 "Cube"的层数,打开第N值,射线只能检查到这一层;
    59         LayerMask mask = 1 << (LayerMask.NameToLayer ("Cube"));
    60         if (Physics.Raycast (ray2, out hit, 100,mask.value)) {
    61             Debug.Log (hit.collider.gameObject.name);
    62         }
    63          #endregion
    64        }
    65   void CubeMove(){
    66         float hor = Input.GetAxis ("Horizontal");
    67         float ver = Input.GetAxis ("Vertical");
    68 //        transform.position += transform.forward * Time.deltaTime * ver * speed;
    69 //        transform.position += transform.right * Time.deltaTime * hor * speed;
    70         // 恒等于
    71         transform.position += (transform.forward * ver + transform.right * hor) * speed * Time.deltaTime;
    72 }
    在Unity中每个GameObject都有Layer属性,  Layer一共有32层,0-7层,默认不可以编译,并且不能增加层数;
     
    GameObject的Layers(层):
         Layers通常用来被摄像机用来渲染部分场景,和灯光照射部分场景使用, 可以用来做射线检测时忽略一些collider或者CCollision时使用;
         
         编辑Layers:  
                如果Layers处于开启状态那么就能通过Layers找寻到GameObject;
          开启方法:
    1 LayerMask mask=1<< 你需要开启的Layers层;
      如果Layers处于关闭状态那么就可以在进行射线检测的时候忽略掉;
           关闭方法:
    1 LayerMask mask=0<<你需要关闭的Layers层;
    2 或者
    3 LayerMask mask=~(1<<你需要开启的Layers层);     //   ~表示取反

    例如:

    1 LayerMask mask = 1 << 2; 表示开启Layer2; 
    2 LayerMask mask = 0 << 5;表示关闭Layer5;    //  恒等于 LayerMask mask=~(1<<5);
    3 LayerMask mask = 1<<2|1<<8;表示开启Layer2和Layer8;
    4 LayerMask mask = 0<<3|0<<7;表示关闭Layer3和Layer7;   // 恒等于 LayerMask mask=~(1<<7);

    实战:

          场景中创建N(两个以上)个物体,鼠标可以选中任何物体,当鼠标选中为非地面时,选中的物体变为红色,之前选中的物体恢复为之前的颜色,鼠标点击到地面时,让之前选中的那个物体移动的当前点击的位置;

    分析: 在场景中创建一块地板,几个游戏物体,这样采用摄像头发射射线

     1 using System.Collections;
     2 using System.Collections.Generic;
     3 using UnityEngine;
     4 
     5 public class GameScript : MonoBehaviour {
     6 
     7     private GameObject selectedGameObject;  // 用来记录点中的物体
     8     private bool flag; // 标记当前是否选中了地面
     9     private Color seletedColor; // 记录当前选中物体的颜色;
    10     private RaycastHit hit;   // 碰撞信息;
    11 
    12     void Update () {
    13 
    14 
    15         if (Input.GetMouseButtonDown (0)) {
    16             // 从摄像头发射一条经过鼠标点击屏幕的点的射线,如果射线碰撞到碰撞体该方法返回true,否则false;
    17             if (Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit)) {
    18                 // 判断鼠标是否点击到地面
    19                 if (hit.collider.name == "Plane") {
    20                     flag = true;
    21             
    22                 } else {
    23             
    24                     flag = false;
    25 
    26                     // 判断是否选中物体
    27                     if (selectedGameObject) {
    28 
    29                         //  将前一个旋转的物体颜色恢复为原来的颜色;
    30                         selectedGameObject.GetComponent<MeshRenderer> ().material.color = seletedColor;
    31                     }
    32                     // 更新选中的物体; 
    33                     selectedGameObject = hit.collider.gameObject;
    34                     seletedColor = selectedGameObject.GetComponent<MeshRenderer> ().material.color;
    35             
    36                     selectedGameObject.GetComponent<MeshRenderer> ().material.color = Color.red;
    37                 }
    38             }
    39 
    40         }
    41             if (flag && selectedGameObject) {   // 当这一次鼠标选择地面,并且被选中物体存在;
    42             
    43                 Move (hit.point);
    44             }
    45     }
    46 
    47 
    48     void Move(Vector3 distination){
    49         // 判断两者之间的距离
    50         if (Vector3.Distance(selectedGameObject.transform.position,distination) <= 0.01f) {
    51 
    52             selectedGameObject.transform.position = distination;
    53         } else {
    54         
    55             // 不希望在Y轴上下移动
    56 
    57             Vector3 pos = selectedGameObject.transform.position;  // 自身的位置;
    58 
    59             pos = Vector3.Lerp (selectedGameObject.transform.position, distination, Time.deltaTime);
    60 
    61             // 限制Y轴移动
    62             selectedGameObject.transform.position = new Vector3 (pos.x, selectedGameObject.transform.position.y, 
    63             pos.z);
    64         
    65         }
    66     }
    67 }
  • 相关阅读:
    3.27上午
    3.24上午 补
    2017.3.27下午
    2017.3.27上午
    2017.3.24下午
    2017.3.24上午
    2017.3.23下午
    2017.3.23上午
    2017.3.22上午
    2017.3.21下午
  • 原文地址:https://www.cnblogs.com/fengjiulin110120/p/6732854.html
Copyright © 2020-2023  润新知