-
矢量图素材
-
位图素材
http://bbs.9ria.com/thread-417976-1-1.html
MonoBehaviour.Update 更新
当MonoBehaviour启用时,其Update在每一帧被调用。
MonoBehaviour.FixedUpdate固定更新
当MonoBehaviour启用时,其 FixedUpdate在每一帧被调用。处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同)
Update和FixedUpdate的区别:
update跟当前平台的帧数有关,而FixedUpdate是真实时间,所以处理物理逻辑的时候要把代码放在FixedUpdate而不是Update.
Update是在每次渲染新的一帧的时候才会调用,也就是说,这个函数的更新频率和设备的性能有关以及被渲染的物体(可以认为是三角形的数量)。在性能好的机器上可能fps 30,差的可能小些。这会导致同一个游戏在不同的机器上效果不一致,有的快有的慢。因为Update的执行间隔不一样了。
而FixedUpdate,是在固定的时间间隔执行,不受游戏帧率的影响。有点想Tick。所以处理Rigidbody的时候最好用FixedUpdate。
PS:FixedUpdate的时间间隔可以在项目设置中更改,Edit->ProjectSetting->time 找到Fixedtimestep。就可以修改了。
Update和LateUpdate的区别
在圣典里LateUpdate被解释成一句话:LateUpdate是在所有Update函数调用后被调用。这可用于调整脚本执行顺序。例如:当物体在Update里移动时,跟随物体的相机可以在LateUpdate里实现。这句我看了云里雾里的,后来看了别人的解释才明白过来。
LateUpdate是晚于所有Update执行的。例如:游戏中有2个脚步,脚步1含有Update和LateUpdate,脚步2含有Update,那么当游戏执行时,每一帧都是把2个脚步中的Update执行完后才执行LateUpdate 。虽然是在同一帧中执行的,但是Update会先执行,LateUpdate会晚执行。
现在假设有2个不同的脚本同时在Update中控制一个物体,那么当其中一个脚本改变物体方位、旋转或者其他参数时,另一个脚步也在改变这些东西,那么这个物体的方位、旋转就会出现一定的反复。如果还有个物体在Update中跟随这个物体移动、旋转的话,那跟随的物体就会出现抖动。 如果是在LateUpdate中跟随的话就会只跟随所有Update执行完后的最后位置、旋转,这样就防止了抖动。
做一个相机跟随主角的功能时,相机的位置调整写在LateUpdate(),老是不明白,看官方的SmoothFollow相机跟随写在Update()中
DestroyImmediate立即对对像进行销毁;
Destroy销毁场景中的物体,但内存中还存在,当令它需要销毁时,只是给一个标识。而内存中它依然是存在的,只有当内存不够,或一段时间没有再次被引用时(或者更多合理的条件满足),机制才会将它销毁并释放内存。
//因此通过它可以让游戏对象按照一个常速进行旋转,而不是依赖于它的帧频: function Update() { tranform.Rotate(0, 5 * Time.deltaTime, 0); } //同样地移动效果: function Update() { transform.Translate(0, 0, 2 * Time.deltaTime); } //如果想要一个值根据每帧的变化而变化(增加或减少) ,你应该使用 Time.deltaTime来乘以这个值。这样才能使得变化的效果依赖于单位时间,而不是帧频。这不仅使得游戏的运行独立于帧频,也使得运动的效果符合现实。 //同理,要让灯光的照射范围在每秒使半径增加 2个单位,可进行如下编码: function Update() { light.range += 2.0 * Time.deltaTime; } //但是在通过force来处理rigidbody时,一般情况下不要乘以 Time.deltaTime,因为 Unity引擎已经为你进行了处理 2 IEnumerator wait(int seconds){ yield return new WaitForSeconds(seconds); } StartCoroutine(wait(2)); // 在Update() 中调用好像无效 //在JS中可以直接用 yield WaitForSeconds(3); //3 定时器的使用 using UnityEngine; using System.Collections; public class NewBehaviourScript : MonoBehaviour { // Use this for initialization void Start () { InvokeRepeating("LaunchProjectile", 1,5);//1秒后调用LaunchProjectile () 函数,之后每5秒调用一次 } // Update is called once per frame void Update () { if (Input.GetButton ("Fire")) { CancelInvoke(); } } void LaunchProjectile () { print("hello"); } }
http://blog.csdn.net/huang9012/article/details/38492937
,yield return是“停止执行方法,并且在下一帧从这里重新开始”
IEnumerator SayHelloFiveTimes() { Yield return 0; Debug.Log("Hello"); Yield return 0; Debug.Log("Hello"); Yield return 0; Debug.Log("Hello"); Yield return 0; Debug.Log("Hello"); Yield return 0; Debug.Log("Hello"); } //This will do the exact same thing as the above function! IEnumerator SayHello5Times() { for(inti = 0; i < 5; i++) { Debug.Log("Hello"); Yield return 0; } }
每一帧输出“Hello”,无限循环。。。
通过在一个while循环中使用yield,你可以得到一个无限循环的协程,这几乎就跟一个Update()循环等同。。。
//Once started, this will run until manually stopped or the object is destroyed IEnumerator SayHelloEveryFrame() { while(true) { //1. Say hello Debug.Log("Hello"); //2. Wait until next frame Yield return 0; }//3. This is a forever-loop, goto 1 }
void Start () { StartCoroutine("loop"); } IEnumerator loop() { while (true) { Debug.Log("aa"); yield return new WaitForSeconds(1); } }
计时
...不过跟Update()不一样的是,你可以在协程中做一些更有趣的事:
IEnumerator CountSeconds() { int seconds = 0; while(true) { for(float timer = 0; timer < 1; timer += Time.deltaTime) Yield return 0; seconds++; Debug.Log(seconds +" seconds have passed since the Coroutine started."); } }
这个方法突出了协程一个非常酷的地方:方法的状态被存储了,这使得方法中定义的这些变量都会保存它们的值,即使是在不同的帧中。还记得这个教程开始时那些烦人的计时器变量吗?通过协程,我们再也不需要担心它们了,只需要把变量直接放到方法里面!
StartCoroutine("loop"); StartCoroutine(loop()); StopAllCoroutines();
。。。那我们怎么终止其中的一个协程呢?在这个例子里,这是不可能的,如果你想要终止某一个特定的协程,那么你必须得在开始协程的时候将它的方法名作为字符串,就像这样:
StopCoroutine("loop"); <p align="left"><span><span class="comment">If you start a Coroutine by name...</span><span> </span></span><span> </span></p><p align="left"><span>StartCoroutine(<span class="string">"FirstTimer"</span><span>); </span></span><span> </span></p><p align="left"><span>StartCoroutine(<span class="string">"SecondTimer"</span><span>); </span></span><span></span></p><p align="left"><span><span class="comment">//You can stop it anytime by name!</span><span> </span></span><span> </span></p><p align="left"><span>StopCoroutine(<span class="string">"FirstTimer"</span><span>); </span></span></p><p></p>
抽象化一个协程的第一个方法是给它传递参数,协程作为一个函数方法来说,它自然能够传递参数。这里有一个协程的例子,它在特定的地方输出了特定的信息。
嵌套的协程
在此之前,我们yield的时候总是用0(或者null),仅仅告诉程序在继续执行前等待下一帧。协程最强大的一个功能就是它们可以通过使用yield语句来相互嵌套。
眼见为实,我们先来创建一个简单的Wait()程序,不需要它做任何事,只需要在运行的时候等待一段时间就结束。
接下来我们要编写另一个协程,如下:
第二个方法用了yield,但它并没有用0或者null,而是用了Wait()来yield,这相当于是说,“不再继续执行本程序,直到Wait程序结束”。
现在,协程在程序设计方面的能力要开始展现了。
在最后一个例子中,我们就来看看协程如何像创建方便的计时器一样来控制对象行为。协程不仅仅可以使用可计数的时间来yield,它还能很巧妙地利用任何条件。将它与嵌套结合使用,你会得到控制游戏对象状态的最强大工具。
对于下面这个简单脚本组件,我们可以在Inspector面板中给targetPosition和moveSpeed变量赋值,程序运行的时候,该对象就会在协程的作用下,以我们给定的速度运动到给定的位置。
这样,这个程序并没有通过一个计时器或者无限循环,而是根据对象是否到达指定位置来yield。
按指定路径前进
我们可以让运动到某一位置的程序做更多,不仅仅是一个指定位置,我们还可以通过数组来给它赋值更多的位置,通过MoveToPosition() ,我们可以让它在这些点之间持续运动。
把Wait()程序加进来,这样就能让我们的对象在某个点就可以选择是否暂停下来,就像一个正在巡逻的AI守卫一样,这真是锦上添花啊!
给某个 GameObject 绑上以下的代码:
function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }
可以直接load并返回某个类型的Object,前提是要把这个资源放在Resource命名的文件夹下,Unity不关有没有场景引用,都会将其全部打入到安装包中。Resources.Load();
Resources.Load是本地动态加载资源所用的方法,也就是你想动态加载的时候才用到它,比如子弹,特效,某些实时更换的图片什么的,建议此文件夹不要放太多东西,在打包的时候,它会单独把里面的所有东西都集中打包到一起,不管里面有没有你用的东西,所以大多数资源应该是自己建文件放置
http://www.xuanyusong.com/archives/2405/
即将perfab资源打成 asset bundle 放在服务器或本地磁盘,然后使用WWW模块get 下来,然后从这个bundle中load某个object。AssetBundle
http://www.mamicode.com/info-detail-312000.html
这种方式只在editor范围内有效,游戏运行时没有这个函数,它通常是在开发中调试用的
Resources的方式需要把所有资源全部打入安装包,这对游戏的分包发布(微端)和版本升级(patch)是不利的,所以unity推荐的方式是不用它,都用bundle的方式替代,把资源达成几个小的bundle,用哪个就load哪个,这样还能分包发布和patch,但是在开发过程中,不可能没更新一个资源就打一次bundle,所以editor环境下可以使用AssetDatabase来模拟,这通常需要我们封装一个dynamic resource的loader模块,在不同的环境下做不同实现。
用于本地持久化保存与读取的类,类似HashTable以键值对的形式将数据保存在文件中
http://www.jianshu.com/p/1d93ece664e2
在Unity3D脚本中,有几个Unity3D自带的事件函数按照预定的顺序执行作为脚本执行。其执行顺序如下:
编辑器(Editor)
第一次场景加载(First Scene Load)
这些函数会在一个场景开始(场景中每个物体只调用一次)时被调用。
注意:当一个场景被添加到场景中,所有脚本上的Awake()和OnEable()函数将会被调用在Start()、Update()等它们中任何函数被调用之前。自然的,当一个物体在游戏过程中被实例化时这不能被强制执行。
第一帧更新之前(Before the first frame update)
对于那些被添加到场景中的物体,所有脚本上的Start()函数将会在它们中任何的Update()函数之前被调用,自然的,当一个物体在游戏过程中被实例化时这不能被强制执行。
在帧之间(In between frames)
更新顺序(Update Order)
当你在跟踪游戏逻辑和状态,动画,相机位置等的时候,有几个不同的事件函数你可以使用。常见的模式是在Update()函数中执行大多数任务,但是也有其它的函数你可以使用。
渲染(Rendering)
协同程序(Coroutines)
正常的协同程序更新是在Update函数返回之后运行。一个协同程序是可以暂停执行(yield)直到给出的依从指令(YieldInstruction )完成,写成的不同运用:
销毁(When the Object is Destroyed)
退出游戏(When Quitting)
这些函数会在你场景中所有的激活的物体上调用:
脚本的生命周期流程图
Mipmap是一个功能强大的纹理技术,它可以提高渲染的性能以及提升场景的视觉质量。它可以用来解决使用一般的纹理贴图会出现的两个常见的问题:
Mipmap就可以解决上面那两个问题。当加载纹理的时候,不单单是加载一个纹理,而是加载一系列从大到小的纹理当mipmapped纹理状态中。然后OpenGl会根据给定的几何图像的大小选择最合适的纹理。Mipmap是把纹理按照2的倍数进行缩放,直到图像为1x1的大小,然后把这些图都存储起来,当要使用的就选择一个合适的图像。这会增加一些额外的内存。在正方形的纹理贴图中使用mipmap技术,大概要比原先多出三分之一的内存空间。
鼠标拖动:
using UnityEngine; using System.Collections; public class Lu : MonoBehaviour { public Camera cam; // We need to actually hit an object RaycastHit hitt = new RaycastHit(); // Use this for initialization void Start() { } // Update is called once per frame void Update() { Ray ray = cam.ScreenPointToRay(Input.mousePosition); Physics.Raycast(ray, out hitt, 100); // Debug.DrawLine(cam.transform.position, ray.direction,Color.red); if (null != hitt.transform) { print(hitt.point);//鼠标点击的坐标 } } }
if (Input.GetAxis("Mouse ScrollWheel") > 0) { Ray ray = cam.ScreenPointToRay(Input.mousePosition); Physics.Raycast(ray, out hit, 100); if (null != hit.transform) { hit.collider.gameObject.transform.localScale += new Vector3(0.1f, 0.1f, 0.1f); } } if (Input.GetAxis("Mouse ScrollWheel") < 0) { Ray ray = cam.ScreenPointToRay(Input.mousePosition); Physics.Raycast(ray, out hit, 100); if (null != hit.transform) { hit.collider.gameObject.transform.localScale -= new Vector3(0.1f, 0.1f, 0.1f); } }
点积:cos
叉积(向量积):两个向量的叉积与这两个向量的和垂直
前几日有同事总是不时的问我什么是矢量图什么是位图及它们之间有什么区别……今天咱们就共同的看看什么是矢量图什么是位图及它们之间的区别。
矢量图素材
位图素材
1、先从概念说起:矢量图是根据几何特性来绘制图形,是用线段和曲线描述图像,矢量可以是一个点或一条线,矢量图只能靠软件生成,矢量图文件占用内在空间较小,因为这种类型的图像文件包含独立的分离图像,可以自由无限制的重新组合;
位图图像也称为点阵图像,位图使用我们称为像素的一格一格的小点来描述图像。
2、最大的区别,矢量图形与分辨率无关,可以将它缩放到任意大小和以任意分辨率在输出设备上打印出来,都不会影响清晰度,而位图是由一个一个像素点产生,当放大图像时,像素点也放大了,但每个像素点表示的颜色是单一的,所以在位图放大后就会出现咱们平时所见到的马赛克状。
3、位图表现的色彩比较丰富,可以表现出色彩丰富的图象,可逼真表现自然界各类实物;而矢量图形色彩不丰富,无法表现逼真的实物,矢量图常常用来表示标识、图标、Logo等简单直接的图像。
4、位图的文件类型很多,如*.bmp、*.pcx、*.gif、*.jpg、*.tif、photoshop的*.psd等;
矢量图形格式也很多,如AdobeIllustrator的*.AI、*.EPS和SVG、AutoCAD的*.dwg和dxf、Corel DRAW的*.cdr等。
5、由于位图表现的色彩比较丰富,所以占用的空间会很大,颜色信息越多,占用空间越大,图像越清晰,占用空间越大;由于矢量图形表现的图像颜色比较单一,所以所占用的空间会很小。
6、经过软件矢量图可以很轻松的转化为位图,而位图要想转换为矢量图必须经过复杂而庞大的数据处理,而且生成的矢量图质量也会有很大的出入。
RaycastHit hit; //range 射线的长度,即攻击范围,maskTarget敌方单位的mask,只攻击敌方单位 if (Physics.Raycast(unit.thisT.position, unit.thisT.forward, out hit, range, maskTarget)) { Unit targetTemp = hit.collider.gameObject.GetComponent(); if (targetTemp != null && targetTemp.HPAttribute.HP > 0) { target = targetTemp; if (attackMode == _AttackMode.StopNAttack) { if (attackMethod != _AttackMethod.Melee) unit.StopAnimation(); unit.StopMoving(); } } }
//返回相交球的所有碰撞体 Collider[] cols = Physics.OverlapSphere(unit.thisT.position, range, maskTarget); //if(cols!=null && cols.Length>0)Debug.Log(cols[0]); if (cols.Length > 0) { Collider currentCollider = cols[Random.Range(0, cols.Length)]; UnittargetTemp = currentCollider.gameObject.GetComponent(); if (targetTemp != null && targetTemp.HPAttribute.HP > 0) { target = targetTemp; if (attackMode == _AttackMode.StopNAttack) { if (attackMethod != _AttackMethod.Melee) unit.StopAnimation(); unit.StopMoving(); } } }
Collider[] cols=Physics.OverlapSphere(unit.thisT.position,range, maskTarget); //if(cols!=null && cols.Length>0)Debug.Log(cols[0]); if(cols.Length>0) { Collider currentCollider=cols[0]; foreach(Collider col in cols) { Quaternion targetRot=Quaternion.LookRotation(col.transform.position-unit.thisT.position); if(Quaternion.Angle(targetRot, unit.thisT.rotation)) Unit targetTemp=currentCollider.gameObject.GetComponent(); if(targetTemp!=null &&targetTemp.HPAttribute.HP>0) { target=targetTemp; if(attackMode==_AttackMode.StopNAttack) { if(attackMethod!=_AttackMethod.Melee)unit.StopAnimation(); unit.StopMoving(); } break; } } }
Shaders define both how an object looks by itself (its material properties) and how it reacts to the light. Because lighting calculations must be built into the shader, and there are many possible light & shadow types, writing quality shaders that “just work” would be an involved task. To make it easier, Unity has Surface Shaders, where all the lighting, shadowing, lightmapping, forward vs. deferred rendering things are taken care of automatically.
This document describes the pecularities of Unity’s lighting & rendering pipeline and what happens behind the scenes of Surface Shaders.
How lighting is applied and which Passes of the shader are used depends on which Rendering Path is used. Each pass in a shader communicates its lighting type via Pass Tags.
ForwardBase
and ForwardAdd
passes are used.Deferred
pass is used.PrepassBase
and PrepassFinal
passes are used.Vertex
, VertexLMRGBM
and VertexLM
passes are used.ShadowCaster
pass is used.ForwardBase
pass renders ambient, lightmaps, main directional light and not important (vertex/SH) lights at once. ForwardAdd
pass is used for any additive per-pixel lights; one invocation per object illuminated by such light is done. See Forward Rendering for details.
If forward rendering is used, but a shader does not have forward-suitable passes (i.e. neither ForwardBase
nor ForwardAdd
pass types are present), then that object is rendered just like it would in Vertex Lit path, see below.
Deferred
pass renders all information needed for lighting (in built-in shaders: diffuse color, specular color, smoothness,world space normal, emission). It also adds lightmaps, reflection probes and ambient lighting into the emission channel. See Deferred Shading for details.
PrepassBase
pass renders normals & specular exponent; PrepassFinal
pass renders final color by combining textures, lighting & emissive material properties. All regular in-scene lighting is done separately in screen-space. See Deferred Lighting for details.
Since vertex lighting is most often used on platforms that do not support programmable shaders, Unity can’t create multiple shader variants internally to handle lightmapped vs. non-lightmapped cases. So to handle lightmapped and non-lightmapped objects, multiple passes have to be written explicitly.
Vertex
pass is used for non-lightmapped objects. All lights are rendered at once, using a fixed function OpenGL/Direct3D lighting model (Blinn-Phong)VertexLMRGBM
pass is used for lightmapped objects, when lightmaps are RGBM encoded (PC and consoles). No realtime lighting is applied; pass is expected to combine textures with a lightmap.VertexLMM
pass is used for lightmapped objects, when lightmaps are double-LDR encoded (mobile platforms). No realtime lighting is applied; pass is expected to combine textures with a lightmap.