2018-05-21 16:37:00 amcp9 阅读数 917
  • unity3D游戏/AR/VR在线就业班

    本套课程是一套完整的 Unity3D-游戏/AR/VR 学习课程,具体的课程内容包括《C#语言》、《Unity引擎》、《编程思想》,《商业级项目实践》等开发课程,引导您一步步循序渐进、由易到难,终获得Unity 3D/游戏/AR/VR工程师的岗位技能。

    12832 人正在学习 去看看 宋晓波

1.添加tag

GameObject obj = GameObject.FindWithTag("Player");

仅适用于tag场景中只有一个player tag时,若场景中有多个player tag,也只返回一个(场景中你最后创建的那个游戏物体)

注意:无论运行该函数的游戏物体处于哪个父子层级,也无论目标tag处于哪个父子层级均能正常找到(遍历所有游戏物体)

2.GameObject.FindGameObjectsWithTag

        GameObject[] objs = GameObject.FindGameObjectsWithTag("Player");
        foreach (GameObject obj in objs)
        {
            Debug.Log(obj.name);
        }

查找所有目标tag的游戏物体

3.transform.find

        Transform t = transform.Find("3");
        Debug.Log(t.name);

注意:该函数只能查找运行该函数的游戏物体下的子物体

4.GetComponentsInChildren<>()

4.1.GetComponentsInChildren<Transform>()

    public Transform[] transforms;
    private void Start()
    {
       test_4();
    }
    public void test_4()
    {
        GameObject obj = GameObject.FindWithTag("Player");
        transforms = obj.GetComponentsInChildren<Transform>();
    }

注意:其中1的tag为player,GetComponentsInChildren<Transform>()包含自身的transform

4.2GetComponentsInChildren<test>()

    public test[] transforms;
	private void Start()
	{
        test_4();
	}
    public void test_4()
    {
        GameObject obj = GameObject.FindWithTag("Player");
        transforms = obj.GetComponentsInChildren<test>();
    }

注意:1的tag为player,1与3-2与2-3没有挂载test脚本


总结:GetComponentsInChildren<>()包含自身的Component

5.遍历所有子物体(包含孙物体)

      GameObject obj = GameObject.FindWithTag("Player");
      transforms = obj.GetComponentsInChildren<Transform>();
      test_6(obj.transform);
    public void test_6(Transform transform)
    {
        foreach (Transform t in transform.GetComponentsInChildren<Transform>())
        {
            Debug.Log(t.name);
        }
    }

注意:这里包含了1这个游戏物体

6.遍历所有子物体(不包括孙物体)

    GameObject obj = GameObject.FindWithTag("Player");
    transforms = obj.GetComponentsInChildren<Transform>();
    test_7(obj.transform);
    public void test_7(Transform transform)
    {
        foreach (Transform t in transform)
        {
            Debug.Log(t.name);
        }
    }

7.正确的Destroy()销毁游戏物体的方式

 GameObject obj = GameObject.FindWithTag("Player");
 transforms = obj.GetComponentsInChildren<Transform>();
 test_8(obj.transform);
 public void test_8(Transform transform)
    {
        List<GameObject> lst = new List<GameObject>();
        foreach(Transform t in transform)
        {
            lst.Add(t.gameObject);
        }

        for (int i = 0; i < lst.Count;i++)
        {
            Destroy(lst[i]);
        }
    }

注意:某些时候也可以使用

   foreach(Transform t in transform)
        {
            Destroy(t.gameObject);
        }

8.判断一个游戏物体下是否有子物体

if(transform.childCount > 0)


2017-07-19 19:50:25 jxw167 阅读数 2875
  • unity3D游戏/AR/VR在线就业班

    本套课程是一套完整的 Unity3D-游戏/AR/VR 学习课程,具体的课程内容包括《C#语言》、《Unity引擎》、《编程思想》,《商业级项目实践》等开发课程,引导您一步步循序渐进、由易到难,终获得Unity 3D/游戏/AR/VR工程师的岗位技能。

    12832 人正在学习 去看看 宋晓波

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

在游戏开发中,UI是经常需要变动的,一款游戏从开发到结束,UI至少更换好多版,这就给替换UI的人增加了很多负担,认为的因素很难将旧的UI彻底删除掉,这样就会出现很多冗余的资源,在项目后期要将这些冗余的资源清除掉,如果单靠人工操作难免会出现各种错误,其实我们完全可以通过工具将它们删除掉。下面把删除冗余的工具代码给读者展示如下:

using UnityEngine;
using UnityEditor;

using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using System;

public static class LinqHelper {
    public static TSource Fold<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func, TSource id)
    {
        TSource r = id;
        foreach (var s in source)
        {
            r = func(r, s);
        }
        return r;
    }
    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        foreach (T element in source)
            action(element);
    }
    public static IEnumerable<U> SelectI<U, T>(this IEnumerable<T> source, Func<T, int, U> action)
    {
        int i = 0;
        foreach (var s in source)
        {
            yield return action(s, i);
            i += 1;
        }
    }
    public static TSource Reduce<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func) where TSource : new()
    {
        return Fold<TSource>(source, func, new TSource());
    }
    public static void ForEachI<T>(this IEnumerable<T> source, Action<T, int> action)
    {
        int i = 0;
        foreach (T element in source)
        {
            action(element, i);
            i += 1;
        }

    }
}
public static class FindUnUnUsedUITexture
{


    static List<string> getUUIDsInFile(string path)
    {
        StreamReader file = new StreamReader(path);
        List<string> uuids = new List<string>();
        string line;
        while ((line = file.ReadLine()) != null)
        {
            var reg = new Regex(@"([a-f0-9]{32})");
            var m = reg.Match(line);
            if (m.Success)
            {
                uuids.Add(m.Groups[0].Value);
            }
        }
        file.Close();
        return uuids;
    }
    // Use this for initialization
    [MenuItem("Tools/UI冗余图片扫描")]
    public static void Scan()
    {

        var uiPrefabRootDir = EditorUtility.OpenFolderPanel("选择UIPrefab目录",  "Assets","");
        if (string.IsNullOrEmpty(uiPrefabRootDir))
        {
            return;
        }

        var uiPicRootDir = EditorUtility.OpenFolderPanel("选择UIPrefab目录", "Assets", "");
        if (string.IsNullOrEmpty(uiPicRootDir))
        {
            return;
        }
        
        //find all meta and pic path
        var uuidReg = new Regex(@"guid: ([a-f0-9]{32})");
        var pngs = Directory.GetFiles(uiPicRootDir, "*.meta", SearchOption.AllDirectories)
        .Select(p => "Assets/" + p.Replace('\\','/').Substring(Application.dataPath.Length+1))
        .Where(p =>
        {
            return p.EndsWith(".png.meta") || p.EndsWith(".jpg.meta") || p.EndsWith(".tag.meta");
        }).ToList();
        var uuid2path = new Dictionary<string, string>();
        pngs.ForEachI((png, i) =>
        {
            var matcher = uuidReg.Match(File.ReadAllText(png));
            var uuid = matcher.Groups[1].Value;
            if (uuid2path.ContainsKey(uuid))
            {
                Debug.LogError("uuid dup" + uuid + " \n" + png + "\n" + uuid2path[uuid]);
            }
            else
            {
                uuid2path.Add(uuid, png.Substring(0,png.Length-5));
            }
            EditorUtility.DisplayProgressBar("扫描图片中", png, (float)i / pngs.Count);

        });

        //find all prefab and search pic uuid
        var prefabs = Directory.GetFiles(uiPrefabRootDir, "*.prefab", SearchOption.AllDirectories);
        var anims = Directory.GetFiles("Assets/", "*.anim", SearchOption.AllDirectories).Where(p => !p.Replace('\\', '/').Contains("Characters/"));
        var allFiles = prefabs.Concat(anims).ToList();
        var alluuids = allFiles
        .SelectI((f, i) => {
            EditorUtility.DisplayProgressBar("获取引用关系", f, (float)i / allFiles.Count);
            return getUUIDsInFile(f);
        }).ToList().Aggregate((a, b) => a.Concat(b).ToList()).ToList();
        EditorUtility.ClearProgressBar();
        //rm used pic uuid
        var uuidshashset = new HashSet<string>(alluuids);
        var em = uuidshashset.GetEnumerator();
        while(em.MoveNext())
        {
            var uuid = em.Current;
            uuid2path.Remove(uuid);
        }

        StringBuilder sb = new StringBuilder();
        sb.Append("UnUsedFiles: ");
        sb.Append(uuid2path.Count);
        sb.Append("\n");
        uuid2path.ForEach(kv => sb.Append(kv.Value +"\n"));

        File.WriteAllText("Assets/unusedpic.txt", sb.ToString());
        EditorUtility.DisplayDialog("扫描成功", string.Format("共找到{0}个冗余图片\n请在Assets/unsedpic.txt查看结果",uuid2path.Count), "ok");
    }
}
将该脚本放置到Editor文件夹下面,然后在Tool菜单下点击UI冗余图片扫描就会弹出窗口将冗余的UI图片列出来,非常方便。

另外,在游戏中经常出现脚本丢失情况,自己查找非常麻烦,这个也可以通过工具去查找,代码如下所示:

using System.Linq;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;
using System;

public static class MissingScriptFinder 
{
    private const string MENU_ROOT = "Tool/Missing References/";
    public static string GetHierarchyName(Transform t)
    {
        if (t == null)
            return "";

        var pname =  GetHierarchyName(t.parent);
        if (pname != "")
        {
            return pname + "/" + t.gameObject.name;
        }
        return t.gameObject.name;
    }

    public static TSource Fold<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func,TSource id)
    {
        TSource r = id;
        foreach(var s in source)
        {
            r = func(r,s);
        }
        return r;
    }
    public static void ForEachI<T>(this IEnumerable<T> source, Action<T,int> action)
    {
        int i = 0;
        foreach (T element in source)
        {
            action(element,i);
            i += 1;
        }
            
    }
    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        foreach (T element in source)
        {
            action(element);
        }
            
    }

    static HashSet<string> findAllScriptUUIDsInAssets()
    {
        var uuids = Directory.GetFiles("Assets/", "*.cs.meta", SearchOption.AllDirectories)
            .Select(p =>
            {
                return File.ReadAllLines(p)[1].Substring(6);
            }).ToList();
        //find dll uuids
        var dlluuids = Directory.GetFiles(EditorApplication.applicationContentsPath, "*.dll", SearchOption.AllDirectories)
        .Select(p =>
        {
            return AssetDatabase.AssetPathToGUID(p.Replace('\\', '/'));
        }).Where(s => s!= "").ToList();
        return new HashSet<string>(uuids.Concat(dlluuids));
    }
    static Regex s_scriptUUIDReg = new Regex(@"m_Script: \{fileID: [0-9]+, guid: ([0-9a-f]{32}), type: 3\}");
    static string getScriptUUID(string line)
    {
        var m = s_scriptUUIDReg.Match(line);
        if (m.Success)
        {
            return m.Groups[1].Value;
        }
        if(line.Contains("m_Script: {fileID: 0}")) //missing script
        {
            return "0";
        }
        return null;
    }
    static Dictionary<string,HashSet<string>> findAllPrefabScriptRefInDir(string dir,Action<int> onBeginFinding,Action<int,string,int> onFinding, Action onEndFinding )
    {
        var allPrefabs = Directory.GetFiles(dir, "*.prefab", SearchOption.AllDirectories);
        onBeginFinding(allPrefabs.Length);
        Dictionary<string, HashSet<string>> r = new Dictionary<string, HashSet<string>>();
        
        for (int i =0;i<allPrefabs.Length;++i)
        {
            onFinding(i, allPrefabs[i],allPrefabs.Length);
            File.ReadAllLines(allPrefabs[i]).ForEach(line =>
            {
                string s = getScriptUUID(line);
                if (s != null)
                {
                    HashSet<string> files = null;
                    r.TryGetValue(s, out files);
                    if (files == null)
                    {
                        files = new HashSet<string>();
                        r.Add(s, files);
                    }
                    files.Add(allPrefabs[i]);
                }
            });
        }
        onEndFinding();
        return r;
    }


    private static void FindMissionRefInGo(GameObject go)
    {
        var components = go.GetComponents<MonoBehaviour>();
        foreach (var c in components)
        {
            // Missing components will be null, we can't find their type, etc.
            if (!c)
            {
                var assetPath =  AssetDatabase.GetAssetPath(go);
                if(assetPath != "" && assetPath != null)
                {
                    Debug.LogError("missing script: " + GetHierarchyName(go.transform) + "-->" + assetPath);
                }
                else
                {
                    Debug.LogError("missing script: " + GetHierarchyName(go.transform));
                }
                continue;
            }
        }
        foreach(Transform t in go.transform)
        {
            FindMissionRefInGo(t.gameObject);
        }
    }
    public static IEnumerable<GameObject> SceneRoots()
    {
        var prop = new HierarchyProperty(HierarchyType.GameObjects);
        var expanded = new int[0];
        while (prop.Next(expanded))
        {
            yield return prop.pptrValue as GameObject;
        }
    }
    [MenuItem(MENU_ROOT + "search in scene")]
    public static void FindMissingReferencesInCurrentScene()
    {
        var objs = SceneRoots();
        int count = objs.Count();
        objs.ForEachI((prefab, i) =>
        {
            EditorUtility.DisplayProgressBar("check missing prefabs", prefab.ToString(), (float)i / count);
            FindMissionRefInGo(prefab);
        });
        EditorUtility.ClearProgressBar();
    }

    [MenuItem(MENU_ROOT + "search in all assets")]
    public static void MissingSpritesInAssets()
    {
        var allScriptsIds = findAllScriptUUIDsInAssets();
        var refScriptIds = findAllPrefabScriptRefInDir("Assets/",
        (count) =>
        {
            EditorUtility.DisplayProgressBar("scanning","",0);
        },
        (idx,file,count) =>
        {
            EditorUtility.DisplayProgressBar("scanning", file, (float) idx/count);
        },
        () =>
        {
            EditorUtility.ClearProgressBar();
        });
        var missingScriptsFiles = refScriptIds
        .Where(kv => !allScriptsIds.Contains(kv.Key))
        .Select(kv => kv.Value)
        .ToList()
        .Fold((a,b)=>new HashSet<string>(a.Concat(b)),new HashSet<string>());
        Debug.LogError("----------------------------------------->\nMissingFiles: "  + missingScriptsFiles.Count);
        missingScriptsFiles.ForEachI((f, i) =>
        {
            EditorUtility.DisplayProgressBar("check missing prefabs", f, (float)i / missingScriptsFiles.Count);
            var prefab = AssetDatabase.LoadAssetAtPath(f, typeof(GameObject)) as GameObject;
            FindMissionRefInGo(prefab);
        });
        EditorUtility.ClearProgressBar();
    }

}
同样需要将该脚本放置到Editor文件夹下面,点击菜单栏中的Tool/Missing Reference 即可实现丢失脚本的查找,它可以分成多个部分查找,自己可以去测试一下。


2017-09-23 15:58:57 meizilaiyifa 阅读数 10507
  • unity3D游戏/AR/VR在线就业班

    本套课程是一套完整的 Unity3D-游戏/AR/VR 学习课程,具体的课程内容包括《C#语言》、《Unity引擎》、《编程思想》,《商业级项目实践》等开发课程,引导您一步步循序渐进、由易到难,终获得Unity 3D/游戏/AR/VR工程师的岗位技能。

    12832 人正在学习 去看看 宋晓波

RT,拖拽一个动画的时候,出现了以上的状况


网上查找了一番,大抵是回答者的水平都太高,没能及时领略其中深意,又或者所遭遇的状况并未一致


最终找到最接近的解答如下:


unity3d中的物体,在Scene窗口中可以看到,而在Game窗口中看不到的原因:

多半是因为物体所属Layer与照相机的culling mask不一致导致的,或者超出照相机的可视范围。

如果游戏中有多个相机,每个相机都有自己的可视范围和culling mask,物体在移动的过程中,进入不同的相机,其可见性可能是变化的,取决与物体所属Layer与当前相机是否一致


想了一会,调整camera -> Culling Mask -> Everything ,至此,问题解决


虽然是一个很简单的问题,但个人认为既然是入门级,就不要让新手存在过多的理解障碍,给出具体解决操作是很必要的,再给原因比较合适


程序方面很多内容理解了并不难,但是在理解前新手往往遭遇天书级别的文字描述,这对新手相当不友好,也阻挡了更多新人的热情。

2019-08-15 22:45:10 piai9568 阅读数 145
  • unity3D游戏/AR/VR在线就业班

    本套课程是一套完整的 Unity3D-游戏/AR/VR 学习课程,具体的课程内容包括《C#语言》、《Unity引擎》、《编程思想》,《商业级项目实践》等开发课程,引导您一步步循序渐进、由易到难,终获得Unity 3D/游戏/AR/VR工程师的岗位技能。

    12832 人正在学习 去看看 宋晓波

有时因为各种原因,某些物体的Inspector上显示脚本丢失。如下图:

通过下面的脚本,我们可以找出场景中哪些物体丢失了脚本。

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using UnityEngine.SceneManagement; 
 
public class SelectGameObjectsWithMissingScripts : Editor
{
    [MenuItem("Tools/Select GameObjects With Missing Scripts")]
    static void SelectGameObjects()
    {
        //Get the current scene and all top-level GameObjects in the scene hierarchy
        Scene currentScene = SceneManager.GetActiveScene();
        GameObject[] rootObjects = currentScene.GetRootGameObjects();
 
        List<Object> objectsWithDeadLinks = new List<Object>();
        foreach (GameObject g in rootObjects)
        {
			var trans = g.GetComponentsInChildren<Transform>();
			foreach (Transform tran in trans)
			{
				Component[] components = tran.GetComponents<Component>();
				for (int i = 0; i < components.Length; i++)
				{
					Component currentComponent = components[i];
	
					//If the component is null, that means it's a missing script!
					if (currentComponent == null)
					{
						//Add the sinner to our naughty-list
						objectsWithDeadLinks.Add(tran.gameObject);
						Selection.activeGameObject = tran.gameObject;
						Debug.Log(tran.gameObject + " has a missing script!"); //Console中输出
						break;
					}
				}

			}
            //Get all components on the GameObject, then loop through them 

        }
        if (objectsWithDeadLinks.Count > 0)
        {
            //Set the selection in the editor
            Selection.objects = objectsWithDeadLinks.ToArray();
        }
        else
        {
            Debug.Log("No GameObjects in '" + currentScene.name + "' have missing scripts! Yay!");
        }
    }
}

将上面的代码复制到SelectGameObjectsWithMissingScripts.cs中。
然后点击菜单栏上的Tool->Select GameObjects With Missing Scripts 项 即可在console中输出所有丢失脚本的物体名称。

实现原理:
获得当前场景Hierarchy窗口中最顶层的物体,然后通过GetComponentsInChildren() 获得所有自身及所有子物体。
遍历这些子物体,通过
Component[] components = tran.GetComponents();
获得子物体上的所有Component,如果某个Component为null,则说明该物体上有丢失脚本。

更多Unity教程,请关注微信公众号 UnityAsk。

2019-05-23 15:32:27 zxy13826134783 阅读数 413
  • unity3D游戏/AR/VR在线就业班

    本套课程是一套完整的 Unity3D-游戏/AR/VR 学习课程,具体的课程内容包括《C#语言》、《Unity引擎》、《编程思想》,《商业级项目实践》等开发课程,引导您一步步循序渐进、由易到难,终获得Unity 3D/游戏/AR/VR工程师的岗位技能。

    12832 人正在学习 去看看 宋晓波

步骤:

1 新建场景,并新建3个测试脚本,名称分别为  TestScript1、Test1、TestScript2

2  新建3个空游戏物体,名称分别为:GameObject1、GameObject2、Test

3 在游戏物体GameObject1上挂载脚本TestScript1和TestScript2,在游戏物体GameObject2挂载脚本TestScript2,在游戏物体Test上挂载脚本Test

4 编写Test脚本如下:

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

public class Test1 : MonoBehaviour {

    void Start()
    {
        //查找到当前所有的带有脚本的游戏物体的MonoBehaviour
        MonoBehaviour[] scripts = Object.FindObjectsOfType<MonoBehaviour>();

        foreach (MonoBehaviour item in scripts)
        {
            //因为直接输出item.ToString()的值为  游戏物体名称(脚本名称)
            Debug.Log(item.gameObject.name + ": " + item.ToString().Split(new char[] { '(', ')' })[1]);

        }
    }
    
}

 

5 运行输出如下:

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