游戏中动态更换/更新寻路数据与光照贴图

861276679e675e0ad4e4c6474cd68c05.png

点击蓝字关注我哦

4255e6e70d4ebca5ad64f0b78b688ac1.png

9b1927b56f862542b3a2d9ff4c87f17c.jpeg

微信公众号:独立游戏之路
关注可了解更多的游戏开发知识与技巧。如果有问题或建议,欢迎+V留言;

170a34dd02d8dd0a8f7ee58c29ea53ef.gif

动态的改变寻路数据

今天,在开发的时候,想到一个问题,游戏场景后来可能会变,但是里面的寻路数据没法和场景数据一起更新下来,按照现在unity的习性,应该是每次烘焙路径信息都会保存在一个同场景名相同的文件夹下,全部打包替换似乎才能完成更新寻路信息.

7706551d88cdc0d925eaa8f5678b258d.png

但是我选中它的时候,却发现,下面可以将它打包成assetbundle,那么这就说明这就是一些数据而已,AI强依赖.发现它的名字叫NavMesh,然后尝试着在脚本中输入NavMesh,然后发现这个需要读取NavMeshData的数据,意外的简单,所以我将这个NavMesh的文件复制到Resources文件夹下,方便加载测试

06b6d8760571af641d2c35b25e2e04a1.png

然后又修改了场景布局,又烘焙了一次,然后同样的复制到Resources文件夹中.

public NavMeshData meshData;
public Transform endPoint;
public NavMeshAgent player;

// Start is called before the first frame update
void Start()
{ 
  meshData = Resources.Load<NavMeshData>("NavMeshDataNum1");
  NavMesh.AddNavMeshData(meshData); 
}

然后清除场景中的寻路信息,直接运行,发现可以运行.真的是好简单的方式!

a0a1e9aaca9a489aacb141b83b5ce280.png

学以致用 一步起飞


18aede83929389a2048e2100c48cfda5.gif

动态的改变关照贴图

如果你的项目里面,有两套或者两套以上的贴图,那么你就会需要用代码来切换贴图,但是,贴图和烘焙的寻路差不多,看起来像是和场景强关联的东西,但是事实上,光照贴图就是一张普通的2D贴图.

但是,有一点需要注意的是,光照贴图烘焙好了之后,即使你把它复制/移动到某个位置,然后你再重新烘焙,它还是会覆盖的,所以,我们应该是复制一份光照贴图.放到一个加载的文件夹中.

d3f3bdc8776ba9778d86ddedab27ecfe.png

我就是用了两个文件夹分别 存储了白天的贴图和晚上的贴图.方便看出效果,其实就是有没有平行光的区别.

这是烘焙好的光照贴图,如果场景足够复杂,不会只有这么一点的光照数据.

2b39ebedacaaa161119d64d6172814ad.png

里面的-0,-1代表就是这种类型的分布在几张贴图中,其实有的场景还会有shadowmash,但是我这里只是简单地搭建了一个简单的:

4e1cce79b4d1a06693ab1ace7a9243c3.png

然后,我们发现里面有个lightingData文件,然后尝试在代码中对它进行一系列的尝试.终于写出如下效果,都是在unity启动的时候动态更换的:

白天:

5b7e7a4a5ad13d41666e75388fdaf4d8.png

夜晚:

a1217d1af86a656b79710a7a505fae6f.png

看起来似乎没有问题,但是有一点需要注意的是,我们点击任何一个带有光照贴图的模型,查看光照贴图的信息:

8b444b6b5a20b9a729f52c019efe352c.png

发现这里还有一些光照数据还没有用到.那么这些数据如果不用的话,然后修改场景并加载光照贴图,也许会出现贴图和场景不吻合的情况.所以,我们需要将这些信息也记录下来.

首先是加载贴图的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class test_Loadmap_nav : MonoBehaviour
{ 
    LightmapData[] lightmaps;  
    int count = 2;

    // Start is called before the first frame update
    void Start()
    {
        Texture2D[] lightmapLight = new Texture2D[count];
        Texture2D[] lightmapDir = new Texture2D[count]; 
        lightmaps = new LightmapData[count];
        for (int i = 0; i < count; i++)
        {

            lightmapLight[i] = Resources.Load<Texture2D>("LightingData/test_Night/Lightmap-" + i.ToString() + "_comp_light");

            lightmapDir[i] = Resources.Load<Texture2D>("LightingData/test_Night/Lightmap-" + i.ToString() + "_comp_dir");

            LightmapData lightmapData = new LightmapData();

            lightmapData.lightmapColor = lightmapLight[i];
            lightmapData.lightmapDir = lightmapDir[i]; 
            lightmaps[i] = lightmapData;
        }
        LightmapSettings.lightmaps = lightmaps;


    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            Texture2D[] lightmapLight = new Texture2D[count];
            Texture2D[] lightmapDir = new Texture2D[count];
            lightmaps = new LightmapData[count];
            for (int i = 0; i < count; i++)
            { 
                lightmapLight[i] = Resources.Load<Texture2D>("LightingData/test_Night/Lightmap-" + i.ToString() + "_comp_light"); 
                lightmapDir[i] = Resources.Load<Texture2D>("LightingData/test_Night/Lightmap-" + i.ToString() + "_comp_dir"); 
                LightmapData lightmapData = new LightmapData(); 
                lightmapData.lightmapColor = lightmapLight[i];
                lightmapData.lightmapDir = lightmapDir[i]; 
                lightmaps[i] = lightmapData;
            }
            LightmapSettings.lightmaps = lightmaps;
        }
        if (Input.GetKeyDown(KeyCode.B))
        {
            Texture2D[] lightmapLight = new Texture2D[count];
            Texture2D[] lightmapDir = new Texture2D[count];
            lightmaps = new LightmapData[count];
            for (int i = 0; i < count; i++)
            {

                lightmapLight[i] = Resources.Load<Texture2D>("LightingData/test_Day/Lightmap-" + i.ToString() + "_comp_light"); 
                lightmapDir[i] = Resources.Load<Texture2D>("LightingData/test_Day/Lightmap-" + i.ToString() + "_comp_dir"); 
                LightmapData lightmapData = new LightmapData(); 
                lightmapData.lightmapColor = lightmapLight[i];
                lightmapData.lightmapDir = lightmapDir[i]; 
                lightmaps[i] = lightmapData;
            }
            LightmapSettings.lightmaps = lightmaps;
        }
    }
}

然后是记录静态模型中的光照贴图的信息:

using Newtonsoft.Json;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class RecordLightMapInfo : Editor
{
    [MenuItem("记录场景中的光照信息/开始生成json文件", false, 150)]
    public static void CreateLightmapJson()
    {

        GameObject Ground = null;

        int lightmapIndex = 1;
        float lightmapScale = 1;
        Vector4 lightmapScaleOffect;




        foreach (GameObject  item in Resources .FindObjectsOfTypeAll(typeof (GameObject)))
        {
            if (item.name.Equals("Ground"))
            {
                Ground = item;
            }
        }


        Root root = new Root();
        root.lightmapEles = new List<LightmapEle>();
        foreach (Transform item in Ground .transform .GetComponentsInChildren<Transform>(true ))
        {
            MeshRenderer renderer=  item.GetComponent<MeshRenderer>();

            LightmapEle lightmapEle = new LightmapEle
            {
                lightmapIndex = renderer.lightmapIndex,
                lightmapScale = renderer.scaleInLightmap,
                x = renderer.lightmapScaleOffset.x,
                y = renderer.lightmapScaleOffset.y,
                z = renderer.lightmapScaleOffset.z,
                w = renderer.lightmapScaleOffset.w
            };
            root.lightmapEles.Add(lightmapEle);
        }

        //foreach (var item in root .lightmapEles)
        //{
        //    Debug.Log(item.lightmapIndex);
        //    Debug.Log(item.lightmapScale);
        //    Debug.Log(item.lightmapScaleOffect);
        //}

        try
        {
          string s =  JsonConvert.SerializeObject(root);

            Debug.Log(s); 
        }
        catch (System.Exception)
        {

            throw;
        }
    }
}

[SerializeField]
public class Root
{
   public List<LightmapEle> lightmapEles;
}

[SerializeField]
public class LightmapEle
{
    public int lightmapIndex;
    public float lightmapScale;
    //由于不支持V4类型的,所以将拆分为4个
    public float x;
    public float y;
    public float z;
    public float w;
}

我将它写成编辑器插件,方便查看生成的信息,当我获取到这些信息之后,就可以在加载贴图的时候再附上去,就避免了一些光照贴图的错乱.

当然,如果需要上传到服务器,就把这些数据当初普通的热更新资源就好.


890c753c95184ab77e6d55513e2d2d1b.png

7261596f0dbd23a6e2642c2eb4ca7c26.png

学以致用 一步起飞


…END…

-

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值