Unity 一些有用的碎片知识整理 之 四 (持续更新中...)

Unity 一些有用的碎片知识整理 之 四 (持续更新中...)

 

—— 系列文章链接

Unity 一些有用的碎片知识整理 之 一 点击可跳转链接

Unity 一些有用的碎片知识整理 之 二 点击可跳转链接

Unity 一些有用的碎片知识整理 之 三 点击可跳转链接


 

目录

Unity 一些有用的碎片知识整理 之 四 (持续更新中...)

五十二、Unity Android 端无需多余Android架包,直接 Unity 端代码,调起 Android 其他 APK

五十三、Unity 模拟实现磁铁的吸附效果

五十四、Unity中反转模型的法线(Normal)

五十五、Unity Mesh 或者 粒子系统绘制点云效果

五十六、鼠标点击屏幕,屏幕坐标转为世界坐标赋值给物体


 

五十二、Unity Android 端无需多余Android架包,直接 Unity 端代码,调起 Android 其他 APK


using UnityEngine;

public class CallApp : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    void OnGUI() {

        if (GUILayout.Button("LoadApk"))
        {
            openPackage("com.xan.test");
        }

    }

    void openPackage(string pkgName)
    {
        using (AndroidJavaClass jcPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject joActivity = jcPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                using (AndroidJavaObject joPackageManager = joActivity.Call<AndroidJavaObject>("getPackageManager"))
                {
                    using (AndroidJavaObject joIntent = joPackageManager.Call<AndroidJavaObject>("getLaunchIntentForPackage", pkgName))
                    {
                        if (null != joIntent)
                        {
                            joActivity.Call("startActivity", joIntent);
                        }
                    }
                }
            }
        }
    }
}

五十三、Unity 模拟实现磁铁的吸附效果

1、Physics.OverlapSphere 获取周边的吸附物体

2、rigidbody.AddExplosionForce 给对应的物体添加吸附力效果

3、效果图(在范围外的求吸附不了,添加阻力的球吸附较慢

4、实现步骤

1)给吸力物体添加脚本 Magnetic

2)给要被吸附的物体添加刚体和设置为指定吸附层

3)运行场景

5、实现代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Magnetic : MonoBehaviour
{
    public LayerMask m_MagneticLayers;//作用的层
    public Vector3 m_Position;//磁铁在物体的相对位置
    public float m_Radius; //磁铁作用的范围
    public float m_Force;//定义物体的力
    void FixedUpdate()
    {
        Collider[] colliders;
        Rigidbody rigidbody;
        colliders = Physics.OverlapSphere(transform.position + m_Position, m_Radius, m_MagneticLayers);
        foreach (Collider collider in colliders)
        {
            rigidbody = (Rigidbody)collider.gameObject.GetComponent(typeof(Rigidbody));
            if (rigidbody == null)
            {
                continue;
            }
            rigidbody.AddExplosionForce(m_Force * -1, transform.position + m_Position, m_Radius);
        }
    }
    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position + m_Position, m_Radius);//绘制一个球(有利于我们的观察)
    }
}


五十四、Unity中反转模型的法线(Normal)

有时候从3dmax或者Maya 导出的模型中的某些模型的法线反了,不是透明的模型,有了透明的感觉。

当然最好的方式就是让美工修改过来,重新导出。

在特别的情况下Unity也可以适当解决一下,通过修改 MeshFilter 的 mesh.triangles 的顺序,简单实现反转法线的效果。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InversionOfTheNormal : MonoBehaviour
{

    public GameObject target;

    // Start is called before the first frame update
    void Start()
    {
        ToInverseNormal();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    /// <summary>
    /// Mesh.vertices中,保存的是图形的顶点信息。
    /// Mesh.triangles中,保存的是对应于Mesh.vertices的顶点的索引。就是一个三角形在渲染中的三个顶点的顺序,所以Mesh.triangles的长度应该是3的倍数(Mesh.triangles的类型为int[])
    /// </summary>
    void ToInverseNormal() {

        int[] triangles = target.GetComponent<MeshFilter>().mesh.triangles;
        for (int i = 0; i < triangles.Length; i += 3)
        {
            // 交换第一点跟第三点的位置
            int t = triangles[i];
            triangles[i] = triangles[i + 2];
            triangles[i + 2] = t;
        }
        target.GetComponent<MeshFilter>().mesh.triangles = triangles;
    }

}

 

下面是参考的资料:

直接上干货

        Vector3[] normals = line.GetComponent<MeshFilter>().mesh.normals;
        for (int i = 0; i < normals.Length; i++) {
            normals[i] = -normals[i];
        }
        line.GetComponent<MeshFilter>().mesh.normals = normals;

        int[] triangles = line.GetComponent<MeshFilter>().mesh.triangles;
        for (int i = 0; i < triangles.Length; i += 3) {
            int t = triangles[i];
            triangles[i] = triangles[i + 2];
            triangles[i + 2] = t;
        }
        line.GetComponent<MeshFilter>().mesh.triangles = triangles;

刚开始想到做法线翻转,只想到了直接把法线取负值,就是第一段代码

        Vector3[] normals = line.GetComponent<MeshFilter>().mesh.normals;
        for (int i = 0; i < normals.Length; i++) {
            normals[i] = -normals[i];
        }
        line.GetComponent<MeshFilter>().mesh.normals = normals;

结果是这样子:

就是一个没有任何光线信息的样子(纯黑)

然后呢,我就一直百度,以求找到解决办法,百度了一个晚上,都是说,“为什么不到3dmax/MAYA中翻转法线呢”,你大爷的!

然后转战Google,5分钟后解决问题= =

        int[] triangles = line.GetComponent<MeshFilter>().mesh.triangles;
        for (int i = 0; i < triangles.Length; i += 3) {
            int t = triangles[i];
            triangles[i] = triangles[i + 2];
            triangles[i + 2] = t;
        }
        line.GetComponent<MeshFilter>().mesh.triangles = triangles;

加上了第二段代码之后,是这样子的:

 

(是的,我做的是卡通渲染的描边,没使用shader)

Mesh.vertices中,保存的是图形的顶点信息。
Mesh.triangles中,保存的是对应于Mesh.vertices的顶点的索引。就是一个三角形在渲染中的三个顶点的顺序,所以Mesh.triangles的长度应该是3的倍数(Mesh.triangles的类型为int[])
那为什么要交换第一点跟第三点的位置呢?


假如现在一个三角形是由P0、P1、P2,三个点组成的一个三角形。
那么,他的绘制的顺序应该是这样子的:

呈现一个逆时针的样子。图形学中(前几天看蓝宝书看到的,忘了是OpenGL中的还是说图形学中都是这样,请指正。Ps. 应该是逆时针吧)将拥有逆时针环绕的多边形为正面。
即上面这个三角形为正面
若我们从屏幕后面那个方向看这个三角形的话,那你看到的是他的背面。
当我们交换三角形的第一点跟第三点后,他的渲染顺序将变成这样子:

变成了从P2到P1再到P0的这么一个顺序。即这个三角形现在是一个顺时针环绕,我们看到的这个面,是他的背面。
在Unity中,默认的渲染是不会渲染背面的。
这样子就会出现刚才的这个效果


 

五十五、Unity Mesh 或者 粒子系统绘制点云效果

1、粒子系统绘制点云实现

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

public class DrawParticlePoint : MonoBehaviour {

    ParticleSystem particleSystem;                  // 整个粒子系统
    int pointCount;                                 // 粒子数目

    ArrayList list = new ArrayList();

    // Use this for initialization
    void Start()
    {
        particleSystem = GetComponent<ParticleSystem>();

        // 1. 读取数据
        list = ReadFile();

        //2.粒子显示
        DrawPointCloud(list);
       
    }

    ArrayList ReadFile()
    {
        // 提前将点云存成csv文件放在Assert/StreamingAssets文件夹下,文本的每行代表一个点,由点的x,y,z
        //csv文件存储数据,用逗号分隔,比较容易读取处理
        string path = (Application.streamingAssetsPath + "/" + "elephant.csv");
        FileInfo fInfo = new FileInfo(path);

        string s = "";
        StreamReader r;
        ArrayList vecList = new ArrayList();

        if (fInfo.Exists)
        {
            r = new StreamReader(path);
        }
        else
        {
            Debug.Log("文件不存在");
            return null;
        }
        // 点云数据存入队列
        while ((s = r.ReadLine()) != null)
        {
            string[] words = s.Split(","[0]);

            Vector3 xyz = new Vector3(float.Parse(words[0]), -float.Parse(words[1]), float.Parse(words[2])) * 10;
            vecList.Add(xyz);
        }

        return vecList;
    }

    ParticleSystem.Particle[] allParticles;         // 所有粒子的集合
    void DrawPointCloud(ArrayList drawList)
    {
        var main = particleSystem.main;
        main.startSpeed = 0.0f;                           // 设置粒子的初始速度为0
        main.startLifetime = 1000.0f;

        var pointCount = drawList.Count;
        allParticles = new ParticleSystem.Particle[pointCount];
        main.maxParticles = pointCount;
        particleSystem.Emit(pointCount);
        particleSystem.GetParticles(allParticles);
        for (int i = 0; i < pointCount; i++)
        {
            allParticles[i].position = (Vector3)drawList[i];    // 设置每个点的位置
            allParticles[i].startColor = Color.yellow;    // 设置每个点的rgb
            allParticles[i].startSize = 0.02f;                     
        }

        particleSystem.SetParticles(allParticles, pointCount);      // 将点云载入粒子系统
    }
}

2、Mesh 绘制实现

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

public class DrawMeshPointCloud : MonoBehaviour
{
    ArrayList list = new ArrayList();

    void Start()
    {
        // 1. 读取数据
        list = ReadFile();

        // 2. 渲染
        CreateMesh();
    }

    ArrayList ReadFile()
    {
        // 提前将点云存成csv文件放在Assert/StreamingAssets文件夹下,文本的每行代表一个点,由点的x,y,z
        //csv文件存储数据,用逗号分隔,比较容易读取处理
        string path = (Application.streamingAssetsPath + "/" + "elephant.csv");
        FileInfo fInfo = new FileInfo(path);

        string s = "";
        StreamReader r;
        ArrayList vecList = new ArrayList();

        if (fInfo.Exists)
        {
            r = new StreamReader(path);
        }
        else
        {
            Debug.Log("文件不存在");
            return null;
        }
        // 点云数据存入队列
        while ((s = r.ReadLine()) != null)
        {
            string[] words = s.Split(","[0]);

            Vector3 xyz = new Vector3(float.Parse(words[0]), -float.Parse(words[1]), float.Parse(words[2])) * 10;
            vecList.Add(xyz);
        }

        return vecList;
    }



    void CreateMesh()
    {
        int num = list.Count;

        GameObject pointObj = new GameObject();
        pointObj.name = "new";
        //处理大象朝向
        pointObj.transform.rotation = Quaternion.Euler(new Vector3(180, -180, 0));
        pointObj.AddComponent<MeshFilter>();
        pointObj.AddComponent<MeshRenderer>();
        Mesh meshNeed = new Mesh();
        Material mat = new Material(Shader.Find("Custom/VertexColor"));
        pointObj.GetComponent<MeshFilter>().mesh = meshNeed;
        pointObj.GetComponent<MeshRenderer>().material = mat;

        Vector3[] points = new Vector3[num];
        Color[] colors = new Color[num];
        int[] indecies = new int[num];
        for (int i = 0; i < num; ++i)
        {
            points[i] = (Vector3)list[i];
            indecies[i] = i;
            colors[i] = Color.white;
        }

        meshNeed.vertices = points;
        meshNeed.colors = colors;
        meshNeed.SetIndices(indecies, MeshTopology.Points, 0);

    }
}

3、数据存放到StreamingAssets文件夹下

(文件可以到链接下载 https://download.csdn.net/download/u014361280/11985614)

4、里面用到的shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/VertexColor" {
	SubShader{
		Pass{
		LOD 200

		CGPROGRAM
#pragma vertex vert
#pragma fragment frag

		struct VertexInput {
		float4 v : POSITION;
		float4 color: COLOR;
	};

	struct VertexOutput {
		float4 pos : SV_POSITION;
		float4 col : COLOR;
	};

	VertexOutput vert(VertexInput v) {

		VertexOutput o;
		o.pos = UnityObjectToClipPos(v.v);
		o.col = v.color;

		return o;
	}

	float4 frag(VertexOutput o) : COLOR{
		return o.col;
	}

		ENDCG
	}
	}

}

五十六、鼠标点击屏幕,屏幕坐标转为世界坐标赋值给物体

using UnityEngine;

public class ScreenPosition : MonoBehaviour
{
    public GameObject cube;
    // Start is called before the first frame update
    void Start()
    {
        
    }



    void Update()
    {
        // 获取物体的屏幕坐标,世界坐标->屏幕坐标
        Vector3 mousePos = Input.mousePosition;
        Debug.Log("x = " + mousePos.x + ", y = " + mousePos.y + ", z = " + mousePos.z);
        mousePos.z = 10;
        Vector3 wolrdPos = Camera.main.ScreenToWorldPoint(mousePos);
        Debug.Log("wolrdPosx = " + wolrdPos.x + ", wolrdPosy = " + wolrdPos.y + ", wolrdPosz = " + wolrdPos.z);
        cube.transform.position = wolrdPos;
    }


}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙魁XAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值