Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明

这篇具有很好参考价值的文章主要介绍了Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎

1 前言

角色在地图上移动到岩石后面时,完全被岩石遮挡,玩家只能看到岩石。这逻辑看起来没问题,但并不是玩家想要看到的画面,玩家更希望关注角色的状态

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎

为了避免角色被遮挡,可以使用 Cinemachine Collider 功能,虚拟相机会自动避开障碍物,或者将角色和摄像机之间的障碍物做半透明处理,这两种方式的原理都是利用物理射线

这里使用障碍物半透明的方案,利用物理射线,检测角色和摄像机之间指定 Layer 的障碍物,改变其透明度,角色移动后,恢复其原本的透明度

2 设置 Layer

场景中的对象类型多种多样,我们仅希望岩石、树木等环境中的物体遮挡角色时,才改变其透明度。因此需要将对象分为不同的类型,利用 Unity 的 Layer 功能可以轻松实现该需求

Layer 定义哪些游戏对象可以与不同的功能以及彼此交互。它们主要有两种用途:由摄像机用来仅渲染场景的某一部分;由光源用来仅照亮场景的某些部分。但是,层也可以供射线投射用于选择性地忽略碰撞体或创建碰撞。更多信息请参阅文档:「https://docs.unity3d.com/cn/2021.2/Manual/Layers.html」

1 添加 Layer

这里偷个懒,只创建一个 Environment 层,就不再细分了

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎

2 分配 Layer

将 Free_Forest 及其子对象均设置为 Environment 层

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎

3 射线检测

在场景中从角色向摄像机投射一条射线,获取 Environment 层中所有命中的对象

脚本中获取 Environment 层的方式有两种

var layerMask = LayerMask.GetMask("Environment");

或者

var layerMask = 1 << LayerMask.NameToLayer("Environment");

通过角色和摄像机的位置计算出射线投射的方向和距离,利用 Physics.RaycastNonAlloc 来获取射线命中对象,相比 Physics.RaycastAll,此函数不会产生任何垃圾,毕竟在 FixedUpdate 中进行射线检测,应当尽量减少性能损耗

var size = Physics.RaycastNonAlloc(selfPosition, direction, this._raycastHits, rayDistance, layerMask);

获取命中对象中所有子节点的材质集合,和上一次命中的材质集合对比,改变其透明度

private void TransparentObjects()
{
    Vector3 selfPosition = transHead.position;
    Vector3 cameraPosition = _cameraTrans.position;
    var rayDistance = Vector3.Distance(selfPosition, cameraPosition);
    Vector3 direction = Vector3.Normalize(cameraPosition - selfPosition);
    Debug.DrawLine(selfPosition, cameraPosition, Color.red);

    var layerMask = LayerMask.GetMask("Environment");
    var size = Physics.RaycastNonAlloc(selfPosition, direction, this._raycastHits, rayDistance, layerMask);
    List<Material> materials = new List<Material>();
    for (int i = 0; i < size; i++)
    {
        var meshRenderers = this._raycastHits[i].collider.GetComponentsInChildren<MeshRenderer>();
        foreach (var variable in meshRenderers)
        {
            materials.AddRange(variable.materials);
        }
    }

    var transparentList = materials.Except(_materialList).ToList();
    var opaqueList = _materialList.Except(materials).ToList();
    foreach (var variable in transparentList)
    {
        MaterialTransparent.SetMaterialTransparent(true, variable, 0.22f);
    }

    foreach (var variable in opaqueList)
    {
        MaterialTransparent.SetMaterialTransparent(false, variable);
    }

    _materialList = materials;
}

4 更改透明度

由于性能等因素,默认情况下 3D 模型的材质是不支持更改透明度的。需要将材质的 Rendering Mode(对于内置渲染管线)或 Surface Type(对于 URP 或 HDRP)设置为 Transparent,才可以调整透明度相关的属性

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎

这里我们需要更改的属性主要为:

  • Surface Type:控制材质是否支持透明度,更多信息,请参阅文档: 「https://docs.unity3d.com/cn/Packages/com.unity.render-pipelines.high-definition@7.4/manual/Surface-Type.html」

    • Opaque:模拟没有光线穿透的全实体材质。

    • Transparent:模拟光线可以穿透的半透明材质,例如透明塑料或玻璃。选择 Transparent 会在 Surface Options 部分中显示更多属性,还会显示一个额外的 Transparency Inputs 部分

  • Blend:确定 GPU 如何将片元着色器的输出与渲染目标进行合并,更多信息请参阅文档: 「https://docs.unity3d.com/cn/current/Manual/SL-Blend.html」

通过脚本更改 Surface Type 和 Blend 属性:

public class MaterialTransparent
{
    private enum SurfaceType
    {
        Opaque,
        Transparent
    }

    private enum BlendMode
    {
        Alpha,
        Premultiply,
        Additive,
        Multiply
    }

    public static void SetMaterialTransparent(bool transparent, Material material, float alpha = 1)
    {
        if (transparent)
        {
            material.SetFloat("_Surface", (float)SurfaceType.Transparent);
            material.SetFloat("_Blend", (float)BlendMode.Alpha);
        }
        else
        {
            material.SetFloat("_Surface", (float)SurfaceType.Opaque);
        }

        SetupMaterialBlendMode(material);
        
        Color color = material.color;
        color.a = alpha;
        material.color = color;
    }

    private static void SetupMaterialBlendMode(Material material)
    {
        if (material == null)
        {
            return;
        }

        bool alphaClip = material.GetFloat("_AlphaClip") == 1;
        if (alphaClip)
        {
            material.EnableKeyword("_ALPHATEST_ON");
        }
        else
        {
            material.DisableKeyword("_ALPHATEST_ON");
        }

        SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");
        if (surfaceType == 0)
        {
            material.SetOverrideTag("RenderType", "");
            material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
            material.SetInt("_ZWrite", 1);
            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
            material.renderQueue = -1;
            material.SetShaderPassEnabled("ShadowCaster", true);
        }
        else
        {
            BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");
            switch (blendMode)
            {
                case BlendMode.Alpha:
                    material.SetOverrideTag("RenderType", "Transparent");
                    material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                    material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                    material.SetInt("_ZWrite", 0);
                    material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                    material.SetShaderPassEnabled("ShadowCaster", false);
                    break;
                case BlendMode.Premultiply:
                    material.SetOverrideTag("RenderType", "Transparent");
                    material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                    material.SetInt("_ZWrite", 0);
                    material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                    material.SetShaderPassEnabled("ShadowCaster", false);
                    break;
                case BlendMode.Additive:
                    material.SetOverrideTag("RenderType", "Transparent");
                    material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    material.SetInt("_ZWrite", 0);
                    material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                    material.SetShaderPassEnabled("ShadowCaster", false);
                    break;
                case BlendMode.Multiply:
                    material.SetOverrideTag("RenderType", "Transparent");
                    material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
                    material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                    material.SetInt("_ZWrite", 0);
                    material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                    material.SetShaderPassEnabled("ShadowCaster", false);
                    break;
            }
        }
    }
}

5 透明效果

最终效果如下图所示,角色走到岩石后面时,岩石呈现半透明状态

Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明,unity,游戏引擎文章来源地址https://www.toymoban.com/news/detail-800961.html

到了这里,关于Unity | 渡鸦避难所-5 | 角色和摄像机之间的遮挡物半透明的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Unity角色或摄像机移动和旋转的控制脚本

    该脚本挂载到需要被移动、旋转控制的物体身上,也可以之间挂在到摄像机上! 挂载到摄像机上可以实现第一人称视角控制! 挂载到物体身上,配合摄像机跟踪脚本可以实现,第三人称视角控制!  将角色控制脚本挂给摄像机即可! 以下是角色控制脚本: 将上面, 角色控

    2024年02月06日
    浏览(49)
  • Unity制作射击游戏案例01(控制角色+发射子弹+摄像机跟踪)

    //【业务逻辑】这个脚本用来1.控制物体移动旋转(WASD)、   2.发射子弹(空格键) //【程序逻辑2】 首先检测用户没有按下空格键 2.如果按下呢执行发射子弹函数    3.克隆子弹 4.让克隆的子弹往前跑 为子弹模板添加刚体,并且限制旋转 这个脚本需要挂在到摄像机,里面谈

    2024年02月06日
    浏览(57)
  • ue4/5 VR 设置VR视角的高度的方法,摄像机高度,控制角色自我感觉大小

    引用虚幻官方的原话: https://docs.unrealengine.com/4.27/zh-CN/SharingAndReleasing/XRDevelopment/VR/VRBestPractices/ 你可以在 世界场景设置 中找到 世界到米 变量,用它调整世界的缩放。这个数字的升降会使用户感觉自己在世界场景中相应地变大或缩小。假设你使用1虚幻单位=1厘米来构建内容,

    2024年02月03日
    浏览(53)
  • unity实现简单的摄像机震动效果(包括普通摄像机和虚拟摄像机)

    用代码实现摄像机简单的震动效果

    2024年02月12日
    浏览(44)
  • 【Unity 摄像机组件】Camera场景摄像机的认识

    OK 同学们好,本节课我们开始学习摄像机创建以及摄像机的属性。 CH3.3 PPT02 摄像机相机是玩家用来观看游戏场景世界的基本设备,当游戏运行的时候,游戏画面就是摄像机看到的画面。 PPT 3一个场景中可以有无数个摄像机,最终游戏运行的画面可能是很多个摄像机拼凑而成。

    2024年02月02日
    浏览(55)
  • Unity摄像机跟随

    将摄像机直接拖拽到被跟随的目标下面即可,这样摄像机永远在目标的后面 缺点: 屏幕旋转太平滑了 目标物体在屏幕上的位置永远不变 目标物体被销毁时总不能把摄像机也销毁了吧 先相机坐标和物体坐标做差,求得偏移量,在之后的每一帧里,将偏移量加上物体的坐标。

    2024年02月21日
    浏览(54)
  • Unity 摄像机

    摄像机分为两种  (1)透视摄像机 (2) 正交摄像机  一般3D游戏使用的透视多一点,2D游戏使用正交多一点。 相机参数 清除标记: (1)天空盒 (2)仅深度,类似于权重,优先级,深度大的覆盖住深度小的视线 例如 主相机显示的却不是当先视线,而是新相机的视线 ,主

    2023年04月21日
    浏览(47)
  • unity摄像机平滑移动旋转

    Unity中使用Vector3.SmoothDamp(平滑阻尼)方法进行跟随移动,可以使跟随看起来很平滑,而不显得突兀,最典型的示例就是相机平滑跟随角色移动。 SmoothDamp (current : Vector3, target : Vector3, ref currentVelocity : Vector3, smoothTime )  

    2024年02月11日
    浏览(52)
  • unity Camera(摄像机)介绍

    目录 一.摄像机类型 1.Perspective (透视摄像机) 2.Orthographic(正交摄像机) 二.摄像机属性 1.Clear Flags 2.Background 背景色 3.Culling Mask 剔除遮罩 4.Projection 投影 5.Field Of View   视野范围 6.Size 大小 7.Clipping Planes 裁剪屏幕 8.Viewport Rect 标准视图矩形 9.Depth 深度 10.Rendering Path 渲染路径

    2024年02月01日
    浏览(44)
  • unity摄像机跟随鼠标旋转

     float vertical = Input.GetAxis(\\\"Mouse X\\\") float horizontal = Input.GetAxis(\\\"Mouse Y\\\") 第二种 通过 计算坐标时只需要通过 Quaternion.Euler 来取得旋转四元数,以玩家为原点衍生一条(0,0,-1)的向量并乘上四元数以旋转至 Player 指向摄像机的方向,最后乘上 Distance ,即可得到摄像机相对玩家的偏移

    2024年02月11日
    浏览(68)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包