3D游戏开发:射线检测实现子弹射击效果

3D游戏开发:射线检测实现子弹射击效果

关于射线检测实现子弹射击效果

1. 什么是射线照相检测?

射线检测是指通过发射射线来检测射线所击中的碰撞物体。 当发生碰撞并且满足条件时,返回值为true。

这些包括:

1.Physics.Linecast线性投影:从起始位置到结束位置的射线投影

2.Physics.Raycast(比较常用):显示与碰撞体碰撞的射线。 射线的方向和长度可以设置。

3.Physics.RaycastAll:发射射线并返回所有碰撞。 返回的是 RaycastHit[] 结构。

4.Physics.OverlapSphere:球形射线检测,返回球形半径内所有collider[],可用于判断拾取物品、手榴弹爆炸等触发。

2、实现子弹射击效果 1、思路

子弹在 3D 游戏场景中发射。 为了避免子弹穿透的问题,可以考虑使用射线检测,从枪口发射射线,确定枪械射程内的碰撞。 碰撞证明物体被击中,并且在碰撞的位置产生射线。 弹孔效果。

2、具体实施

这里我以第一人称射击游戏(FPS)中实现的射击效果为例

代码如下(示例):

public class Player_OpenFire : MonoBehaviour
{
    //屏幕中心点位置坐标
    private Vector3 point;
    //FPS人物相机
    public Camera fpscam;    
    //枪的射程
    private float GunRange = 20f; 
    void Start()
    {   
        //第一人称相机在不停的转动,但是准星的位置始终是在屏幕的中心点,这里获取到屏幕的中心点位置坐标
        point = new Vector3(Screen.width / 2, Screen.height / 2, 0);
    }
    void Update()
    {
       OpenFire();
    }
     void OpenFire() 
    {
        RaycastHit hit;
        //初始化一条从屏幕中心点发出的射线
        Ray ray = fpscam.ScreenPointToRay(point);
        //这里的5表示的是所在的层,因为我的项目中用了多个相机,所以需要分层处理。(读者可以根据自己的需要自行修改)
        if (Physics.Raycast(ray, out hit, GunRange, 5))
        {
           //这里进行的判断是防止枪口朝向脚下时,射线碰撞到玩家,玩家身上产生弹孔,造成自己打自己的情况。
            if (hit.collider.gameObject.tag=="Player")
            {
                return;
            }
            //这里我的弹孔特效是做成了预设体,放在Resources目录下进行动态加载,参数hit.point表示的是发生碰撞的坐标点是一个Vector3值
            GameObject bullet = Instantiate(Resources.Load("Bullet/BulletMark1"), hit.point, Quaternion.identity); 
            //在Unity三维坐标中的一个点包括三个值(三角朝向、法线值、UV值),这里用到了碰撞点的法线值
            bullet.transform.LookAt(hit.point - hit.normal);
             //把子弹特效设为碰撞到的物体的子物体
            bullet.transform.parent = hit.collider.transform;
             //我的预设体方向做的时候有问题,所以这里加载后再次修改了方向(读者根据需要自行修改这行代码)
            bullet.transform.Rotate(90, 0, 0);
             //我们让子弹移动一点点位置,调整子弹的特效能够显示在碰撞的物体上,避免遮盖的现象
            bullet.transform.Translate(Vector3.back * 0.01f);
              //为了方便演示这里设置弹孔特效一秒后自动销毁(读者可以用子弹对象池进行修改)
            Destroy(bullet, 1f);                      
        }
    }

3.扩展(FPS游戏进入游戏并开始游戏选择)(1)光线检测以及组件LineRenderer的使用

该脚本挂在枪的空物体上。 空对象必须包含LineRenderer和Outline组件Li,否则运行时会报错。

具体代码如下:

使用系统;

使用系统集合;

使用 System.Collections.Generic;

使用Unity引擎;

使用 UnityEngine.EventSystems;

使用UnityEngine.UI;

公共类 StartGame :MonoBehaviour

//获取LineRenderer组件

私有 LineRenderer 线;

//获取开始游戏按钮组件

公共按钮开始游戏;

//获取初始射线的终点坐标

Vector3端点;

// Start 在第一帧更新之前调用

无效开始()

行= this.GetComponent();

终点 = line.GetPosition(1);

//为按钮添加点击事件

startGame.onClick.AddListener(委托()

GameObject.Find("StartGame").SetActive(false);

});

无效更新()

//初始化一条射线unity 2d射线碰撞检测,从枪口位置向前方发射

Ray ray = new Ray(this.transform.position, this.transform.forward);

RaycastHit 命中;

//设置射线的碰撞距离为50米

if (Physics.Raycast(射线, out hit, 50))

//判断开始游戏按钮是否被触摸

if (hit.collider.tag == "StartGame")

//当触摸开始游戏按钮时,使按钮出现亮边框

startGame.GetComponent().enabled = true;

//绘制射线并将颜色设置为红色

Debug.DrawLine(transform.position, hit.point, Color.red);

//将世界坐标转换为本地坐标

line.SetPosition(1, line.transform.InverseTransformPoint(hit.point));

//点击鼠标左键会执行回调函数

if (Input.GetMouseButtonDown(0))

/*

* 这里我们用伪代码来简单描述一下具体可以实现的功能

* 1.可以实现上述的弹孔特效

* 2.可以跳转到游戏界面

* 3.也可以进入加载界面,通过异步加载的方式加载游戏(建议使用这种方式直接设计加载,如果游戏场景太大3D素材,会造成卡顿3D道具,而异步加载可以给用户带来一定的延迟)更好的游戏体验)

*/

ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler);

别的

//按钮在没有遇到碰撞体的情况下不能有亮边框

startGame.GetComponent().enabled = false;

//同时恢复射线原来的样子

line.SetPosition(1, 终点);

LineRenderer组件使用介绍:

LineRenderer组件可以显示光线

我这里没有使用世界空间坐标,是为了防止光线偏差造成的不切实际的效果。

LineRenderer中的坐标点可以编辑和添加,必须选择Loop才能使光线连续性更加真实。

射线线的宽度可以通过修改Width的值来实现。 默认值是1。我这里用0.01来达到线条而不是条的效果。

线条的颜色是可以改变的,但是要注意的是必须有材质才可以改变颜色,否则改变颜色是不行的。 多种材料中只有一种有效。

概述组件的使用

这里使用时默认不勾选,只有检测到射线时才会显示亮边框。

EffectColer根据场景色调和视觉效果来设置颜色并进行适当的匹配。

EffectDistance 设置宽度和高度。 不同的值显示不同的边框粗细。 值越大,厚度越大。

使用Graphic Alpha:使用Alpha值的图像具有更好的视觉效果unity 2d射线碰撞检测,并且占用更多的字节空间。

(2)优化策略

上面代码中之所以设置endPoint来存储初始光线位置,是为了节省光线,避免穿透。

line.SetPosition(1, line.transform.InverseTransformPoint(hit.point));

这段代码将射线的终点设置为碰撞点,这样射线在碰撞点之后就不会再出现,并且在离开碰撞对象后,射线可以通过endPoint点恢复到原来的形状,而不会造成碰撞固定长度。

这里提到的一些问题是出现的情况,读者可以自行尝试。

总结

这里特别说明一下:通过3D角色场景触发Canvas上的Button按钮,是光线检测与2D相结合。 这里的处理方法是给按钮添加一个BoxCollider碰撞体,实现碰撞和光线检测。

文章来源:https://blog.csdn.net/qq_37160769/article/details/109341055