U3D 重庆销毁假冒产品GameObject

Unity3D开发常用API之实例化与销毁(六) - 简书
Unity3D开发常用API之实例化与销毁(六)
1.实例化游戏物体
1.游戏中的案例介绍
在很多 MMORPG 类的游戏中都有类似于“金钱副本”的副本关卡。在这类副
本中通常都是限定一个时间,在这个时间内玩家可以尽情的破坏,然后收集金钱。
分析游戏截图讲解场景元素:[见图]
①场景中所有的坛子,模型都是一样的,坛子是预制体。
②坛子是从“天上”掉下来的,所以坛子模型身上有刚体组件。
③如果玩家在一段时间内没有打碎坛子,这些坛子会消失。
2.案例场景制作
①创建地面模型;
②创建“坛子”模型,并制作成预制体;
3.实例化生成 1 个坛子
GameObject.Instantiate(Object, Vector3, Quaternion);
参数说明:
Object:用于实例化的预制体;
Vector3:实例化后生成的物体所在的位置;
Quaternion[四元数]:实例化后生成的物体的旋转状态;
Quaternion.identity:无旋转;
4.构造随机位置
位置是用 Vector3 类型进行表示的。
X,Y,Z 三个值确定了物体在三维世界中的位置。
Random.Range(min, max):生成随机数。
在 min 和 max 直接随机生成一个随机数。
演示:按下键盘的一个键,就在随机位置实例化一个物体。
2.销毁游戏物体
GameObject.Destroy(Object, float);定时销毁某个游戏物体。
参数说明:
Object:要销毁的游戏物体;
float:时间,多少秒后销毁;
CreateBoxs
public class CreateBoxs : MonoBehaviour {
//定义公开变量 并通过拖曳 把相关预置体拖至相关属性下
public GameObject goP
void Start () {
//实例化对象关键语句(静态方法)
// GameObject.Instantiate(goPrefab,Vector3.up,Quaternion.identity);//参数1:预置体,就是要实例化的对象;参数2:0位置上方1米,参数3:4元数无旋转
//自己定义随机范围(位置)
// Vector3 position = new Vector3(1,1,1);
//Vector3 position = new Vector3(Random.Range(-9.0f,9.0f),10,Random.Range(-9.0f,9.0f));//参数1:X轴的范围 Y固定下高度,Z轴的范围
//GameObject.Instantiate(goPrefab,position,Quaternion.identity);
//通过按下空格键随机实例化box;
void Update () {
//通过按下空格键随机实例化box;
if (Input.GetKeyDown(KeyCode.Space))
Vector3 position = new Vector3(Random.Range(-9.0f,9.0f),10,Random.Range(-9.0f,9.0f));
GameObject.Instantiate(goPrefab,position,Quaternion.identity);
DestroyBox
public class DestroyBox : MonoBehaviour {
// Use this for initialization
void Start () {
//出现段时候后,销毁物体
关键语句 gameobject静态类方法
GameObject.Destroy(gameObject,Random.Range(5.0f,10.0f));//参数1:销毁物体的对象(就是本身) 参数2:销毁的时间
//以上方法只能写在start方法里,不能写在其他update方法中;
//// Update is called once per frame
//void Update () {
Unity API.png
一个无聊的人,经常做些无聊的事儿,撸代码,喂马,劈柴,周游世界......更喜欢看妹子~哈哈哈...AR/VR技术交流群:
本节要点 关键代码 ToolsClass 小结
本节要点 关键代码 PlayerController 小结
本节要点 关键代码 CoroutinTest 小结
本节要点 关键代码 GoldRotate 小结
本节要点 关键代码 LifeTest CubeLife 小结
1.下面的代码输出多少?修改代码让fnArr[i]() 输出 i。使用 两种以上的方法 2.封装一个汽车对象,可以通过如下方式获取汽车状态 3.下面这段代码输出结果是? 为什么? 4.下面这段代码输出结果是? 为什么? 5.下面这段代码输出?如何输出delayer: 0, ...
我听养鸟的行家说,刚抓的小鸟野性太足,千万不要一下子关起来,先把小鸟关在一个软的网里面,然后小鸟无法休息,也无法撞死,然后在小鸟跌入网底的时候,慢慢的给它一些食物,如果还是不从就放弃驯养。
但是大多数鸟会被食物吸引,慢慢的开始进食。等到一个月以后,这种小...
我说我啊 桀骜轻狂,我也 优柔寡合,并且 自负自卑 可是,我不能成为我这样的人啊 可是你, 长在荒芜,你也 长在城墙,并且 潇洒自得 可是我不能成为你这样的人啊 不可以,不能够,或者 也不想 璀璨是你,皎洁是你 骄傲是你,理想是你 孤独是你,迷蒙是你 精致是你,沉寂是你 你...
国庆长假八天,孩子刚踏入大学校门,没有回家,我也不愿意去景点给全国人民添堵,想想做点什么呢?突然想起来李笑来说过,利用长长的假期可以写书、开公司,我正好已经积累了200多页的素材,那就写书吧。 今天正好有人在steemit微信群里聊起来,写作是普通人实现财富自由的机会,我真...
前几天,何洁在参加一档节目时放话说自己再也不结婚了。言语之坚决,态度之冷漠,眼神之黯然,几近哽咽,让人心疼。参加超女时那个快乐的,笑起来眼睛弯弯的歌唱精灵不见了,眼前的何洁变成了一个对爱情失望,对婚姻绝望的失婚单亲妈妈。 短短的三年婚姻,若不是失望到底,怎么会说出余生不再结...扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
如何删除gameObject下面的所有子物体
阅读&202 |
方法一:using UnityE
using System.C
/// &summary&
/// 脚本位置:将此脚本挂载到父物体A身上
/// 脚本功能:用于测试销毁所有子物体
/// &/summary&
public class Parent : MonoBehaviour
void Start ()
for (int i = 0; i & transform.childC i++) {//API第一种方法
Destroy (transform.GetChild (i).gameObject);
for (int i = 0; i & transform.childC i++)//API第二种方法
Destroy( GetComponentInChildren&Transform&().gameObject);
}方法二:using UnityE
using System.C
/// &summary&
/// 脚本位置:将此脚本挂载到父物体A身上
/// 脚本功能:发送广播给自己和自己的所有子物体
/// &/summary&
public class Parent : MonoBehaviour
void Start ()
// 执行Start方法后会发送一个广播
// 广播会从自身开始查找这个DestoryMe方法,查找完自身后会查找所有子物体
BroadcastMessage ("DestoryMe");
}using UnityE
using System.C
/// &summary&
/// 脚本位置:每个需要被销毁的子物体身上
/// 脚本功能:销毁自身
/// &/summary&
public class Son : MonoBehaviour
// 作为被广播通知的方法,由父物体通知执行
public void DestoryMe ()
Destroy (gameObject);
作者的其他最新博客
评论 ( 个评论)脚本创建的xx(clone)物体要怎么销毁?【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:84,361贴子:
脚本创建的xx(clone)物体要怎么销毁?收藏
我用Destroy(gameObject);报错Destroying assets is not permitted to avoid data loss.
为什么我问问题次次都没人~~~
同问,我也遇到一样的问题~
你这个是在销毁脚本所挂接的gameobject
GameObject a = Instantiate(gameObject) as GameODestroy(a);创建一个gameObject的克隆,然后再删掉,这肯定是没问题的。根据你提的问题,我感觉你是这么干的GameObject a = Instantiate(gameObject) as GameODestroy(gameObject); &- 你删除本体去了。你删错东西了。
假设:平面为P
立方体球什么的分别为 A B C控制脚本挂在P身上那么创建A B C等物体时候注意A.transform.parent =//将创建的A挂在P的子节点下A.name = &aname&; //给物体A起个名字以后好找删除的时候Destroy(transform.Find(&aname&).gameObject);
我写2个脚本,下面第一个是给空对象,用来控制,另一个给这四个预制体的脚本:主要思路是:物体一放置,脚本有个参数flg就倒计时,后放置的物体flg数值大,碰撞检测时,删除flg小的(先放置)那一个。using UnityEusing System.Cpublic class DemoUI : MonoBehaviour {
public Transform StackedO//放置物体的平面
public Transform StackO//四个需要放置的物体 public Transform StackS public Transform StackG public Transform StackA
protected int ObjectFlg = 0; Vector3 StackP // Use this for initialization void Start ()
// Update is called once per frame void Update ()
switch ( ObjectFlg )//选择放置哪一个物体
//DestroyImmediate(StackObject, true);
ObjectFlg = 0;
Instantiate( StackObject, StackedObject.transform.position + new Vector3(0, StackObject.transform.localScale.y/2,0), Quaternion.identity );
ObjectFlg = 0;
Instantiate( StackSphere, StackedObject.transform.position + new Vector3(0, StackObject.transform.localScale.y/2,0), Quaternion.identity );
ObjectFlg = 0;
Instantiate( StackGun, StackedObject.transform.position + new Vector3(0, StackObject.transform.localScale.y/2,0), Quaternion.identity );
ObjectFlg = 0;
Instantiate( StackAircraft, StackedObject.transform.position + new Vector3(0, StackObject.transform.localScale.y/2,0), Quaternion.identity );
void OnGUI() {
GUI.skin.label.fontSize = 20;
if (Time.timeScale == 0)
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.1f, 100, 30), &继续&) )
Time.timeScale = 1;
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.1f, 100, 30), &暂停&) )
Time.timeScale = 0;
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.2f, 100, 30), &立方体&))
ObjectFlg = 1;
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.3f, 100, 30), &球体&))
ObjectFlg = 2;
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.4f, 100, 30), &狙击枪&))
ObjectFlg = 3;
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.5f, 100, 30), &飞机模型&))
ObjectFlg = 4;
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.6f, 100, 30), &清除&))
Application.LoadLevel (&ObjectStacked&);
if (GUI.Button (new Rect(Screen.width*0.5f + 200, Screen.height*0.8f, 100, 30), &退出&))
Application.Quit();
4个预制体脚本(刚才帖子怎么被删了,还用手机申请恢复,汗……) public class ObjectActions : MonoBehaviour {//这个类赋给四个预制体
//public Transform StackO // Use this for initialization protected float flg = 100;//倒计时开始 void Start () {
// Update is called once per frame void Update ()
transform.Rotate(0, Time.deltaTime*25, 0);
flg -= Time.deltaT
Debug.Log(flg); }
void OnTriggerEnter(Collider other) {
ObjectActions SObject = other.GetComponent&ObjectActions&();
if ( this.flg & SObject.flg)//后放的物体flg数值大,保留【此处有错误!!!】/*NullReferenceException: Object reference not set to an instance of an objectObjectActions.OnTriggerEnter (UnityEngine.Collider other) (at Assets/materials/Scripts/ObjectActions.cs:28) 【虽然有错误,但是程序还能继续正常运行,不知道是为什么汗】*/
Destroy(this.gameObject);
4个预制体脚本(刚才帖子怎么被删了,还用手机申请恢复,汗……) public class ObjectActions : MonoBehaviour {//这个类赋给四个预制体
//public Transform StackO // Use this for initialization protected float flg = 100;//倒计时开始 void Start () {
// Update is called once per frame void Update ()
transform.Rotate(0, Time.deltaTime*25, 0);
flg -= Time.deltaT
Debug.Log(flg); }
void OnTriggerEnter(Collider other) {
ObjectActions SObject = other.GetComponent&ObjectActions&();
if ( this.flg & SObject.flg)//后放的物体flg数值大,保留
Destroy(this.gameObject);
按你的代码写了下,正常运行不会报错呀
火星学习unity3d,编程师就业薪资20k起,毕业=高薪就业,unity3d0基础学习,半年即可入职一线游戏/互联网公司,火星终身免费推荐就业.
我发现问题了,代码不同在于我是public T ransform StackedO你是public GameObject StackedObject,请问这两个声明有什么不同?我看了3本Unity书,基本上产生物体都是public
还有,改成你这个代码系统不报错了,但是在前一行输入Destroy(PutObjected); 时,运行却没有删除前一次的物体,这是怎么一回事呀?
登录百度帐号gameObject.renderer.enabled //是控制一个物体是否在屏幕上渲染或显示& 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.Destroy()& //表示移除物体或物体上的组件 代表销毁该物体& 实际上该物体的内存并没有立即释放 而是在你下下个场景中槽释放内存资源,就是你a场景中Destroy了 一般是在c场景中才真正释放该物体的内存资源(这是我的体会 不知道理解错误没)gameObject.active&& //是否在场景中停用该物体&& 在你gameObject.active =false中 则你在场景中用find找不到该物体& //如果该物体有子物体 你要用SetActiveRecursively(false) 来控制是否在场景中停用该物体(递归的)
我们要介绍是销毁物体Destroy()&
1 using UnityE
2 using System.C
4 public class acc : MonoBehaviour {
// Use this for initialization
public Transform Q;
int speed=50;
void Start () {
// Update is called once per frame
void Update () {
float x = Input.GetAxis("Horizontal") * Time.deltaTime *//左右移动
float z = Input.GetAxis("Vertical") * Time.deltaTime *//
//主摄像机物体
transform.Translate(x,0,z);
if(Input.GetKeyDown(KeyCode.Mouse0))
//实列化子弹
Transform n = Instantiate(Q) as T
//发射子弹的位置为物体的位置
n.position = transform.
Vector3 f = transform.TransformDirection(Vector3.forward);
n.gameObject.rigidbody.AddForce(f*3000);
Destroy(n.gameObject,5);
//Destroy(n.gameObject);
//Destroy(gameObject);
5秒后 销毁物体
Destroy(n.gameObject,5);
立即销毁物体
Destroy(n.gameObject);
如果文件绑定在物体上用
Destroy(gameObject);
来销毁物体
Unity资源内存申请和释放
1.资源类型
GameObject, Transform, Mesh, Texture, Material, Shader, Script和各种其他Assets。
2.资源创建方式
静态引用,在脚本中加一个public GameObject变量,在Inspector面板中拖一个prefab到该变量上,然后在需要引用的地方Instantiate;
Resource.Load,资源需要放在Assets/Resources目录下;
AssetBundle.Load, Load之后Instantiate。
3. 资源销毁方式
GameObject.Destroy(gameObject),销毁该物体;
AssetBundle.Unload(false),释放AssetBundle文件内存镜像,不销毁Load创建的Assets对象;
AssetBundle.Unload(true),释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存镜像;
Resources.UnloadAsset(Object),释放已加载的Asset对象;
Resources.UnloadUnusedAssets,释放所有没有引用的Asset对象。
4. 生命周期
实验中创建了一个简单场景,场景中创建了一个Empty GameObject,上面挂了一个脚本,在Awake函数中通过协程函数来创建资源,具体的Coroutine函数下面都有。 实验中创建的Prefab是一个坦克车,加入场景中场景内存增加3M左右,同时创建了一个AssetBundle资源供AssetBundle使用。
1. Resources.Load方式加载一个Prefab, 然后Instantiate GameObject
代码如下:
IEnumerator LoadResources()
// 清除干净以免影响测试结果
Resources.UnloadUnusedAssets();
// 等待5秒以看到效果
yield return new WaitForSeconds(5.0f);
// 通过Resources.Load加载一个资源
GameObject tank = Resources.Load("Role/Tank") as GameO
yield return new WaitForSeconds(0.5f);
// Instantiate一个资源出来
GameObject tankInst = GameObject.Instantiate(tank, Vector3.zero, Quaternion.identity) as GameO
yield return new WaitForSeconds(0.5f);
// Destroy一个资源
GameObject.Destroy(tankInst);
yield return new WaitForSeconds(0.5f);
//释放无用资源
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(0.5f);
执行结果如下:
下面是统计结果:
数据描述MemoryTextureMeshMaterialGameObjectsObjects in SceneTotal Objects
Resources.Load
Instantiate
Resources.UnloadUnusedAssets
从这里我们得出如下结论:
Resouces.Load一个Prefab相对于Instantiate一个资源来说是相对轻量的一个操作,上述过程中,Resources.Load加载一个Prefab几乎没有消耗内存,而Instantiate消耗了2.5M的资源空间。Resources.Load增加了Mesh和Total Object的数量,而Instantiate增加了GameObjects,Objects In Scene和Total Objects的数量;
Destroy一个GameObject之后,内存有所减少,但是比较少,本例中减少了0.6M;Instantiate和Destroy前后Material和Texture没有还原,用以后面继续进行Instantiate之用。
若没有调用Resources.UnloadUnusedAssets,则结果如下:
统计结果如下:
数据描述MemoryTextureMeshMaterialGameObjectsObjects in SceneTotal Objects
Resources.Load
Instantiate
得出如下结论: 如果不手动执行Resources.UnloadUnusedAssets,则多余的Mesh,Material和Object不会主动释放。
2. 以AssetBundle.Load的方式加载一个Prefab,然后Instantiate一个GameObject
代码如下:
IEnumerator LoadAssets(string path)
// 清除干净以免影响测试结果
Resources.UnloadUnusedAssets();
// 等待5秒以看到效果
yield return new WaitForSeconds(5.0f);
// 创建一个WWW类
WWW bundle = new WWW(path);
yield return new WaitForSeconds(0.5f);
// AssetBundle.Load一个资源
bundle.assetBundle.Load("tank");
yield return new WaitForSeconds(0.5f);
// Instantiate一个资源出来
GameObject tankInst = Instantiate(obj) as GameO
yield return new WaitForSeconds(0.5f);
// Destroy一个资源
GameObject.Destroy(tankInst);
yield return new WaitForSeconds(0.5f);
// Unload Resources
bundle.assetBundle.Unload(false);
yield return new WaitForSeconds(0.5f);
// 释放无用资源
//Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(0.5f);
执行结果如下:
统计结果如下:
数据描述MemoryTextureMeshMaterialGameObjectsObjects in SceneTotal Objects
AssetBundle.Load
Instantiate
AssetBundle.Unload
Resources.UnloadUnusedAssets
得出如下结论: 通过WWW Load AssetBundle的方式加载一个资源时会自动加载相应的Mesh,Texture和Material,而通过Resouces.Load方式进行加载只会加载Mesh信息。因此通过AssetBundle方式加载后Instantiate一个资源的内存消耗较小,本例中AssetBundle.Load增加了2.5M的内存,而Instantiate增加了1.1M的内存。相比较Resources.Load后Instantiate的内存增量要小很多。
3. 通过静态绑定的方法来Instantiate一个资源
代码如下:
IEnumerator InstResources()
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(5.0f);
GameObject inst = GameObject.Instantiate(tank, Vector3.zero, Quaternion.identity) as GameO
yield return new WaitForSeconds(1f);
GameObject.Destroy(inst);
yield return new WaitForSeconds(1f);
//释放无用资源
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(1f);
执行结果如下:
统计结果如下:
数据描述MemoryTextureMeshMaterialGameObjectsObjects in SceneTotal Objects
Instantiate
UnloadUnused Resources
得出结论如下: 通过静态绑定的方式各种资源的加载顺序和Resources.Load的方式是一样的,一个GameObject创建时,其Component中静态绑定的GameObject只会加载Mesh信息,只有当该GameObject Instantiate出来之后才会加载Texture和Material信息。
加载资源的过程可以分为两个阶段,第一阶段是使用Resources.Load或者AssetBundle.Load加载各种资源,第二阶段是使用GameObject.Instantiate克隆出一个新的GameObject。 Load的资源类型包括GameObject, Transform, Mesh, Texture, Material, Shader和Script等各种资源,但是Resources.Load和AssetBundle.Load是有区别的。 使用Resources.Load的时候在第一次Instantiate之前,相应的Asset对象还没有被创建,直到第一次Instantiate时才会真正去读取文件创建这些Assets。它的目的是实现一种OnDemand的使用方式,到该资源真正使用时才会去创建这些资源。 而使用AssetBundle.Load方法时,会直接将资源文件读取出来创建这些Assets,因此第一次Instantiate的代价会相对较小。 上述区别可以帮助我们解释为什么发射第一发子弹时有明显的卡顿现象的出现。
然后我们再来了解一下Instantiate的过程。Instantiate的过程是一个对Assets进行Clone(复制)和引用相结合的过程,Clone的过程需要申请内存存放自己的数据,而引用的过程只需要直接一个简单的指针指向一个已经Load的资源即可。例如Transform是通过Clone出来的,Texture和TerrainData是通过引用复制的,而Mesh,Material,PhysicalMaterial和Script是Clone和引用同时存在的。以Script为例,Script分为代码段和数据段,所有需要使用该Script的GameObject使用的代码是一样的,而大家的数据有所区别,因此对数据段需要使用Clone的方式,而对代码段需要使用引用的方式来复制。 因此Load操作其实Load一些数据源出来,用于创建新对象时被Clone或者被引用。
然后是销毁资源的过程。当Destory一个GameObject或者其他实例时,只是释放实例中那些Clone出来的Assets,而并不会释放那些引用的Assets,因为Destroy不知道是否有其他人在引用这些Assets。等到场景中没有任何物体引用到这些Assets之后,它们就会成为UnusedAssets,此时可以通过Resources.UnloadUnusedAssets来进行释放。AssetBundle.Unload(false)不行,因为它只会释放文件的内存镜像,不会释放资源;AssetBunde.Unload(true)也不行,因为它是暴力的释放,可能有其他对象在引用其中的Assets,暴力释放可能导致程序错误。 另外需要注意,系统在加载新场景时,所有的内存对象都会被自动销毁,这包括了Resources.Load加载的Assets, 静态绑定的Assets,AssetBundle.Load加载的资源和Instantiate实例化的对象。但是AssetBundle.Load本身的文件内存镜像(用于创建各种Asset)不会被自动销毁,这个必须使用AssetBundle.Unload(false)来进行主动销毁。推荐的做法是在加载完资源后立马调用AssetBunble.Unload(false)销毁文件内存镜像。 下图可以帮助理解内存中的Asset和GameObject的关系。
为了不出现首次Instantiate时卡顿的现象,推荐使用AssetBundle.Load的方式代替Resources.Load的方式来加载资源;
加载完资源后立马调用AssetBunble.Unload(false)释放文件内存镜像;
Unity自身没有提供良好的内存申请和释放管理机制,Destroy一个GameObject会马上释放内存而不是进行内部的缓存,因此应用程序对频繁不用的对象如NPC,FX等进行对象池管理是必要的,减少内存申请次数;
何时进行Resources.UnloadUnusedAssets是需要讨论的一个问题。
www.520books.com
阅读(...) 评论()程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity研究院之Prefab和GameObject的正向和逆向查找引用
Unity研究院之Prefab和GameObject的正向和逆向查找引用
围观55533次
编辑日期: 字体:
我发现很多美工兄弟都爱问程序Unity3d为什么总丢材质? 我不排除U3d有BUG的情况下会丢材质?但是其实很多时候是人为操作而引起的。
1.不保存就在上传
这个操作太恐怖了,切记!!在 U3D里面你无论操作了什么,当你要上传svn的时候一定要先保存场景,Ctrl+S 切记切记!!如果不保存就上传很有可能就会丢材质。
2.我的电脑明明没事,怎么你哪里就丢材质?
我发现一个很有意思的现象,每次走到美术电脑前看它的svn工程时,我都会发现各种的“黄叹号”整个工程严重的冲突。然后程序和美术的对话就是:“这资源有用没?没用删了, 我重新更新。。。” 哈哈哈 我觉得可能只有程序员才会对冲突非常敏感吧,但我觉得这件事不能怪美术,美术是很抽象的东西,不向程序要具体到少一个分号就无法进行了。
3.管理好材质贴图
如果项目不管理好材质和贴图,后起你会发现有很多完全一样的图片只是名子不一样,但是还都在使用中。。这个很有可能是好几个美术同时在做,这样会造成资源的浪费。
4.特效丢材质
我举个实际的例子,我们项目场景和特效是两个人来做。之前总遇到场景特效莫名其妙丢材质的问题。原因就是做特效的人把特效修改了,但是做场景的又不知道,因为可能这个特效在好多场景上都在使用中。
如下图所示,在Preiject下面方的Prefab 如果拖入Hierarchy视图中,它俩是具有关联关系的,如果你直接在Project视图中修改了Prefab那么所有Hierarchy视图中关联它的Prefab都会得到修改。小改动这样是没问题的,如果发生一些比较大的改动,那么Hierarchy视图中Prefab可能就会丢失或者坏掉。但是假如你有很多场景都引用同一个Prefab,这么多场景会很难找到的。
正向在Hierarch视图中选择一个prefab,然后在右侧Inspector视图中点击Select会自动找到Project视图中的Prefab对象。那么反向如何从Project视图中找到Hierarchy视图中引用的Prefab呢?
如下图所示,Unity3d做了一个功能,在Project视图中选择一个Prefab,然后右键选择Find References In Scene ,那么此时Unity会自动帮你在当前场景中找到Hierarchy视图中引用这个Prefab的GameObject。
但是这个方法有点局限性,就是它只能找到当前场景的,假设你的这个Prefab在很多场景中都引用了,那么这样是找不到了,为了美术我决定写一个小小的工具,嘿嘿。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
[MenuItem("Assets/Check Prefab Use ?")] private static void OnSearchForReferences() { &&//确保鼠标右键选择的是一个Prefab
if(Selection.gameObjects.Length != 1)
//遍历所有游戏场景
foreach(EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
if(scene.enabled)
&&//打开场景
EditorApplication.OpenScene(scene.path);
//获取场景中的所有游戏对象
GameObject []gos = (GameObject[])FindObjectsOfType(typeof(GameObject));
foreach(GameObject go&&in gos)
&&//判断GameObject是否为一个Prefab的引用
if(PrefabUtility.GetPrefabType(go)&&== PrefabType.PrefabInstance)
UnityEngine.Object parentObject = EditorUtility.GetPrefabParent(go);
string path = AssetDatabase.GetAssetPath(parentObject);
//判断GameObject的Prefab是否和右键选择的Prefab是同一路径。
if(path == AssetDatabase.GetAssetPath(Selection.activeGameObject))
//输出场景名,以及Prefab引用的路径
Debug.Log(scene.path&&+ "&&" + GetGameObjectPath(go));
} } public static string GetGameObjectPath(GameObject obj) {
string path = "/" + obj.name;
while (obj.transform.parent != null)
obj = obj.transform.parent.gameObject;
path = "/" + obj.name + path;
return path; }
如下图所示,我就可以找到哪个场景引用了这个Prefab。 这里我没有用GameObject和Prefab的名子来判断,我觉得最好也不要用名字,因为Hierarchy视图中的名子完全可以随意修改的,如果被改了的话就肯定找不到了,而且场景那么多完全有重名的情况。
是不是很简单呢?嘿嘿。
或者还有个办法,就是运行时动态的载入Prefab,但是有些场景特效其实万全没有任何意义,仅仅是展示而已,程序也无需对它进行操作。
有了这个小工具,那么以后美术改完Prefab的时候,运行一下连带的看看某些场景上是否正常的显示了?嘿嘿嘿嘿。
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!

我要回帖

更多关于 销毁session 的文章

 

随机推荐