-
关于延迟:
Unity
延迟执行一段代码的较为优雅的方式
在
Unity
中,延时执行一段代码或者一个方法或者几个方法
的情况非常普遍。
一般会用到
Inv
oke
和
InvokeRepeating
方法。顾名思义,第一个是执行一次,第二个是重复执行。
看下定义:
void
Invoke(string methodName, float time);
第一个参数是方法名
(
注意是字符串形式),并不是更方便的委
托。第二个是延时多少秒。只执行一次。
voidInvokeRepeating(string methodName,
float time, float repeatRate);
InvokeRe
peating
第二个参数是延时多少秒后开始,第三个参数是每次执行间隔的秒数。<
/p>
你有没有发现这两个方法有个弊端,就是必须输入方法名!也就
是我说,如果我想延时执行某段代码,必
须把代码放在某个方法里,然后使用这
Invoke
或者
InvokeRepeati
ng
方法来执行。
这样对于上下文变
量、属性的引用就会尤为不便,而且不能传参数
!!!
尼玛,要
他还有何用?
我猜你一定用过这样的方法。没错,“协同”,
听起来还挺高大上的名字啊。
用
St
artCoroutine
来执行一个以
IEnumerato
r
为返回值的方法,
通常用于异步下载啊,
等比较耗时又不能
让游戏卡死的情况。
< br>还有一个好的类
WaitForSeconds
,
对,
它就一个构造函数,
用来延时的
(延时??????比万艾可好用?
比希爱力好用?)。
好了不废话了,以下是我自用的延时方法,放在一个类里以静态方法存在。可
以在任何时候任何地方延时
指定秒数的代码。
usingUnityEngine;
tions;
using System;
public class
DelayToInvoke : MonoBehaviour
{
public static
IEnumeratorDelayToInvokeDo(Action action, float
delaySeconds)
{
yield return
new WaitForSeconds(delaySeconds);
action();
}
}
如何使用呢?
比如我点击
NGUI
的一个
Button
,则
voidOnClick()
{
StartCoroutine(oInvokeDo(() =>
{
vel(
“
Option
”
);
},
0.1f));
}
看到了吧
vel(
< br>“
Option
”
);
就是想要延时执行的代码段。
你可以写很长很
长。
Action
,随便搞。
iTween
的使用
移动模型时候用到的几个核心方法如下:
()
:
让模型移动到一个位置,
它
的底层函数是通过动态的修
改模型每一帧的
on
完成的,
所以它会百分之百到达目标点,
不会出现误差
。
om():
它和上面的一样,
p>
()
是将模型移
动到目标位置,而
om()
是将模型从目标位置移动到原始位
置。
d()
和
()
底层实现一样,大家可以去
看源码。处理移动时采用的是<
/p>
ate
也就是
API
的平移,
这样在处理移动的时候可能会出现一些误差,但是效果好点。
date():
和
()<
/p>
差不多,
只是它需要放在
循环或者
Update()
中。
有了核心的移动方法后,我们就来了解
iTween
强大的
核心参数,与事件。移
动方法的参数都差不多,所以这里我就以
MoveTo
来做例子。直接上代码。
绑定在需要移动的游戏对象身上。
1
using UnityEngine;
2
using tions;
3
4
public class
Move : MonoBehaviour
5
{
6
7
8
9
10
11
12
//
键值对儿的形式保存
iTween
所用到的参数
Hashtableargs = new Hashtable();
void Start()
{
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//
这里是设置类型,
iTween
的类型又很多种,在源码中的枚举
Ea
seType
中
//
例如移动的特效,先震动在移动、先后退在移动、先加速在变速、等等
(
//
移动的速度,
(
//
移动的整体时间。如果与
speed
共存那么优先
speed
(
//
这个是处理颜色的。可以看源码的那个
枚举。
(
//
延迟执行时间
(
//
移动的过程中面朝一个点
(
//
三个循环类型
none
loop pingPong (
一般循环来回
)
//(
//(
(
//
处理移动过程中的事件。
<
/p>
//
开始发生移动时调用
Animati
onStart
方法,
5.0
表示它的
参数
(
(
/
/
设置接受方法的对象,默认是自身接受,这里也可以改成别的对象接受,
//
那么就得在接收对象的脚本中实现
AnimationStart
方法。
(
//
移动结束时调用,参数和上面类似
(
(
(
//
移动中调用,参数和上面类似
(
(
(
//
x y z
标示移动的位置。
(
(
(
57
58
59
60
61
62
63
}
//
当然也可以写
Vector3 <
/p>
//(
//
最终让改对象开始移动
(gameObject,args);
64
//
对象移动中调用
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
}
void AnimationUpdate(bool
f)
{
}
//
对象开始移动时调用
void AnimationStart(float f)
{
}
//
对象移动时调用
void AnimationEnd(string f)
{
}
(
(
(
p>
在看看
iTween
中的寻路算法,其实非
常非常的简单,我们几乎不用做任何事
情。
如下图所示,
我们能清楚的看到编辑了一个简单的寻路,
我们通过
< br>iTween
来实现小人跑步到终点。
绑在主角身上即可。
1
using UnityEngine;
2
using tions;
3
4
public class Path :
MonoBehaviour {
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//
让模型开始寻路
}
(gameObject,args);
void
Start ()
{
Hashtableargs =
new Hashtable();
(
//
< br>设置类型为线性,线性效果会好一些。
(
//
设置寻路的速度
(<
/p>
//
是否先从原始位置走到路径中第一个点的位置
(
//
是否让模型始终面朝
当面目标的方向,拐弯的地方会自动旋转模型
//
如果你发现你的模型在寻路的时候始终都是一个方向那么一定要打开这个
(
//
设置路径的点
//
路径寻路中的所有点
public Transform [] paths;
28
29
30
31
32
33
34
35
36
37
}
void
OnDrawGizmos()
{
}
//
在
scene
视图中绘制出路径与线<
/p>
ne(paths,);
th(paths,);
运行后即可看到主角自动寻路的效果。
如果你仔细阅读到这里你可能会想到,
iTween
做的东西
有点
像
()
Vector3
.Lerp() lookAt()
等等这类的方法。
假设不使用
iTween
这个类就用源生的
API
其实也可以实现上述
的所有效果。只有
iTween
帮我们封装的更好一些,平滑过
渡的效果更好一些,而且还能增加一
些特效。只是这些特效与动画全都是
iTween
通过数学的方法计算出来。因为
底层它们
使用的也是简单的移动旋转
API
中的方法。我觉得寻路的话可
以使用
Unity
自带的方法(因为是官方提供的),处理一些
简单的动画使用
iTween
还是挺不错的,因为更加形象。<
/p>
截图
Unity3d
之截图方法
分类:
Unity3D
2013-11-28 17:13
1014
人阅读
评论
(2)
收藏
举报
AnYuanLzhunityunity3d
截屏
下面是我总结的、在
u3d
中的,三种截屏方法:
1
、使用
Application
类下的
Cap
tureScreenshot
方法。
[csharp]
view
plaincopy
1.
void
CaptureScreen()
2.
{
3.
eScreenshot(
, 0);
4.
}
这个方法,截取的是某一帧时整
个游戏的画面,或者说是全屏截图吧。
a
、不能针对某一个相机(
camera
)的画面,进行截图
。
b
、对局部画面截图,实现起来不
方便,效率也低,不建议在项目中使用:
虽然
CaptureScreenshot
这个方法呢,本身是不要做到这一点的。
但是我们可以走曲线救
国的路线来实现它。
思路是这样的:
p>
你可以先用这个方法截图一个全屏,
然后通过路径获取
到这个截图;
接下来就通过相关的图形类来,
取得这
个截图的局部区域并保存下来,
这样就
能得到一个局部截图了。
在这里我就不实现它了,
不过有兴趣的可以试试,
肯定是可以实现
的。
<
/p>
2
、这第二个截图的方法是,使用
Tex
ture2d
类下的相关方法,也可实现截图功能。
[csharp]
view
plaincopy
1.
///
2.
/// Captures
the screenshot2.
3.
///
4.
///
5.
///
截图的区域,左下角为
p>
o
点
6.
Texture2D CaptureScreenshot2(Rect rect)
7.
{
8.
//
先创建一个的空纹理,大小可根据实现需要来设置
9.
Texture2D screenShot =
new
Texture2D((
int
),
(
int
),
24,
false
);
10.
11.
//
读取屏幕像素信息并存储为纹理数据,
12.
xels(rect, 0, 0);
13.
();
14.
15.
//
然后将这些纹理数据,成一个
p
ng
图片文件
16.
byte
[] bytes = ToPNG();
17.
string
filename = th +
;
18.
llBytes(filename, bytes);
19.
(
< br>string
.Format(
截屏了一张图片
: {0}
, filename));
20.
21.
//
最后,我返回这个
Textur
e2d
对象,这样我们直接,所这个截图图示在游戏中,当然这
个根据自己的需求的。
22.
return
screenShot;
23.
}
截全屏(如下图
,
注:有
ui
):
CaptureScreenshot2( new Rect( *0f, *0f,
*1f,
*1f));
截中间
4
分之(如下图)
:
CaptureScreenshot2( new Rect(
*0.25f, *0.25f,
*0.5f, *0.5f));
这里使用了几个
< br>Texture2d
类的方法,使用上也有一些要注意的地方,自己看吧。
当然,
这个方法也不要到实现针对某个相机
的截图的功能。
不过关键接口已经出现了,
它就
是
xels()
,这段就不说了,接着往下看吧!
p>
3
、这第三个
方法,最牛了,可以针对某个相机进行截图。
这样的话,我就
可截下,我的
Avatar
在游戏中场景中所看的画面了,
p>
UI
界面(用一个专门
的
< br>camera
显示)什么的是不应该有的。要做到这一点,我们应该将分出一个<
/p>
camera
来专
门显示
ui
界面,用另一个
camera
相机来场景显示场景画面。然后,我们只对场景相机进
行截屏就是了。
所以这关键点就是:
如何实现对某个相机进行截屏了。
这里用到一个新的类
是
RenderTexture
。
代码如下:
[csharp]
view
plaincopy
1.
///
2.
///
对相机截图。
3.
///
4.
///
5.
///
要被截屏的相机
6.
///
截屏的区域
7.
Texture2D CaptureCamera(Camera camera,
Rect rect)
8.
{
9.
//
创建一个
RenderTexture
对象
10.
RenderTexture rt =
new
RenderTexture((
int
),
(
int
),
0);
11.
//
临时设置相关相机的
targe
tTexture
为
rt,
并手动渲染相关相机
12.
Texture =
rt;
13.
();
14.
//ps: ---
如果这样加上第二个相机,可以实现只截
图某几个指定的相机一起看到的
图像。
15.
//ps: Texture = rt;
16.
//ps: ();
17.
//ps: ---------------------------------
-----------------------------
-----
18.
19.
//
激活这个
rt,
并从中中读取像素。
20.
= rt;
21.
Texture2D screenShot =
new
Texture2D((
int
),
(
int
),
24,
false
);
22.
xels(rect, 0, 0);
//
注:这个时候,它
是从
中读取像素
23.
();
24.
25.
//
重置相关参数,以使用
camera
继续在屏幕上显示
26.
Texture =
null
;
27.
//ps: Texture = null;
28.
=
null
;
// JC:
added to avoid errors
29.
y(rt);
30.
//
最后将这些纹理数据,成一个
p
ng
图片文件
31.
byte
[] bytes = ToPNG();
32.
string
filename = th +
;
33.
llBytes(filename, bytes);
34.
(
< br>string
.Format(
截屏了一张照片
: {0}
, filename));
35.
36.
return
screenShot;
37.
}
多的我就不说了,相关知识自己去找资料吧,因为我也不懂!
直接上图了。
无
ui
的全屏图:
只有
ui
的全屏图:
有
ui
有场
景的全屏图(只指定这两个相机哦,相关提示在代码的
“//ps”
中):
碰撞检测
相关
API
:
1
、
Ray
PointToRay(Vector3 pos)
返回一条射线
Ray
从摄像机到
屏幕指定一个点
2
、
Ray
rtPointToRay(Vector3 pos)
返回一条射线
Ray
从摄像机到
视口(视口之外无效)指定一个点
3
、
Ray
射线类
4
、
RaycastHit
光线投射碰撞信息
5
、
bool t(Vector3
origin, Vector3 direction, float distance, int
layerMas
k)
当光线投射与任何碰撞器交叉时为真,否则为假。
bool t(Ray ray, Vector3 direction,
RaycastHit out hit, float distanc
e, int
layerMask)
在场景中投下可与所有碰撞器
碰撞的一条光线,并返回碰撞的细节信息
()
。
bool t(Ray ray, float
distance, int layerMask)
当光线投射与任何碰撞器交叉时为真,否则为假。
bool t(Vector3 origin, Vector3
direction, RaycastHit out hit,float
d
istance, int layerMask)
当光线投射与任何碰撞器交叉时为真,否则为假。
注意:如果从一个球型体的内部到外部用光线投射,返回为假。
参数理解:
origin :
在世界坐标中射线的起始点
direction:
射线的方向
distance:
射线的长度
hit:
使用
c
#中
out
关键字传入一个空的
碰撞信息类,然后碰撞后赋值。可以得到碰撞
物体的
trans
form,rigidbody,point
等信息。
layerMask:
只选定
Layermask
层内的碰撞器,其它
层内碰撞器忽略。
选择性的碰撞
6
、
RaycastHit[]
RaycastAll(Ray ray, float distance, int layerMask)
投射一条光线并返回所有碰撞,也就是投射光线并返回一
个
RaycastHit[]
结构体。
-
-
-
-
-
-
-
-
-
上一篇:数学名词翻译
下一篇:常见聚合物的玻璃化转变温度和表面张力(DOC)