Unity杂项2018篇

本文汇集了Unity开发中遇到的各种问题及解决方案,包括Raycast穿透、NavMesh数据导出、自动保存场景、解决Mesh顶点色问题等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/////////

The problem is that I have a button that sits above the clay seal and it is being blocked by the Rect of the scroll picture. Since the scroll moves I cant exactly parent the button to it. So I'm asking if there is a way to ignore the alpha on the scroll and make ray casts pass trough it. I already have a script that uses a box collider and implements the ICanvasRaycastFilter but it doesnt seem to work with the unity scroll rect for some reason. Here is the full script :

using UnityEngine;
using System.Collections;

public class RaycastFilter : MonoBehaviour, ICanvasRaycastFilter
{
    private RectTransform rectTransform;
    private new BoxCollider2D collider2D;

    public void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
        collider2D = GetComponent<BoxCollider2D>();
    }

    public bool IsRaycastLocationValid(Vector2 screenPosition, Camera raycastEventCamera) //uGUI callback
    {
        // If we don't have a collider we will simply use the big button box. //TODO: make custom exception for this.
        if (collider2D == null)
            return true;

        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPosition, raycastEventCamera, out localPoint);

        Vector2 pivot = rectTransform.pivot - new Vector2(0.5f, 0.5f);

        Vector2 pivotScaled = Vector2.Scale(rectTransform.rect.size, pivot);

        Vector2 realPoint = localPoint + pivotScaled;

        Rect colliderRect = new Rect(
            collider2D.center.x - collider2D.size.x / 2,
            collider2D.center.y - collider2D.size.y / 2,
            collider2D.size.x,
            collider2D.size.y); // TODO: CACHE

        bool containsRect = colliderRect.Contains(realPoint);

        return containsRect;
    }
}

In case anyone stumbles upon this like I did, here's my solution for raycasting sprites through alpha in a 3D world.

First, transform your hit point to the local space of the sprite using an inverse transform. Then, add the pivot point of your sprite. Since it is expressed in pixels, dividing it by the pixels per unit gives you the correct offset. To get the UV values of that local point, divide it by the sprite bounds size. This will give you values between 0 and 1. Since our coordinate system is Y up and a texture is Y down, we'll have to invert our Y value. Now it's easy to read the correct pixel. Multiply the UV with the texture width and height.

private GameObject Raycast(Vector2 screenPos)
    {
        Ray ray = new Ray(_camera.ScreenToWorldPoint(screenPos), _camera.transform.forward);

        var result = Physics.RaycastAll(ray, float.MaxValue).ToList().OrderByDescending(h => h.distance); //inverse raycast

        foreach (var hit in result)
        {
            var rend = hit.transform.GetComponent<SpriteRenderer>();
            if (rend == null)
                continue;

            Vector2 localPos = hit.transform.InverseTransformPoint(hit.point);
            localPos += rend.sprite.pivot / rend.sprite.pixelsPerUnit;

            Vector2 uv = localPos / rend.sprite.bounds.size;
            uv.y = 1f - uv.y;

            Texture2D tex = rend.sprite.texture as Texture2D;

            int x = (int)(uv.x * tex.width);
            int y = (int)(uv.y * tex.height);
            var pix = tex.GetPixel(x, y);

            if (pix.a > 0)
            {
                return hit.transform.gameObject;
            }
        }

        return null;
    }

//////////////////////////////////////

Go to Edit => Preferences. In the Preferences window go to GI Cache Tab. And then click clean cache.

And Woila! your Cache is removed.

If you're looking to clear your Global Illumination cache, then above does it.

GI ---> Global Illumination

https://docs.unity3d.com/$$anonymous$$anual/GICache.html

GI cache The GI cache is an internal data cache that the Unity Editor uses to store intermediate files when precomputing lighting data for Realtime Global Illumination (deprecated), lightmaps , Light Probes , and Reflection Probes . By storing this data in a cache, Unity can speed up subsequent precomputations.

The cache is shared between all Unity projects on the computer, so projects with the same content and lightmapping backend can share the files.

You can manage the size, location, and compression of the cache using the GI Cache preferences. For more information, see the Preferences documentation.

////////////////////////////////////////////////////////////

Caching.ClearCache() doesn't work because this method clears the caches that reside in the Application.temporaryCachePath, while the catalog_shared.json and catalog_shared.hash are stored under Application.persistentDataPath.

//////导出NavMesh 到MeshFilter//////

[MenuItem("Tools/Create Mesh from NavMesh")]

static void ExportNavMesh()
{
NavMeshTriangulation triangulatedNavMesh = NavMesh.CalculateTriangulation();
var clone = new GameObject("BakedNav01", typeof(MeshFilter));
var clonecomp = clone.GetComponent<MeshFilter>();
clonecomp.sharedMesh = new Mesh();
clonecomp.sharedMesh.name = "exported";
clonecomp.sharedMesh.vertices = triangulatedNavMesh.vertices;
clonecomp.sharedMesh.triangles = triangulatedNavMesh.indices;
clonecomp.sharedMesh.RecalculateBounds();
clonecomp.sharedMesh.RecalculateNormals();
clonecomp.sharedMesh.RecalculateTangents();
MeshUtility.Optimize(clonecomp.sharedMesh);
clone.AddComponent<MeshRenderer>();
var mat = new Material(Shader.Find("Standard"));
clone.GetComponent<MeshRenderer>().sharedMaterial = mat;
SaveMesh(clonecomp.sharedMesh, clonecomp.sharedMesh.name, true);
}
public static void SaveMesh (Mesh mesh, string name, bool makeNewInstance) {
string path = EditorUtility.SaveFilePanel("Save Separate Mesh Asset", "Assets/", name, "asset");
if (string.IsNullOrEmpty(path)) return;
path = FileUtil.GetProjectRelativePath(path);
Mesh meshToSave = (makeNewInstance) ? Object.Instantiate(mesh) as Mesh : mesh;
AssetDatabase.CreateAsset(meshToSave, path);
AssetDatabase.SaveAssets();
}

///////////群体寻路时物体之间拥挤、碰撞问题/////////////

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

public class NewBehaviourScript : MonoBehaviour

{

    public GameObject targetGo;

    public List<NavMeshAgent> agents;

    void Start()

    {

        StartCoroutine( IUpdate() );

    }

    IEnumerator IUpdate()

    {

        while ( true )

        {

            // 按下鼠标,开始寻路

            if ( Input.GetMouseButtonDown( 0 ) )

            {

                Ray ray = Camera.main.ScreenPointToRay( Input.mousePosition );

                RaycastHit hitInfo;

                if ( Physics.Raycast( ray, out hitInfo ) )

                {

                    targetGo.transform.position = hitInfo.point + new Vector3(0, 0.5f, 0);

                    for ( int i = 0; i < agents.Count; i++ )

                    {

                        agents[i].GetComponent<NavMeshObstacle>().enabled = false;

                        yield return null;      // 这里必须要等待一帧,否则 下一次寻路就会错位。

                        agents[i].enabled = true;

                        agents[i].SetDestination( hitInfo.point );

                    }

                }

            }

            yield return null;

            // 动态设置优先级

            if ( agents[0].enabled )

            {

                agents.Sort( ( x, y ) =>

                {

                    if ( x.enabled && y.enabled )

                    {

                        return x.remainingDistance.CompareTo( y.remainingDistance );

                    }

                    return 0;

                } );

                for ( int i = 0; i < agents.Count; i++ )

                {

                    agents[i].avoidancePriority = 50 + i;

                }

            }

            // 判断到达结束点 打开障碍组件

            for ( int i = 0; i < agents.Count; i++ )

            {

                if ( agents[i].enabled && agents[i].remainingDistance > 0.5f && agents[i].remainingDistance < 0.8f )

                {

                    agents[i].Stop();

                    agents[i].enabled = false;

                    agents[i].GetComponent<NavMeshObstacle>().enabled = true;

                }

            }

        }

    }

}

/////////////////////////NavMeshSurface组件/////////////////////////

using UnityEngine;
using UnityEngine.AI;
 
/// <summary>
/// 动态实时计算导航网格
/// </summary>
public class RuntimeBake : MonoBehaviour
{
    private static NavMeshSurface surface;//NavMeshSurface组件
 
    private void Awake()
    {
        surface = GetComponent<NavMeshSurface>();
    }
 
    /// <summary>
    /// 计算导航网格
    /// </summary>
    public static void Bake()
    {
        surface.BuildNavMesh();
    }
}
五:将NavMesh数据导出为obj文件
Unity提供了相关的接口:NavMesh.CalculateTriangulation,利用这个接口能够获取到NavMesh的数据,顶点以及顶点索引,根据这些信息就可以画出模型来。
下面的代码是用来把NavMesh数据导出为一个obj文件,这样就可以将NavMesh数据给服务器使用,导出之后直接拖到Unity中也可以看到NavMesh的形状

using UnityEngine;
using UnityEditor;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEngine.AI;
 
/// <summary>
/// 导出NavMesh数据给服务器使用
/// </summary>
public class ExportNavMesh : MonoBehaviour
{
    [MenuItem("Tool/Export NavMesh")]
    public static void Export()
    {
        NavMeshTriangulation tmpNavMeshTriangulation = NavMesh.CalculateTriangulation();
 
        //新建文件
        string tmpPath = Application.dataPath + "/" + SceneManager.GetActiveScene().name + ".obj";
        StreamWriter tmpStreamWriter = new StreamWriter(tmpPath);
 
        //顶点
        for (int i = 0; i < tmpNavMeshTriangulation.vertices.Length; i++)
        {
            tmpStreamWriter.WriteLine("v  " + tmpNavMeshTriangulation.vertices[i].x + " " + tmpNavMeshTriangulation.vertices[i].y + " " + tmpNavMeshTriangulation.vertices[i].z);
        }
 
        //tmpStreamWriter.WriteLine("g pPlane1");
        tmpStreamWriter.WriteLine("Plane1");
 
        //索引
        for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;)
        {
            tmpStreamWriter.WriteLine("f " + (tmpNavMeshTriangulation.indices[i] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 1] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 2] + 1));
            i += 3;
        }
 
        tmpStreamWriter.Flush();
        tmpStreamWriter.Close();
 
        Debug.Log("导出NavMesh成功");
    }
}
/////////////////////NavMesh数据导出为obj文件////////////////////////////////

using UnityEngine;
using UnityEditor;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEngine.AI;
 
/// <summary>
/// 导出NavMesh数据给服务器使用
/// </summary>
public class ExportNavMesh : MonoBehaviour
{
    [MenuItem("Tool/Export NavMesh")]
    public static void Export()
    {
        NavMeshTriangulation tmpNavMeshTriangulation = NavMesh.CalculateTriangulation();
 
        //新建文件
        string tmpPath = Application.dataPath + "/" + SceneManager.GetActiveScene().name + ".obj";
        StreamWriter tmpStreamWriter = new StreamWriter(tmpPath);
 
        //顶点
        for (int i = 0; i < tmpNavMeshTriangulation.vertices.Length; i++)
        {
            tmpStreamWriter.WriteLine("v  " + tmpNavMeshTriangulation.vertices[i].x + " " + tmpNavMeshTriangulation.vertices[i].y + " " + tmpNavMeshTriangulation.vertices[i].z);
        }
 
        //tmpStreamWriter.WriteLine("g pPlane1");
        tmpStreamWriter.WriteLine("Plane1");
 
        //索引
        for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;)
        {
            tmpStreamWriter.WriteLine("f " + (tmpNavMeshTriangulation.indices[i] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 1] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 2] + 1));
            i += 3;
        }
 
        tmpStreamWriter.Flush();
        tmpStreamWriter.Close();
 
        Debug.Log("导出NavMesh成功");
    }
}
////////////////////////////////////绘制出NavMesh导航路径////////////////////

using UnityEngine;
using UnityEngine.AI;
 
public class Player : MonoBehaviour
{
    private NavMeshAgent agent;//导航组件
    private LineRenderer lr;//LineRenderer组件
 
    public Transform foodTrans;//食物位置
 
    private void Awake()
    {
        agent = GetComponent<NavMeshAgent>();
        lr = GetComponent<LineRenderer>();
 
        //初始化LineRenderer
        InitLine();
    }
 
    /// <summary>
    /// 初始化LineRenderer
    /// </summary>
    private void InitLine()
    {
        lr.startColor = Color.red;
        lr.endColor = Color.red;
        lr.startWidth = 0.1f;
        lr.endWidth = 0.1f;
        lr.numCapVertices = 90;
        lr.numCornerVertices = 90;
        lr.material = new Material(Shader.Find("Sprites/Default"));
    }
 
    /// <summary>
    /// 更新LineRenderer
    /// </summary>
    private void UpdateLineRenderer()
    {
        lr.positionCount = agent.path.corners.Length;
        lr.SetPositions(agent.path.corners);
    }
 
    private void Update()
    {
        //设置导航位置
        agent.SetDestination(foodTrans.position);
 
        //更新LineRenderer
        UpdateLineRenderer();
    }
}

///////////////////////实现超出屏幕的敌人/队友位置显示//////////////////////

using UnityEngine;
using UnityEngine.UI;
 
public class Test : MonoBehaviour
{
    public GameObject go;//物体
    public GameObject targetGo;//目标物体
 
    public Image labelUI_img;//标记UI的Image组件
 
    private float labelUI_HalfWidth;//标记UI一半的宽
    private float labelUI_HalfHeight;//标记UI一半的高
    private Vector2 v3;//v3的坐标
    private Vector2 v4;//v4的坐标
 
    private void Awake()
    {
        labelUI_HalfWidth = labelUI_img.GetComponent<RectTransform>().rect.width / 2;
        labelUI_HalfHeight = labelUI_img.GetComponent<RectTransform>().rect.height / 2;
    }
 
    private void Update()
    {
        //判断标记UI的显示与隐藏
        if (IsInView(targetGo.transform.position))
        {
            labelUI_img.enabled = false;
        }
        else
        {
            labelUI_img.enabled = true;
        }
 
        //设置标记UI的显示位置
        GetV3AndV4(out v3, out v4);
        labelUI_img.transform.localPosition = CalculateCrossPoint(go.transform.position, targetGo.transform.position, v3, v4);
    }
 
    /// <summary>
    /// 得到v3,v4的值
    /// </summary>
    private void GetV3AndV4(out Vector2 v3, out Vector2 v4)
    {
        Vector2 v1 = Camera.main.WorldToScreenPoint(go.transform.position);
        Vector2 v2 = Camera.main.WorldToScreenPoint(targetGo.transform.position);
        Vector2 offset = v2 - v1;
        if (Mathf.Abs(offset.x) > Mathf.Abs(offset.y))
        {
            if (offset.x > 0)
            {
                v3 = new Vector2(Screen.width - labelUI_HalfWidth, 0);
                v4 = new Vector2(Screen.width - labelUI_HalfWidth, Screen.height);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, -135);
            }
            else
            {
                v3 = new Vector2(0 + labelUI_HalfWidth, 0);
                v4 = new Vector2(0 + labelUI_HalfWidth, Screen.height);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, 45);
            }
        }
        else
        {
            if (offset.y > 0)
            {
                v3 = new Vector2(0, Screen.height - labelUI_HalfHeight);
                v4 = new Vector2(Screen.width, Screen.height - labelUI_HalfHeight);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, -40);
            }
            else
            {
                v3 = new Vector2(0, 0 + labelUI_HalfHeight);
                v4 = new Vector2(Screen.width, 0 + labelUI_HalfHeight);
                labelUI_img.transform.rotation = Quaternion.Euler(0, 0, -220);
            }
        }
    }
 
    /// <summary>
    /// 给定四个点,求两条线段的交点(y=a1x+b1,y=a2x+b2)
    /// v1,v2是物体与目标物体的位置,v3,v4是屏幕左上,左下,右上,右下中的两个点
    /// </summary>
    private Vector2 CalculateCrossPoint(Vector3 v1, Vector3 v2, Vector2 v3, Vector2 v4)
    {
        v1 = Camera.main.WorldToScreenPoint(v1);
        v2 = Camera.main.WorldToScreenPoint(v2);
 
        float a1 = 0, b1 = 0, a2 = 0, b2 = 0;
        Vector2 crossPoint = Vector2.zero;
 
        if (v1.x != v2.x)
        {
            a1 = (v1.y - v2.y) / (v1.x - v2.x);
        }
        if (v1.y != v2.y)
        {
            b1 = v1.y - v1.x * (v1.y - v2.y) / (v1.x - v2.x);
        }
 
        if (v3.x != v4.x)
        {
            a2 = (v3.y - v4.y) / (v3.x - v4.x);
        }
        if (v3.y != v4.y)
        {
            b2 = v3.y - v3.x * (v3.y - v4.y) / (v3.x - v4.x);
        }
 
        if (a1 == a2 && b1 == b2)
        {
            Debug.LogWarning("两条线共线,没有交点");
            return Vector2.zero;
        }
        else if (a1 == a2)
        {
            Debug.LogWarning("两条线平行,没有交点");
            return Vector2.zero;
        }
        else
        {
            //交点的x和y坐标
            //(v3与v4需要进行特殊判定处理)
            float x = 0;
            float y = 0;
            if (v3.x == v4.x)
            {
                if (v3.x == 0)
                {
                    x = 0;
                    y = b1;
                }
                else
                {
                    x = v3.x;
                    y = x * a1 + b1;
                }
            }
            else if (v3.y == v4.y)
            {
                if (v3.y == 0)
                {
                    y = 0;
                    x = -b1 / a1;
                }
                else
                {
                    y = v3.y;
                    x = (y - b1) / a1;
                }
            }
            else
            {
                x = (b2 - b1) / (a1 - a2);
                y = a1 * (b2 - b1) / (a1 - a2) + b1;
            }
 
            //限定x和y的范围
            x = Mathf.Clamp(x, 0, Screen.width);
            y = Mathf.Clamp(y, 0, Screen.height);
 
            crossPoint = new Vector2(x, y);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(GameObject.Find("Canvas").GetComponent<RectTransform>(),
                crossPoint, null, out crossPoint);
            return crossPoint;
        }
    }
 
    /// <summary>
    /// 是否在指定相机的视野范围内
    /// </summary>
    /// <param name="worldPos">物体世界坐标</param>
    /// <returns>是否在相机视野范围内</returns>
    public bool IsInView(Vector3 worldPos)
    {
        Transform camTransform = Camera.main.transform;
        Vector2 viewPos = Camera.main.WorldToViewportPoint(worldPos);
 
        //判断物体是否在相机前面  
        Vector3 dir = (worldPos - camTransform.position).normalized;
        float dot = Vector3.Dot(camTransform.forward, dir);
 
        if (dot > 0 && viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

/////////////////////////////////Editor////////////////////////////////////////

EditorApplication.ExecuteMenuItem("File/Save Project") 

using UnityEngine;
using UnityEditor;
using System;
 
public class AutoSave : EditorWindow {
 
	private bool autoSaveScene = true;
	private bool showMessage = true;
	private bool isStarted = false;
	private int intervalScene;	
	private DateTime lastSaveTimeScene = DateTime.Now;
 
	private string projectPath = Application.dataPath;
	private string scenePath;
 
	[MenuItem ("Window/AutoSave")]
	static void Init () {
		AutoSave saveWindow = (AutoSave)EditorWindow.GetWindow (typeof (AutoSave));
		saveWindow.Show();
	}
 
	void OnGUI () {	
		GUILayout.Label ("Info:", EditorStyles.boldLabel);
		EditorGUILayout.LabelField ("Saving to:", ""+projectPath);
		EditorGUILayout.LabelField ("Saving scene:", ""+scenePath);
		GUILayout.Label ("Options:", EditorStyles.boldLabel);
		autoSaveScene = EditorGUILayout.BeginToggleGroup ("Auto save", autoSaveScene);
		intervalScene = EditorGUILayout.IntSlider ("Interval (minutes)", intervalScene, 1, 10);
		if(isStarted) {
			EditorGUILayout.LabelField ("Last save:", ""+lastSaveTimeScene);
		}
		EditorGUILayout.EndToggleGroup();
		showMessage = EditorGUILayout.BeginToggleGroup ("Show Message", showMessage);
		EditorGUILayout.EndToggleGroup ();
	}
 
 
	void Update(){
		scenePath = EditorApplication.currentScene;
		if(autoSaveScene) {
			if(DateTime.Now.Minute >= (lastSaveTimeScene.Minute+intervalScene) || DateTime.Now.Minute == 59 && DateTime.Now.Second == 59){
				saveScene();
			}
		} else {
			isStarted = false;
		}
 
	}
 
	void saveScene() {
		EditorApplication.SaveScene(scenePath);
		lastSaveTimeScene = DateTime.Now;
		isStarted = true;
		if(showMessage){
			Debug.Log("AutoSave saved: "+scenePath+" on "+lastSaveTimeScene);
		}
		AutoSave repaintSaveWindow = (AutoSave)EditorWindow.GetWindow (typeof (AutoSave));
		repaintSaveWindow.Repaint();
	}
}

//////////////////////////////////////////////////
unity中创建的mesh为什么带有顶点色?如何才能创建不带顶点色的mesh?或者怎么在unity中把顶点色给抹掉?
做过以下尝试:
1、mesh.color = null,mesh.colors32 = null 没用。
2、重新new一个mesh,不赋值顶点色 没用。
3、转成obj再放到unity中看,居然还有顶点色, 但是把obj放到max中看,是没有的,转成fbx再放到项目中,还是有顶点色。
最后关闭Use Direct3D 11选项,重启Unity即可。关了Use Direct3D 11之后,重新创建Mesh,此时已经不带顶点色了。Obj文件以及不带顶点色的FBX文件,直接预览,顶点色也没了。开关位置:Edit>Project Settings>Player>Other Settings>Use Direct3D 11(PC选项卡下)

=========================

error CS0619: 'ProceduralPropertyDescription' is obsolete: 'Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.'

That's a Unity warning, since they removed Substance native support in more recent Unity versions you'll have to import their dedicated plugin in order to use sbsar files.
Substance for Unity Plugin

================================

m_masterCamera.cullingMask = isOn ? 1 : 0;  //1<<LayerMask.NameToLayer("Everything")

1<<LayerMask.NameToLayer("Everything") 这个变成 31号的layer了

0是Nothing  ~0是Everything

int a = 1 << LayerMask.NameToLayer("Nothing");-2147483648
            int b = ~(1 << LayerMask.NameToLayer("Nothing"));2147483647
            int c = LayerMask.NameToLayer("Nothing");-1
            int d = LayerMask.NameToLayer("Everything");-1
            int e = 1 << LayerMask.NameToLayer("Everything");-2147483648

// Only render objects in the first layer (Default layer)
        cam.cullingMask = 1 << 0;

The camera's culling mask tells it which layers to render.

The first mask, ~(1 << LayerMask.NameToLayer("Transparent")), renders everything except the transparent layer.

The second mask, 1 << LayerMask.NameToLayer("Transparent"), renders only the transparent layer.

It's pretty common to render opaque geometry in one pass, then render transparent geometry in a second pass. This makes sure that you render any opaque objects that are behind transparent objects.

If none of that makes sense, you may want to read up on bit masks.

Bit masking tends to make heavy use of:

left shift (<<) to pick a bit
bitwise OR (|) to enable certain bits of a mask
bitwise AND (&) to disable certain bits of a mask
bitwise NOT (~) to negate a mask

Suppose NameToLayer returns 3, which in binary is 0011, but that is not the same as 1 << 3, which in binary is 1000. The layer index tells you which bit to set, and then the left shift operation is used to set that bit.

=====================================================

EditorGUIUtility.isProSkin  EditorPrefs.GetInt("UserSkin") == 1; 相同的作用

=============================================================

collider convex 勾线了,不勾选IsTrigger,是让Collider 凹下去的地方紧贴模型

Use a convex collider from the mesh.

This means that if you have this set to true, your mesh collider wont have holes or entrances. Convex meshes can collide with other convex colliders and non-convex meshes. Thus convex mesh colliders are suitable on rigidibodies, if you really need more detailed colliders than what the primitive colliders provide you with.
Note: A convex mesh is required by the physics engine to have a non-zero volume. Flat meshes such as quads or planes that are marked as convex will be modified by the physics engine to have a thickness (and therefore a volume) to satisfy this requirement. The thickness of the resulting mesh is proportional to its size and can be up to 0.05 of its longest dimension in the plane of the mesh.

Is the collider a trigger?

A trigger doesn't register a collision with an incoming Rigidbody. Instead, it sends OnTriggerEnter, OnTriggerExit and OnTriggerStay message when a rigidbody enters or exits the trigger volume.

=====================================================

------- GLSL link error:  The number of vertex shader storage blocks (1) is greater than the maximum number allowed (0).
(Filename: ./Runtime/GfxDevice/opengles/ApiGLES.cpp Line: 645)

https://forum.unity.com/threads/error-glsl-link-error-the-number-of-vertex-shader-storage-blocks.666277/

The device you're running on doesn't support SSBO. You have to disable the effects that use SSBO.
Shader Storage Buffer Object
You can try switching to Vulkan - Mali has read support for compute buffers in all shader stages there.
 i like to use it post-processing effects under mobile devices, how can i check what effects are using SSBO? Eye adaptation? Bloom effect? Grain? Vignette?
--
Also, this problem i have it before to load any screen using postprocessing profile.
his is going to happen on all Mali GPUs.
What packages are you using in your project?
You can try switching to Vulkan - Mali has read support for compute buffers in all shader stages there.

==============================================

Used to extract the context for a MenuItem.

MenuCommand objects are passed to custom menu item functions defined using the MenuItem attribute.
Note: The menu is added to the object and is accessible by right-clicking in the inspector. The script code requires the CONTEXT option.

// Add context menu named "Do Something" to context menu

using UnityEngine;

using UnityEditor;

public class Something : EditorWindow

{

    // Add menu item

    [MenuItem("CONTEXT/Rigidbody/Do Something")]

    static void DoSomething(MenuCommand command)

    {

        Rigidbody body = (Rigidbody)command.context;

        body.mass = 5;

        Debug.Log("Changed Rigidbody's Mass to " + body.mass + " from Context Menu...");

    }

}

有些游戏引擎会把时间变量封装为一个类。引擎可能含此类的数个实例一个用作表示真实“挂钟时间”、另一个表示“游戏时间”(此时间可以暂停,或相对真实时间减慢/加快)、另一个记录全动视频的时间等。

//加上理想帧时间:别忘记把它缩放至我们当前的时间缩放率!
U64 dtScaledCycles= secondToCycles(
(1.0f/30.0f)* m timeSca1e);
m_timeCycles + dtscaledCycles;

///////////////////////////////////////////////////////////////////////////////////////////////////

Color myColor = new Color(0xc6,0xe7, 0x45, 0xFF);
 string colorHex = ColorUtility.ToHtmlStringRGB(myColor);
 Assert.AreEqual("c6e745", colorHex);
ColorUtility.TryParseHtmlString(htmlValue, out newCol)
ColorUtility.TryParseHtmlString returns bool not Color if successful. You get the output color in the second parameter then take that and assign it to the Button. Only use the output color if ColorUtility.TryParseHtmlString returns true.
function hexToRgb(hex) {
    var bigint = parseInt(hex, 16);
    var r = (bigint >> 16) & 255;
    var g = (bigint >> 8) & 255;
    var b = bigint & 255;

    return r + "," + g + "," + b;
}
function hexToRgbNew(hex) {
  var arrBuff = new ArrayBuffer(4);
  var vw = new DataView(arrBuff);
  vw.setUint32(0,parseInt(hex, 16),false);
  var arrByte = new Uint8Array(arrBuff);

  return arrByte[1] + "," + arrByte[2] + "," + arrByte[3];
}
function rgb2hex(red, green, blue) {
        var rgb = blue | (green << 8) | (red << 16);
        return '#' + (0x1000000 + rgb).toString(16).slice(1)
  }

  function hex2rgb(hex) {
        // long version
        r = hex.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
        if (r) {
                return r.slice(1,4).map(function(x) { return parseInt(x, 16); });
        }
        // short version
        r = hex.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i);
        if (r) {
                return r.slice(1,4).map(function(x) { return 0x11 * parseInt(x, 16); });
        }
        return null;
  }
const hexToRgb = hex =>
  hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i
             ,(m, r, g, b) => '#' + r + r + g + g + b + b)
    .substring(1).match(/.{2}/g)
    .map(x => parseInt(x, 16))

console.log(hexToRgb("#0033ff")) // [0, 51, 255]
console.log(hexToRgb("#03f")) // [0, 51, 255]
const rgbToHex = (r, g, b) => '#' + [r, g, b]
  .map(x => x.toString(16).padStart(2, '0')).join('')

console.log(rgbToHex(0, 51, 255)); // '#0033ff'
 

///////////////////////////////////////////////////////////////////////////////////////////////////////

If you want the editor to open in a scene when opening the project, change it in "Projectfolder"/Library/LastSceneManagerSetup.txt

LastSceneManagerSetup.txt 新工程保存后 

才有,sceneSetups:
- path: Assets/aa.unity
  isLoaded: 1
  isActive: 1
sceneSetups:
- path: Assets/Scenes/SampleScene.unity
  isLoaded: 1
  isActive: 1
如果在打开空场景(File->New Scene:Untitled)退出unity,则是sceneSetups: []
 

////////////////////////////////////////////

Unity gui 变高scrollview,比如text行数变高:text 设置overflow

程序每个字体设置好text1.text=”AAAA”; text2.text=”AAAA”;

text1.SetNativeSize();text2.SetNativeSize();

rectTransform.sizeDelta=new Vector2(rectTransform.sizeDelta.x, text1.preferredHeight + text2.preferredHeight);即可

////// AssetBundle渲染bug//////

[MenuItem("Utility/修复Shader")] private static void 修复Shader() { var renderers = Resources.FindObjectsOfTypeAll<Renderer>(); if (renderers == null || renderers.Length == 0) return; foreach (var renderer in renderers) { if (AssetDatabase.GetAssetPath(renderer) != "") continue; foreach (var sharedMaterial in renderer.sharedMaterials) { if (sharedMaterial != null) sharedMaterial.shader = Shader.Find(sharedMaterial.shader.name); } } var graphics = Resources.FindObjectsOfTypeAll<Graphic>(); if (graphics == null || graphics.Length == 0) return; foreach (var graphic in graphics) { if (AssetDatabase.GetAssetPath(graphic) != "") continue; graphic.material.shader = Shader.Find(graphic.material.shader.name); } }

////////////////////////

string.Format("({0},{1},{2},{3})", MeshRenderer.lightmapScaleOffset.x, MeshRenderer.lightmapScaleOffset.y, MeshRenderer.lightmapScaleOffset.z, MeshRenderer.lightmapScaleOffset.w) (0.0324565, 0.0324565, 0.9645787, 0.03698259)

如果是MeshRenderer.lightmapScaleOffset (0.0, 0.0, 1.0, 0.0)精读不够的问题

if (GameObjectUtility.GetStaticEditorFlags(item.gameObject).ToString().Contains(StaticEditorFlags.LightmapStatic.ToString()))

                        {

                            var render = item.GetComponent<MeshRenderer>();

                            if (render != null)

                            {

                                SerializedObject so = new SerializedObject(render);

                                float fScale = so.FindProperty("m_ScaleInLightmap").floatValue;

                                int i = so.FindProperty("m_LightmapIndex").intValue;

                                UnityEngine.Debug.LogError(item.name + "====render.lightmapIndex=====" + render.lightmapIndex);

                                UnityEngine.Debug.LogError(item.name + "====render.lightmapScaleOffset=====" + render.lightmapScaleOffset);

                               

                                float fTilingX = so.FindProperty("m_LightmapTilingOffset.x").floatValue;

                                float fTilingY = so.FindProperty("m_LightmapTilingOffset.y").floatValue;

                                float fOffsetX = so.FindProperty("m_LightmapTilingOffset.z").floatValue;

                                float fOffsetY = so.FindProperty("m_LightmapTilingOffset.w").floatValue;

                            }}

https://www.cnblogs.com/Tom-yi/p/8662251.html

[XmlElement("AAA")]public List<string> AAA; //这种在写入XML的时候能成功写入,但是读取的时候是null,要把string变成自己的类并加[System.Serializable]

xml写入的时候,"{0}\t{1}"拼接能正确写入,但是不能用Split('\t')正确获取,要把每一个元素分别[XmlAttribute("")]public string bbb;

Resources.Load<T>(Resources下的不带后缀的路径)

FileStream fs = new FileStream(硬盘上的全路径并且带后缀, FileMode.Open);

using (FileStream fs = new FileStream(Path.Combine(configPath, string.Format("{0}.bytes", item.Key)), FileMode.CreateNew, FileAccess.Write))

                    {

                        using (StreamWriter sw = new StreamWriter(fs))

                        {

                            sw.WriteLine(item.Key);

                            sw.WriteLine(item.Value.Count);

                        }

                    }

虽然是bytes后缀,但是记事本能看到内容

UnauthorizedAccessException: Access to the path "一个自己写的路径" is denied.

System.IO.Directory.CreateDirectoriesInternal (System.String path) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/Directory.cs:131)

System.IO.Directory.CreateDirectory (System.String path) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/Directory.cs:96)

文件流写入权限问题,如果文件确实已经 s.Close();此时需要注意的是,要进行s.Dispose();重新分配一下系统使用资源就可以,这样就不会出现文件被访问的权限不够的现象,因为原来的情况下,文件并没有被执行完。

InvalidOperationException: Operation is not valid due to the current state of the object

System.Collections.Stack.Pop () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections/Stack.cs:329)

UnityEngine.GUILayoutUtility.EndLayoutGroup () (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUILayoutUtility.cs:323)

UnityEngine.GUILayout.EndVertical () (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUILayout.cs:322)

解决的参考网址: 
InvalidOperationException: Operation is not valid due to the current state of the object System.Collections.Stack.Peek () - Unity Answers

原因是:unity的窗口方式有时会导致这个错误。 
更改unity的窗口方式为:default重启unity即可。

此问题,是在编译的dll时遇到的。

If you do own tools in the Editor(Unity5), you can use this callback for correct run any methods without exeptions. It's very comfortably. Like this

  1.  void OnGUI()
  2.  {
  3.    EditorGUILayout.BeginHorizontal();
  4.    if (GUILayout.Button("Build all"))
  5.    {
  6.      EditorApplication.delayCall += BuildAssetsBundles;
  7.      Close();
  8.    }
  9.    EditorGUILayout.EndHorizontal();
  10.  }
  11.  protected virtual void BuildAssetsBundles()
  12.  {
  13.    BuildPipeline.BuildAssetBundles("AssetsBundles");
  14.  }

Transform hasSetIsHierarchyDispatchInterested present when destroying the hierarchy. Systemsmust deregister themselves in Deactivate.

UnityEditor.AssetDatabase:StopAssetEditing()

 

 

C#堆栈日志//System.Environment.StackTrace;

AssetDatabase.StartAssetEditing();AssetDatabase.StopAssetEditing();//加速编辑

//////////////////////////////////////

varisPrefab = PrefabUtility.GetPrefabParent(item);

                if (isPrefab)

                {

                    varpath = AssetDatabase.GetAssetPath(isPrefab);

                    if (File.Exists(path))

                    {

                        stringstrValidate = AssetDatabase.ValidateMoveAsset(path, string.Format("Assets{0}{1}/{2}", m_mapConstData.InteractiveFolder, interactiveParentName,path.Substring(path.LastIndexOf("/",StringComparison.Ordinal) + 1)));

                        if (string.IsNullOrEmpty(strValidate))

                        {

                            stringstrErr = AssetDatabase.MoveAsset(path, string.Format("Assets/{0}/{1}/{2}", 目标文件夹, 文件名字.prefab, path.Substring(path.LastIndexOf("/", StringComparison.Ordinal) + 1)));

                            if (!string.IsNullOrEmpty(strErr))

                                Debug.LogErrorFormat("22222 Error: {0}", strErr);

                        }

                        else

                        {

                            Debug.LogWarningFormat("{0} MoveAssetError: {1}",item.name, strValidate);

                        }

//以下是拷贝的

                        //boolb = AssetDatabase.CopyAsset(path, string.Format("Assets/{0}/{1}/{2}", 目标文件夹, 文件名字.prefab,  path.Substring(path.LastIndexOf("/",StringComparison.Ordinal) + 1)));

                        //移动是同样的作用

//File.Move(path, string.Format("{0}/{1}.prefab", 磁盘的路径文件夹, item.name));

                        //File.Move(string.Format("{0}.meta", path), string.Format("{0}/{1}.prefab.meta",磁盘的路径文件夹, item.name));

                    }

}

/////////////////////////////////////////////

 

Fixrange = Fix.Ratio(MapDynamicDataUtils.GridDetectionDistance, 1);//10  10

           Fixrange1 = newFix(MapDynamicDataUtils.GridDetectionDistance);//0.000153  10

 

DestroyImmediate Objectobj = Resources.Load)把工程里资源搞坏

 

constintReporterExecOrder = -12000;

        GameObjectreporterObj = newGameObject();

        reporterObj.name = "Reporter";

        Reporterreporter = reporterObj.AddComponent<Reporter>();

        reporterObj.AddComponent<ReporterMessageReceiver>();

        //reporterObj.AddComponent<TestReporter>();

       

        // Register root object for undo.

        Undo.RegisterCreatedObjectUndo(reporterObj,"Create Reporter Object");

 

        MonoScriptreporterScript = MonoScript.FromMonoBehaviour(reporter);

        stringreporterPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(reporterScript));

 

        if (MonoImporter.GetExecutionOrder(reporterScript) != ReporterExecOrder) {

            MonoImporter.SetExecutionOrder(reporterScript, ReporterExecOrder);

            //Debug.Log("Fixing exec order for " + reporterScript.name);

        }

 

m_deleteScriptName = EditorGUILayout.ObjectField("脚本", m_deleteScriptName,typeof(Object)) asMonoScript;

            SetButton("FindMatchScripts", () =>

            {

                varobjs = Selection.GetFiltered<GameObject>(SelectionMode.TopLevel);

                foreach (var iteminobjs)

                {

                    varcps = item.GetComponents<Component>();

                    foreach (var VARIABLEincps)

                    {

                        if (VARIABLE.GetType()== m_deleteScriptName.GetClass())

                        {

                            varpath = AssetDatabase.GetAssetPath(item);

                            UnityEngine.Debug.LogFormat("包含 {0} 脚本的Prefab {1}", m_deleteScriptName.GetClass(), path);

                        }

                    }

                }

 

           });

 

//效果一样=======

m_getNoDestroyList = newList<MapNoDestroyInfo>();//.Clear();

           

           for (int i = 0; i < m_dynamicDetectionCellList.Count; i++)

           {

                //m_getNoDestroyList =DeepClone<MapNoDestroyInfo>(m_cellNoDestroyDic[m_dynamicDetectionCellList[i]+ 1]);

                m_getNoDestroyList =m_cellNoDestroyDic[m_dynamicDetectionCellList[i] + 1];

            }

或者在循环里边

m_getNoDestroyList.Clear();m_getNoDestroyList.AddRange(m_cellNoDestroyDic[m_dynamicDetectionCellList[i] + 1]);

//效果一样=======

 

 

GC.GetTotalMemory Method (Boolean)

Retrieves the number of bytes currentlythought to be allocated. A parameter indicates whether this method can wait ashort interval before returning, to allow the system to collect garbage andfinalize objects.

 

If the forceFullCollection parameter is true,this method waits a short interval before returning while the system collectsgarbage and finalizes objects. The duration of the interval is an internallyspecified limit determined by the number of garbage collection cycles completedand the change in the amount of memory recovered between cycles. The garbagecollector does not guarantee that all inaccessible memory is collected.

 

 

GC.Collect(0)

Use the mode parameter to specify whethergarbage collection should occur immediately or only if the time is optimal toreclaim objects. Using this method does not guarantee that all inaccessiblememory in the specified generation is reclaimed.

To adjust the intrusiveness of garbagecollection during critical periods in your application, set the LatencyModeproperty.

The garbage collector does not collectobjects with a generation number higher than specified by the generationparameter. Use the MaxGeneration property to determine the maximum valid valueof generation.

To have the garbage collector consider allobjects regardless of their generation, use the version of this method thattakes no parameters.

To have the garbage collector reclaim objectsup to a specified generation of objects, use the GC.Collect(Int32) methodoverload. When you specify the maximum generation, all objects are collected.

//////////////////////////////TestPath

                //Fx_butterflyprefab

                //  butterflyAAAAA  Fx_butterfly的子节点

vara = GameObject.Find("butterflyAAAAA");//("NoDestroy_Cylinder_0001");

                Debug.LogError("========11========"+ a.name); //butterflyAAAAA

                varaa = AssetDatabase.GetAssetPath(a);

                Debug.LogError("========111111========" + aa); //空的

                varaaa = PrefabUtility.GetPrefabParent(a);

                Debug.LogError("========111111========" + aaa.name);//butterfly

                varaaaa = AssetDatabase.GetAssetPath(aaa);

                Debug.LogError("=======11111111=========" + aaaa);//Assets/GameData/Prefabs/Effect/Scene/Fx_butterfly.prefab

                varaaa2 = PrefabUtility.FindPrefabRoot(a);

                Debug.LogError("========1111112========" + aaa2.name); //Fx_butterfly

                varaaaa2 = AssetDatabase.GetAssetPath(aaa2);

                Debug.LogError("=======111111112=========" + aaaa2);//空的

 

                varb = GameObject.Find("NoDestroy_PForestRattanVine02c(2)_0027"); //prefab

                Debug.LogError("=======222========="+ b.name);//NoDestroy_PForestRattanVine02c(2)_0027

                varbb = AssetDatabase.GetAssetPath(b);

                Debug.LogError("=======2222222=========" + bb);//空的

                varc = PrefabUtility.GetPrefabParent(b);

                vard = AssetDatabase.GetAssetPath(c);

                Debug.LogError("=======333========="+ d);//Assets/Art/Enviroment/DemoScene/Plant/Prefabs/P_Forest_RattanVine_02c.prefab

///////////////////////////////////

Deepth copy

//public static IList<T>Clone<T>(this IList<T> listToClone) where T : ICloneable

        //{

        //    return listToClone.Select(item =>(T)item.Clone()).ToList();

        //}

 

        publicstaticList<T> DeepClone<T>(objectobj)

        {

            using (varms = newMemoryStream())

            {

                varformatter= newBinaryFormatter();

                formatter.Serialize(ms, obj);

                ms.Seek(0,SeekOrigin.Begin);

 

                returnformatter.Deserialize(ms) asList<T>;

            }

            //objectretval;

            //using(MemoryStream ms = new MemoryStream())

            //{

            //    var formatter = new BinaryFormatter();

            //    formatter.Serialize(ms, obj);

            //    ms.Seek(0, SeekOrigin.Begin);

            //    retval = formatter.Deserialize(ms);

            //    ms.Close();

            //}

            //returnretval as List<T>;

       }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值