2016-03-31 01:00:00 puppet_master 阅读数 15190

从网上淘到了一套人物的模型,当时的心情是激动无比,掏出用的不熟练的3DMax折腾了半天,突然发现了一个蛋疼的事儿,所有的模型文件,材质名称,子材质,以及贴图全部用的是中文命名!!!虽然说是能跑,不过这个命名也忒不规范了,将模型,资源导入了Unity,关联产生的资源和材质名称也都是中文的!!!虽说是能用,不过心里总感觉有点儿别扭,然而要修改一系列的名称又太太太麻烦....于是我这个懒人就想到了写一个max脚本完成这个功能。

我搞到的素材在Max里面打开是酱紫的,赤果果的中文命名:

从文件名,模型名称,材质名称,子材质名称,贴图名称,贴图路径都是中文...

我的思路大概是这样:

1)max文件名称保持不变,仍然为中文,方便查找,而且这个无影响。

2.)手动修改模型名称为自己希望的英文名,根据材质名称 手动修改文件夹下的贴图名称为“模型名称 + 递增编号”

3)通过脚本,自动将材质名称改为模型名称,如果有多维子材质,自动将子材质重命名为 ”模型名称 + 递增编号“

4)通过脚本,自动将材质对应的贴图名称&贴图路径名改为当前路径下对应的贴图


好了,废话不多说了,上代码:

--更换材质包含的贴图的名称
--arg: mat 材质名
--arg: index standard material 中贴图的index 比如2是diffuse 7是Opacity
--arg  name 要修改的名称
function ChangeTexName mat index name = 
(
	tex = getSubTexmap mat index
	if tex == undefined then
	(
		print("Index " + (index as string)+ " isn't exist in mat, so skip it")
	)
	else
	(
		tex.name = name
		tex.filename = maxFilePath + tex.name + ".dds"
		print (name + " texture name changed ok")
	)
)

--遍历选择的物体
for obj in selection do 
(
	--修改材质名称为与对象名称一致
	obj.material.name = obj.name
	local num = getNumSubMtls obj.material
	if num == 0 then
	(
		ChangeTexName obj.material 2 obj.name
		ChangeTexName obj.material 7 obj.name
		print "main material changed ok"
	)
	else
	(
	
		local count = 1
		--处理多维子材质,将多维子材质按照对象名称+递增编号重命名
		for material in obj.material do
		(
			local tempName = obj.name
			append tempName (count as string)
			material.name = tempName
			count = count + 1
			--将index 2对应的diffuse贴图改名
			ChangeTexName material 2 tempName
			--将index 7对应的opecity贴图改名(如果不需要刻意去掉此行)
			ChangeTexName material 7 tempName
			print "sub material changed ok"
		)
	)
	print "Name Change OK"
)



详细的注释我写在了代码中,主要要注意的是一个地方,由于我的资源是使用了Diffuse和Opecity两个贴图,所以我这样写,如果要改名字的脚本是其他类型的贴图,只需要修改Index值就可以,index的对应关系如下:

下面看一下使用:

我首先根据材质编辑器中的贴图,将文件夹下的贴图修改名称,这时,模型会因为找不到贴图而变成白色:


然后,我们把模型名称修改一下,改成jingyingbaijianke,然后运行脚本:


由于最后一个贴图没有用Opecity贴图,所以跳过了修改。这时,我们的模型贴图又回来了,而我们打开材质编辑器,也可以看到,所有的中文都被我们修改成我们想要的命名了:



由于这些模型资源是一个蒙皮文件(max)+若干个动作文件(max)+贴图文件(dds)放在同一个目录下,所以我只需要第一次修改一次贴图文件名称,然后每次打开一个文件之后,重命名一下模型,运行一下脚本,所有材质,子材质,贴图名,贴图路径就都变成我们设定好的名称了,哇咔咔!!

比如我重新打开一个动作文件,开始时会提醒我贴图丢失,我们直接点击跳过,然后修改模型名,运行脚本,一切就都自动搞定了。然后我们就可以放心大胆的把它们导入到Unity中,最后再来张帅帅哒图片。


2019-02-27 00:33:21 weixin_38239050 阅读数 137

提示:选中右侧目录,可快速找到所需内容

以下笔者整理了Unity的3种截屏功能,分享给大家:

  • 截全屏
  • 屏幕指定范围截屏
  • 指定相机截屏

 

一、截全屏

使用方法:

将下方脚本挂载到物体上,Skode_StartCapture为截图方法。action_End 委托方法为截图完后执行。

using UnityEngine;
using System.Collections;
using System.IO;
using System;

public class Skode_ScreenCapture_Full : MonoBehaviour
{
    [Tooltip("是否启用截图后将图片保存到下面路径的功能")]
    public bool saveUseable = false;

    [Tooltip("存储路径")]
    public string savePath = "/sdcard/Skode";

    public GameObject[] shouldHideObj;

    /// <summary>
    /// 截图后的sprite
    /// </summary>
    [HideInInspector]
    public Sprite sprite;

    public void Skode_StartCapture(Action action_End = null)
    {
        CaptureStart();
        StartCoroutine(OnScreenShot(action_End));
    }

    public IEnumerator OnScreenShot(Action action_End = null)
    {
        //命名图片  202002261416527077
        string currentTime = string.Format("{0:yyyyMMddHHmmssffff}", DateTime.Now);

        //截屏
        Texture2D texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
        yield return new WaitForEndOfFrame();
        texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
        texture.Apply();

        sprite = Sprite.Create(texture,
            new Rect(0, 0, texture.width, texture.height),
            new Vector2(0.5f, 0.5f));

        if (saveUseable)
        {
            byte[] bytes = texture.EncodeToPNG();

            //若没路径 创建
            if (!Directory.Exists((savePath)))
            {
                Directory.CreateDirectory(savePath);
            }
            //保存路径
            string path_save = savePath + "/IMG_" + currentTime;
            //写入图片
            File.WriteAllBytes(path_save, bytes);
        }

        CaptureOver();
        action_End?.Invoke();
    }

    void CaptureStart()
    {
        if (shouldHideObj.Length > 0)
        {
            for (int i = 0; i < shouldHideObj.Length; i++)
            {
                shouldHideObj[i].SetActive(false);
            }
        }
    }

    void CaptureOver()
    {
        if (shouldHideObj.Length > 0)
        {
            for (int i = 0; i < shouldHideObj.Length; i++)
            {
                shouldHideObj[i].SetActive(true);
            }
        }
    }
}

 

 

二、屏幕指定范围截图

使用方法:

将下方脚本挂载到物体上,Skode_StartCapture为截图方法。action_End 委托方法为截图完后执行。

using System;
using System.Collections;
using System.IO;
using UnityEngine;

public class Skode_ScreenCapture_Rect : MonoBehaviour
{
    [Tooltip("是否启用截图后将图片保存到下面路径的功能")]
    public bool saveUseable = false;

    [Tooltip("存储路径")]
    public string savePath = "/sdcard/Skode";

    public GameObject[] shouldHideObj;

    /// <summary>
    /// 截图后的sprite
    /// </summary>
    [HideInInspector]
    public Sprite sprite;

    public void Skode_StartCapture(Rect mRect, Action action_End = null)
    {
        CaptureStart();
        StartCoroutine(CaptureByRect(mRect, action_End));
    }

    /// <summary>
    /// 根据一个Rect类型来截取指定范围的屏幕, 左下角为(0,0)
    /// 例:StartCoroutine(CaptureByRect(new Rect(100, 150, 1024, 768)));
    /// 从左下角的横坐标100,纵坐标150坐标开始截图,宽度1024,高度768
    /// </summary>
    public IEnumerator CaptureByRect(Rect mRect, Action action_End = null)
    {
        //等待渲染线程结束
        yield return new WaitForEndOfFrame();

        string currentTime = string.Format("{0:yyyyMMddHHmmssffff}", DateTime.Now);

        //初始化Texture2D, 大小可以根据需求更改
        Texture2D mTexture = new Texture2D((int)mRect.width, (int)mRect.height,
                                 TextureFormat.RGB24, false);
        //读取屏幕像素信息并存储为纹理数据
        mTexture.ReadPixels(mRect, 0, 0);
        //应用
        mTexture.Apply();

        sprite = Sprite.Create(mTexture,
    new Rect(0, 0, mTexture.width, mTexture.height),
    new Vector2(0.5f, 0.5f));

        if (saveUseable)
        {
            byte[] bytes = mTexture.EncodeToPNG();

            //若没路径 创建
            if (!Directory.Exists((savePath)))
            {
                Directory.CreateDirectory(savePath);
            }
            //保存路径
            string path_save = savePath + "/IMG_" + currentTime;
            //写入图片
            File.WriteAllBytes(path_save, bytes);
        }

        CaptureOver();
        action_End?.Invoke();
    }

    void CaptureStart()
    {
        if (shouldHideObj.Length > 0)
        {
            for (int i = 0; i < shouldHideObj.Length; i++)
            {
                shouldHideObj[i].SetActive(false);
            }
        }
    }

    void CaptureOver()
    {
        if (shouldHideObj.Length > 0)
        {
            for (int i = 0; i < shouldHideObj.Length; i++)
            {
                shouldHideObj[i].SetActive(true);
            }
        }
    }
}

 

 

三、指定相机截图

使用方法:

将下方脚本挂载到物体上,Skode_StartCapture为截图方法。action_End 委托方法为截图完后执行。

using System;
using System.Collections;
using System.IO;
using UnityEngine;

public class Skode_ScreenCapture_Cam : MonoBehaviour
{

    [Tooltip("是否启用截图后将图片保存到下面路径的功能")]
    public bool saveUseable = false;

    [Tooltip("存储路径")]
    public string savePath = "/sdcard/Skode";

    public GameObject[] shouldHideObj;

    /// <summary>
    /// 截图后的sprite
    /// </summary>
    [HideInInspector]
    public Sprite sprite;

    public void Skode_StartCapture(Camera targetCam, Rect mRect, Action action_End = null)
    {
        CaptureStart();
        StartCoroutine(CaptureByCamera(targetCam, mRect, action_End));
    }

    /// <summary>
    /// 指定相机截图
    /// </summary>
    /// <param name="mCamera">M camera.要被截屏的相机</param>
    /// <param name="mRect">M rect. 截屏的区域</param>
    /// 例:Skode_StartCapture(Camera.main,new Rect(0,0, Screen.width, Screen.height))
    /// <param name="mFileName">M file name.</param>
    private IEnumerator CaptureByCamera(Camera mCamera, Rect mRect, Action action_End = null)
    {
        //等待渲染线程结束
        yield return new WaitForEndOfFrame();

        string currentTime = string.Format("{0:yyyyMMddHHmmssffff}", DateTime.Now);

        //初始化RenderTexture   深度只能是【0、16、24】截不全图请修改
        RenderTexture mRender = new RenderTexture((int)mRect.width, (int)mRect.height, 16);
        //设置相机的渲染目标
        mCamera.targetTexture = mRender;
        //开始渲染
        mCamera.Render();
        //激活渲染贴图读取信息
        RenderTexture.active = mRender;
        Texture2D mTexture = new Texture2D((int)mRect.width, (int)mRect.height, TextureFormat.RGB24, false);
        //读取屏幕像素信息并存储为纹理数据
        mTexture.ReadPixels(mRect, 0, 0);
        //应用
        mTexture.Apply();
        //释放相机,销毁渲染贴图
        mCamera.targetTexture = null;
        RenderTexture.active = null;
        Destroy(mRender);

        sprite = Sprite.Create(mTexture,
new Rect(0, 0, mTexture.width, mTexture.height),
new Vector2(0.5f, 0.5f));

        if (saveUseable)
        {
            byte[] bytes = mTexture.EncodeToPNG();

            //若没路径 创建
            if (!Directory.Exists((savePath)))
            {
                Directory.CreateDirectory(savePath);
            }
            //保存路径
            string path_save = savePath + "/IMG_" + currentTime;
            //写入图片
            File.WriteAllBytes(path_save, bytes);
        }

        CaptureOver();
        action_End?.Invoke();
    }

    void CaptureStart()
    {
        if (shouldHideObj.Length > 0)
        {
            for (int i = 0; i < shouldHideObj.Length; i++)
            {
                shouldHideObj[i].SetActive(false);
            }
        }
    }

    void CaptureOver()
    {
        if (shouldHideObj.Length > 0)
        {
            for (int i = 0; i < shouldHideObj.Length; i++)
            {
                shouldHideObj[i].SetActive(true);
            }
        }
    }
}

 

2019-04-12 22:46:27 qq_20413523 阅读数 32

UnityShader入门 首先还是要多谢shader女神乐乐的书  以及论坛上的各个博文 

扒了一天 总算是对shader有了一个初步的了解 

 根据程序一通百通的原理  

为了方便理解 自己做了关系对应  

shader编程  其实就i跟我们平时写c#编程一样 

不同的是 里面声明函数 以及变量的方式 在shader里面改变了一下 

1   shader的脚本名称  这是为了方便管理 自己尽量去分类 

Shader "MyShade/shadertest"      可以随意明名   斜杠表示分层关系 

 

2 定义属性   c#里面有公共变量  私有变量   而shader里面呢  是这样的  

Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor("MainColor",color)=(1,1,1,1)
    }

Properties   是所有属性设置     当前shader脚本里面所要用到的变量 都要在这里去定义  (萌新入门级的理解 如有不妥,请指出)

例如 {}里面第一行  设置了一个texture     _MainTex  是我们在下面函数中要拿来用的  相当于c#的变量  

"Texture"   这是 为了方便界面话调试   会在控制面板上显示 (找到材质球  你改变"Texture"的字符串会发现控制面板上的会跟着变化)  2D是表示 这是一个2的阶数的图片信息   例如  2*2    64*64 256*256大小的图片   "white"   代表的是默认值  白色    值的话是(1,1,1,1),   方便渲染  不会影响其他图形的叠加

3 SubShader (shader主体,shader的实现)   这里就相当于我们acn#里's面的h函数(方法了)   

 

Tags 是一个标签   设备会读取这些标签 标签的信息是 什么时候调用该shader进行渲染

lod    全名Level of Detail    可以根据设备性能进行画面调整

pass  shader的实现     可以有多个pass     每个pass相当于通道   因为市面上显卡设备众多, 有好的 差的  兼容 支持不一样 所以 要准备多个pass  以便去适配    当程序运行时候  有且只有一个pass执行  

暂且更新到此    还有下文  待有时间继续更新 

 

 

 

 

 

没有更多推荐了,返回首页