首页 > 代码库 > Ray射线

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 }

 

Ray射线