安装unity3d小游戏插件之后 小游戏仍然不能运行 说是安装错误还是什么的

总结使用Unity 3D优化游戏运行性能的经验
发布时间: 17:44:42
Tags:,,,,
作者:Amir Fasshihi
流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏《Shadow Blade》已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标。
以下是我们在紧凑的优化过程中提升游戏运行性能,并实现目标帧率时需要考虑的事项。
当基本游戏功能到位时,就要确保游戏运行表现能够达标。我们衡量游戏运行表现的一个基本工具是Unity内置分析器以及Xcode分析工具。使用Unity分析器来分析设备上的运行代码真是一项宝贵的功能。
我们总结了这种为将目标设备的帧率控制在60fps而进行衡量、调整、再衡量过程的中相关经验。
shadow blade()
一、遇到麻烦时要调用“垃圾回收器”(Garbage Collector,无用单元收集程序,以下简称GC)
由于具有C/C++游戏编程背景,我们并不习惯无用单元收集程序的特定行为。确保自动清理你不用的内存,这种做法在刚开始时很好,但很快你就公发现自己的分析器经常显示CPU负荷过大,原因是垃圾回收器正在收集垃圾内存。这对移动设备来说尤其是个大问题。要跟进内存分配,并尽量避免它们成为优先数,以下是我们应该采取的主要操作:
1.移除代码中的任何字符串连接,因为这会给GC留下大量垃圾。
2.用简单的“for”循环代替“foreach”循环。由于某些原因,每个“foreach”循环的每次迭代会生成24字节的垃圾内存。一个简单的循环迭代10次就可以留下240字节的垃圾内存。
3.更改我们检查游戏对象标签的方法。用“if (go.CompareTag (“Enemy”)”来代替“if (go.tag == “Enemy”)” 。在一个内部循环调用对象分配的标签属性以及拷贝额外内存,这是一个非常糟糕的做法。
4.对象库很棒,我们为所有动态游戏对象制作和使用库,这样在游戏运行时间内不会动态分配任何东西,不需要的时候所有东西反向循环到库中。
5.不使用LINQ命令,因为它们一般会分配中间缓器,而这很容易生成垃圾内存。
二、谨慎处理高级脚本和本地引擎C++代码之间的通信开销。
所有使用Unity3D编写的游戏玩法代码都是脚本代码,在我们的项目中是使用Mono执行时间处理的C#代码。任何与引擎数据的通信需求都要有一个进入高级脚本语言的本地引擎代码的调用。这当然会产生它自己的开销,而尽量减少游戏代码中的这些调用则要排在第二位。
1.在这一情景中四处移动对象要求来自脚本代码的调用进入引擎代码,这样我们就会在游戏玩法代码的一个帧中缓存某一对象的转换需求,并一次仅向引擎发送一个请求,以便减少调用开销。这种模式也适用于其他相似的地方,而不仅局限于移动和旋转对象。
2.将引用本地缓存到元件中会减少每次在一个游戏对象中使用 “GetComponent” 获取一个元件引用的需求,这是调用本地引擎代码的另一个例子。
三、物理效果
1.将物理模拟时间步设置到最小化状态。在我们的项目中就不可以将让它低于16毫秒。
2.减少角色控制器移动命令的调用。移动角色控制器会同步发生,每次调用都会耗损极大的性能。我们的做法是缓存每帧的移动请求,并且仅运用一次。
3.修改代码以免依赖“ControllerColliderHit” 回调函数。这证明这些回调函数处理得并不十分迅速。
4.面对性能更弱的设备,要用skinned mesh代替physics cloth。cloth参数在运行表现中发挥重要作用,如果你肯花些时间找到美学与运行表现之间的平衡点,就可以获得理想的结果。
5.在物理模拟过程中不要使用ragdolls,只有在必要时才让它生效。
6.要谨慎评估触发器的“onInside”回调函数,在我们的项目中,我们尽量在不依赖它们的情况下模拟逻辑。
7.使用层次而不是标签。我们可以轻松为对象分配层次和标签,并查询特定对象,但是涉及碰撞逻辑时,层次至少在运行表现上会更有明显优势。更快的物理计算和更少的无用分配内存是使用层次的基本原因。
8.千万不要使用Mesh对撞机。
9.最小化碰撞检测请求(例如ray casts和sphere checks),尽量从每次检查中获得更多信息。
四、让AI代码更迅速
我们使用AI敌人来阻拦忍者英雄,并同其过招。以下是与AI性能问题有关的一些建议:
1.AI逻辑(例如能见度检查等)会生成大量物理查询。可以让AI更新循环设置低于图像更新循环,以减少CPU负荷。
五、最佳性能表现根本就不是来自代码!
没有发生什么情况的时候,就说明性能良好。这是我们关闭一切不必要之物的基本原则。我们的项目是一个侧边横向卷轴动作游戏,所以如果不具有可视性时,就可以关闭许多动态关卡物体。
1.使用细节层次的定制关卡将远处的敌人AI关闭。
2.移动平台和障碍,当它们远去时其物理碰撞机也会关闭。
3.Unity内置的“动画挑选”系统可以用来关闭未被渲染对象的动画。
4.所有关卡内的粒子系统也可以使用同样的禁用机制。
六、回调函数!那么空白的回调函数呢?
要尽量减少Unity回调函数。即使敌人回调函数存在性能损失。没有必要将空白的回调函数留在代码库中(有时候介于大量代码重写和重构之间)。
七、让美术人员来救场
在程序员抓耳挠腮,绞尽脑汁去想该如何让每秒运行更多帧时,美术人员总能神奇地派上大用场。
1.共享游戏对象材料,令其在Unity中处于静止状态,可以让它们绑定在一起,由此产生的简化绘图调用是呈现良好移动运行性能的重要元素。
2.纹理地图集对UI元素来说尤其有用。
3.方形纹理以及两者功率的合理压缩是必不可少的步骤。
4.我们的美术人员移除了所有远处背景的网格,并将其转化为简单的2D位面。
5.光照图非常有价值。
6.我们的美术人员在一些关口移除了额外顶点。
7.使用合理的纹理mip标准是一个好主意(游戏邦注:要让不同分辨率的设备呈现良好的帧率时尤其如此)。
8.结合网格是美术人员可以发挥作用的另一个操作。
9.我们的动画师尽力让不同角色共享动画。
10.要找到美学/性能之间的平衡,就免不了许多粒子效果的迭代。减少发射器数量并尽量减少透明度需求也是一大挑战。
八、要减少内存使用
使用大内存当然会对性能产生负面影响,但在我们的项目中,我们的iPod由于超过内存上限而遭遇了多次崩溃事件。我们的游戏中最耗内存的是纹理。
1.不同设备要使用不同的纹理大小,尤其是UI和大型背景中的纹理。《Shadow Blade》使用的是通用型模板,但如果在启动时检测到设备大小和分辨率,就会载入不同资产。
2.我们要确保未使用的资产不会载入内存。我们必须迟一点在项目中找到仅被一个预制件实例引用,并且从未完全载入内存中实例化的资产。
3.去除网格中的额外多边形也能实现这一点。
4.我们应该重建一些资产的生周期管理。例如,调整主菜单资产的加载/卸载时间,或者关卡资产、游戏音乐的有效期限。
5.每个关卡都要有根据其动态对象需求而量身定制的特定对象库,并根据最小内存需求来优化。对象库可以灵活一点,在开发过程中包含大量对象,但知道游戏对象需求后就要具体一点。
6.保持声音文件在内存的压缩状态也是必要之举。
加强游戏运行性能是一个漫长而具有挑战性的过程,游戏开发社区所分享的大量知识,以及Unity提供的出色分析工具为《Shadow Blade》实现目标运行性能提供了极大帮助。(本文为游戏邦/编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦)
“0 – 60 fps in 14 days!” What we learned trying to optimize our game using Unity3D.
by Amir Fassihi
The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.
A smooth gameplay is built upon the foundations of a smooth frame rate and hitting the 60 frames per second target on the standard iPhone and iPad devices was a significant goal during the development of our upcoming action platformer game, Shadow Blade. ()
The following is a summary from the things we had to consider and change in the game in order to increase the performance and reach the targeted frame rate during the intense optimization sessions.
Once the basic game functionalities were in place, it was time to make sure the game performance would meet its target. Our main tool for measuring the performance was the built-in Unity profiler and the Xcode profiling tools. Being able to profile the running code on the device using the Unity profiler proved to be an invaluable feature.
So here goes our summary and what we learned about the results of this intense measuring, tweaking and re-measuring journey which paid out well at the end and resulted in a fixed 60fps for our target devices.
1 – Head to head with a ferocious monster called the Garbage Collector.
Coming from a C/C++ game programming background, we were not used to the specific behaviors of the garbage collector. Making sure your unused memory is cleaned up automatically for you is nice at first but soon the reality kicks in and you witness regular spikes in your profiler showing the CPU load caused by the garbage collector doing what it is supposed to do, collecting the garbage memory. This proved to be a huge issue specifically for the mobile devices. Chasing down memory allocations and trying to eliminate them became priority number one and here are some of the main actions we took:
Remove any string concatenation in code since this leaves a lot of garbage for the GC to collect.
Replace the “foreach” loops with simple “for” loops. For some reason, every iteration of every “foreach” loop generated 24 Bytes of garbage memory. A simple loop iterating 10 times left 240 Bytes of memory ready to be collected which was just unacceptable
Replace the way we checked for game object tags. Instead of “if (go.tag == “Enemy”)” we used “if (go.CompareTag (“Enemy”)”. Calling the tag property on an object allocates and copies additional memory and this is really bad if such a check resides in an inner loop.
Object pools are great, we made and used pools for all dynamic game objects so that nothing is ever allocated dynamically during the game runtime in the middle of the levels and everything is recycled back to the pool when not needed.
Not using LINQ commands since they tended to allocate intermediate buffers, food for the GC.
2 – Careful with the communication overhead between high level scripts and native engine C++ code.
All gameplay code written for a game using Unity3D is script code which in our case was C# that was handled using the Mono runtime. Any requirements to communicate with the engine data would require a call into the native engine code from the high level scripting language. This of course has its own overhead and trying to reduce such calls in game code was the second priority.
Moving objects around in the scene requires calls from the script code to the engine code and we ended up caching the transformation requirements for an object during a frame in the gameplay code and sending the request to the engine only once to reduce the call overhead. This pattern was used in other similar places other than the needs to move and rotate an object.
Caching references to components locally would eliminate the need to fetch a component reference using the “GetComponent” method on a game object every time which is another example for a call into the native engine code.
3 – Physics, Physics and more Physics.
Setting the physics simulation timestep to the minimum possible. For our case we could not set it lower than 16 milliseconds.
Reducing calls to character controller move commands. Moving the character controller happens synchronously and every call can have a significant performance cost. What we did was to cache the movement requests per frame and apply them only once.
Modifying code to not rely on the “ControllerColliderHit” callbacks. It proved that these callbacks are not handled very quickly.
Replacing the physics cloth with a skinned mesh for the weaker devices. The cloth parameters can play important roles in performance also and it pays off to spend some time to find the appropriate balance between aesthetics and performance.
Ragdolls were disabled so that they were not part of the physics simulation loop and only enabled when necessary.
“OnInside” callbacks of the triggers need to be assessed carefully and in our case we tried to model the logic without relying on them if possible.
Layers instead of tags! Layers and tags can be assigned to objects easily and used for querying specific objects, however, layers have a definite advantage at least performance wise when it comes to working with collision logic. Quicker physics calculations and less unwanted newly allocated memory are the basic reasons.
Mesh colliders are definitely a no-no.
Minimize collision detection requests like ray casts and sphere checks in general and try to get as much information from each check.
4 – Let’s make the AI code faster!
We use artificial intelligence for the enemies that try to block our main ninja hero and fight with him. The following topics needed to be covered regarding AI performance issues:
A lot of physical queries are generated from AI logic like visibility checks. The AI update loop could be set to something much lower than the graphics update loop to reduce CPU load.
5 – Best performance is achieved from no code at ALL!
When nothing happens, performance is good. This was the base philosophy for us to try and turn anything not necessary at the moment off. Our game is a side scroller action game and so a lot of the dynamic level objects can be turned off when they are not visible in the scene.
Enemy AI was turned off when far away using a custom level of detail scheme.
Moving platforms and hazards and their physics colliders were turned off when far away.
Built in Unity “animation culling” system was used to turn off animations on objects not being rendered.
Same disabling mechanism used for all in level particle systems.
6 – Callback! How about empty callbacks?
The Unity callbacks needed to be reduced as much as possible. Even the empty callbacks had performance penalties. There is no reason for having empty callbacks but they just get left in the code base sometimes in between a lot of code rewrite and refactoring.
7 – The mighty Artists to the rescue.
Artists can always magically help out the hair-pulling programmer trying to go for a few more frames per second.
Sharing materials for game objects and making them static in Unity causes them to be batched together and the resulting reduced draw calls are critical for good mobile performance.
Texture atlases helped a lot especially for the UI elements.
Square textures and power of two with proper compression was a must.
Being a side-scroller enabled our artists to remove all far background meshes and convert them to simple 2D planes instead.
Light maps were highly valuable.
Our artists removed extra vertices during a few passes.
Proper texture mip levels were a good decision especially for having a good frame rate on devices with different resolutions.
Combining meshes was another performance friendly action by the artists.
Our animator tried to share animations between different characters if it was possible.
A lot of iterations on the particles were necessary to find the aesthetic/performance balance. Reducing number of emitters and trying to reduce transparency requirements were among the major challenges.
8 – The memory usage needs to be reduced, now!
Using a lot of memory of course has negative performance related effects but in our case we experienced a lot of crashes on iPods due to exceeding memory limits which was a much more critical problem. The biggest memory consumers in our game were the textures.
Different texture sizes were used for different devices, especially textures used in UI and large backgrounds. Shadow Blade uses a universal build but different assets get loaded when the device size and resolution is detected upon startup.
We needed to make sure un-used assets were not loaded in memory. We had to find out a little late in the project that any asset that was only referenced by an instance of a prefab and never instantiated was fully loaded in memory.
Stripping out extra polygons from meshes helped.
We needed to re-architect the lifecycle management of some assets a few times. For example tweaking the load/unload time for the main menu assets or end of level assets or game music.
Each level needed to have its specific object pool tailored to its dynamic object requirements and optimized for the least memory needs. Object pools can be flexible and contain a lot of objects during development, however, they need to be specific once the game object requirements are known.
Keeping the sound files compressed in memory was necessary.
Game performance enhancement is a long and challenging journey and we had a fun time experiencing a small part of this voyage. The vast amount of knowledge shared by the game development community and very good profiling tools provided by Unity were what made us reach our performance targets for Shadow Blade.(source:)
CopyRight Since 2010 GamerBoom All rights reserved &&闽ICP备&号-1欢迎大家访问游戏开发网,有您更美好!
请记住本站网址,一定要搜藏哦亲!
Unity3D插件2dtoolkit游戏开发实战碰撞检测功能的实现以及障碍物的随机摆放详解
Unity3D插件2dtoolkit游戏开发实战碰撞检测功能的实现以及障碍物的随机摆放详解
围观459次 评论关闭 编辑日期: 字体:
貌似有一段时间没更新2dtoolkit系列了,这段时间一直在忙着其他事情,今天开始继续这个插件系列的教程,网上搜索,貌似关于这个插件的教程无非还是跟官方的教程很类似,有的甚至都没有自己照着亲手实践一遍就直接Copy,对这样博客的文章感觉起步到任何作用,对自己没有什么深刻的理解,对他人来说也只是搜出来一份相同品,也没什么收获,还都浪费了大家的时间!所以我决定通过这个小游戏项目来驱动式的学习这个2d插件。
但如果学习2dtoolkit插件仅仅是看官方的文档操作,不通过自己去动手实践,不注意细节可能是会碰到许多问题,这不我今天是深有感触哇!一直到吃晚饭之前都是摸索一个问题,就是关于碰撞检测的问题,我在小花上添加了自定义的不规则碰撞器,这里可以参考如何创建带有碰撞器的精灵集合的,其实在那儿操作的时候就留了一个“隐患”,没注意一个细节,导致今天很纠结,其实也不是没注意了,只是那时候也不知道要注意这么一点!
还是回到之前的创建精灵集合,按照之前的操作,来到这一步
切记在选择自定义Collider的时候要勾选上Convex,这是为什么呢?或许有人要问。原因:
meshcollider不能和非凸边形发生碰撞
Mesh Colliders cannot collide with each other unless they are marked as Convex. Therefore, they are most useful for background objects like environment geometry.
我猜想可能是跟碰撞算法有关,具体底层的碰撞算法是怎么写的,我只能是猜测,计算的是凸多边形之间的碰撞检测,这里自定义碰撞边缘,默认的就是MeshCollider碰撞,BoxCollider碰撞是矩形框碰撞,其实也就是特殊的凸多边形了,但无疑碰撞的没那么精确而已。就是因为这个,我看论坛还有人家博客上写的这个2dtoolkit教程都没有这个提示,这让新手会很纠结!这点我比较欣赏雨凇大哥,写博客写的很详细!赞一个!但搜关于这个插件的教程,他也还没写,所以就只能自己摸索了,哈哈,正好也给我了这么个自己机会!画好不规则边框以后,点击Commit提交,然后
下面我们来进行碰撞检测,
//鼠标左击控制主角精灵移动
IEnumerator OnMouseDown()
print("MouseDown");
Vector3 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
Vector3 mScreenPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPosition.z);
Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(mScreenPosition);
//鼠标左击
while (Input.GetMouseButton(0))
mScreenPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPosition.z);
Vector3 pos = offset + Camera.main.ScreenToWorldPoint(mScreenPosition);
pos.z = 0;
transform.position =
yield return new WaitForFixedUpdate();
void OnTriggerEnter(Collider other)
if (other.tag == "flower")
print("Trigger触发了");
void OnTriggerStay(Collider other)
if (other.tag == "flower")
print("Trigger触发中了");
void OnTriggerExit(Collider other)
if (other.tag == "flower")
print("Trigger结束了");
123456789101112131415161718192021222324252627282930313233343536373839404142
//鼠标左击控制主角精灵移动&&&&IEnumerator OnMouseDown()&&&&{&&&&&&&&print("MouseDown");&&&&&&&&Vector3 screenPosition = Camera.main.WorldToScreenPoint(transform.position);&&&&&&&&Vector3 mScreenPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPosition.z);&&&&&&&&Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(mScreenPosition);&&&&&&&&//鼠标左击&&&&&&&&while (Input.GetMouseButton(0))&&&&&&&&{&&&&&&&&&&&&mScreenPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPosition.z);&&&&&&&&&&&&Vector3 pos = offset + Camera.main.ScreenToWorldPoint(mScreenPosition);&&&&&&&&&&&&pos.z = 0;&&&&&&&&&&&&transform.position = pos;&&&&&&&&&&&&yield return new WaitForFixedUpdate();&&&&&&&&}&&&&}&&&&&void OnTriggerEnter(Collider other)&&&&{&&&&&&&&if (other.tag == "flower")&&&&&&&&{&&&&&&&&&&&&print("Trigger触发了");&&&&&&&&}&&&&&&&&&&&&}&&&&&void OnTriggerStay(Collider other)&&&&{&&&&&&&&if (other.tag == "flower")&&&&&&&&{&&&&&&&&&&&&print("Trigger触发中了");&&&&&&&&}&&&&}&&&&&void OnTriggerExit(Collider other)&&&&{&&&&&&&&if (other.tag == "flower")&&&&&&&&{&&&&&&&&&&&&print("Trigger结束了");&&&&&&&&}&&&&}
这里设置花的tag为flower,然后拖动小龙进行跟花碰撞,哦,忘了说一点了,还记得我之前转载过公司的基础面试题么,虽然遭到一些自认为是老手的人的“嘲讽”,评论说有必要整理这么简单的问题吗?现在看来我觉得还是有必要的,至少我从中知道了一点,碰撞检测的条件,必须具有刚体和碰撞器,或许好多人就知道必须有碰撞器,可能会忽略了刚体,我亲自试验过,还真是很被容易忽视,然后就又纠结怎么碰撞不了的呢?虽然去公司都会问一些高级的问题:一般都是NGUI有没有很熟,有没有扩展;有没有内存优化;会不会网络资源更新;项目中遇到过的难题以及解决办法?会写Shader么?会用Android和IOS第三方插件么?以前的项目你都负责过那些?你对角色动作换装熟悉么?如果有一些大公司或许还会问图形学的相关知识。但我感觉这些都是在你已经牢牢掌握了基础知识的前提下才有必要进一步掌握的,所以说基础你都牢牢掌握了么?细节还是不能忽视的!!!废话不多说了,进行碰撞检测
看到能够成功的进行碰撞检测,大功告成!
但后来问题又出现了,就是要得拖动小龙主动去碰撞花朵,才能检测出碰撞,如果不人为拖动,就没有出现碰撞检测,又觉得纳闷了,后来发现了碰撞的条件,可以对比这这个表格,碰撞列表
看官方的论坛,有人也碰到过这问题.
如果想两个物体只发生物理碰撞效果,就是不会穿透,就不勾选IsTrigger选项
然后碰撞的物理效果
会发现小龙的最都被撞歪了,花也被“推”到后面去了,哇咔咔,这就起到物理效果,
如果想要这种情况的话,就是IsTrigger不被勾选的情况,然后碰撞就用:
void OnCollisionEnter(Collision collider)
collider.gameObject.tag == “name”;
Destroy(collider.gameObject);
但我们想要的效果并不是这样,我们是需要能检测出碰撞事件的,所以就勾选其中的一个IsTrigger即可,就能触发OnTriggerEnter()方法
看下面检测到了碰撞,代码跟上图一样!就不重复了!
被碰撞的问题搞的纠结了两天,总算是告一段落,写下来就是花朵的随机摆放,也比较简单。
首先在场景中做一个预设,包含一上一下两朵花,然后拖放四个到场景中
这里用脚本做一个随机的位置摆放,上下波动在[-0.8f,0],左右波动在[-0.1f,0.1f],这样使得游戏更逼真!
using UnityE
using System.C
/// &summary&
/// 让花朵的位置随机,挂在doubleflower上
/// &/summary&
//小花朵上下位置范围是[-0.82,0]
public class randompos : MonoBehaviour {
public float minPositionX;
public float terPositionX;
//波动范围
// Use this for initialization
void Start () {
minPositionX = -6;
terPositionX = 0;
rannum = 0.1f;
//执行一次位置的随机变动
float ran = GetRandomNum(-0.82f, 0f);
float ran1 = GetRandomNum(-rannum, rannum);
//print(ran);
transform.localPosition = new Vector3(transform.localPosition.x+ran1, ran, transform.localPosition.z);
// Update is called once per frame
void Update () {
movespeed = speed * Time.deltaT
transform.Translate(Vector3.left * movespeed, Space.World); //向左移动
if (transform.localPosition.x & minPositionX)
float ran = GetRandomNum(-0.82f, 0f); //上下波动范围
float ran1 = GetRandomNum(-rannum, rannum);//左右波动范围
print("上下波动:"+ran+",左右波动:"+ran1);
transform.localPosition = new Vector3(terPositionX+ran1, ran, transform.localPosition.z);
float GetRandomNum(float min,float max)
return Random.Range(min, max);
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
using UnityEngine;using System.Collections;/// &summary&/// 让花朵的位置随机,挂在doubleflower上/// &/summary&&//小花朵上下位置范围是[-0.82,0]&public class randompos : MonoBehaviour {&&&&&public float speed;&&&&private float movespeed;&&&&&public float minPositionX;&&&&public float terPositionX;&&&&public float rannum;//波动范围& // Use this for initialization void Start () {&&&&&&&&minPositionX = -6;&&&&&&&&terPositionX = 0;&&&&&&&&rannum = 0.1f;&&&&&&&&&//执行一次位置的随机变动&&&&&&&&float ran = GetRandomNum(-0.82f, 0f);&&&&&&&&float ran1 = GetRandomNum(-rannum, rannum);&&&&&&&&//print(ran);&&&&&&&&transform.localPosition = new Vector3(transform.localPosition.x+ran1, ran, transform.localPosition.z); }
// Update is called once per frame void Update () {&&&&&&&&&movespeed = speed * Time.deltaTime;&&&&&&&&transform.Translate(Vector3.left * movespeed, Space.World); //向左移动&&&&&&&&if (transform.localPosition.x & minPositionX)&&&&&&&&{&&&&&&&&&&&&float ran = GetRandomNum(-0.82f, 0f); //上下波动范围&&&&&&&&&&&&float ran1 = GetRandomNum(-rannum, rannum);//左右波动范围&&&&&&&&&&&&print("上下波动:"+ran+",左右波动:"+ran1);&&&&&&&&&&&&transform.localPosition = new Vector3(terPositionX+ran1, ran, transform.localPosition.z);&&&&&&&&} }&&&&&float GetRandomNum(float min,float max)&&&&{&&&&&&&&return Random.Range(min, max);&&&&}&}
本文固定链接:
转载请注明:
作者:游戏开发
欢迎大家访问游戏开发网!
如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!
您可能还会对这些文章感兴趣!

我要回帖

更多关于 unity3d插件安装 的文章

 

随机推荐