存档

‘游戏开发’ 分类的存档

GUI Texture

2011年1月24日 没有评论

GUI Textures are displayed as flat images in 2D. They are made especially for user interface elements, buttons, or decorations. Their positioning and scaling is performed along the x and y axes only, and they are measured in Screen Coordinates, rather than World Coordinates.

GUI贴图是显示在2D视图里的平面图。它们主要被用来制作用户接口元件,按键,或者装饰。它们的位置和缩放只由x和y轴来决定,它们的单位是以屏幕坐标,而不是空间坐标来描述的。

The GUI Texture Inspector
GUI贴图检视图
Please Note: Unity 2.0 introduced UnityGUI, a GUI Scripting system. You may prefer creating user interface elements with UnityGUI instead of GUI Textures. Read more about how to use UnityGUI in the GUI Scripting Guide.
请注意:Unity2.0中介绍UnityGUI为一种GUI脚本系统。你可以能更喜欢使用UnityGUI来制作用户接口元件,而不是GUI贴图。想了解更多关于UnityGUI,请阅读GUI Scripting Guide。
Properties
属性

Texture
贴图 Reference to the Texture that will be used as the texture’s display.
参考将被用于贴图显示的Texture。
Color
颜色 Color that will tint the Texture drawn on screen.
绘制在屏幕上的贴图所着的颜色。
Pixel Inset
像素插入 Used for pixel-level control of the scaling and positioning of the GUI Texture. All values are measured relative to the position of the GUI Texture’s Transform.
用于控制GUI贴图缩放和位置的像素级别的控制。所有的数值的测量都是依据GUI贴图形变的位置。
X
X Left-most pixel position of the texture.
贴图的最左端像素位置。
Y
Y Bottom-most pixel position of the texture.
贴图的最下端像素位置。
Width
宽度 Right-most pixel position of the texture.
贴图的最右端像素位置。
Height
高度 Top-most pixel position of the texture.
贴图的最上端像素位置。
Left Border
左边界 Number of pixels from the left that are not affected by scale.
在左端,不受缩放影响的边框的像素个数。
Right Border
右边界 Number of pixels from the right that are not affected by scale.
在右端,不受缩放影响的边框的像素个数。
Top Border
上边界 Number of pixels from the top that are not affected by scale.
在上端,不受缩放影响的边框的像素个数。
Bottom Border
下边界 Number of pixels from the bottom that are not affected by scale.
在下端,不受缩放影响的边框的像素个数。

Details
细节
To create a GUITexture:
创造一个GUI贴图:
1. Select a Texture in the Project View
2. Choose GameObject->Create Other->GUI Texture from the menu bar
在项目视图中选择一个贴图
从菜单从菜单栏中选择GameObject->Create Other->GUI Texture
GUI Textures are perfect for presenting game interface backgrounds, buttons, or other elements to the player. Through scripting, you can easily provide visual feedback for different “states” of the texture — when the mouse is hovering over the texture, or is actively clicking it for example. Here is the basic breakdown of how the GUI Texture is calculated:
GUI贴图适合于在游戏中,对用户的游戏接口背景,按键和其他元件。通过脚本,你可以轻松的提高贴图的不同状态的可视化反馈—当鼠标略过贴图时候,或者被点击激活后。这里是GUI贴图如何计算的基本分类:

GUI Textures are laid out according to these rules
GUI贴图的摆放是根据他们的规则。

The GUI elements seen here were all created with GUI Textures
这里看到的GUI元件都是由GUI贴图制作的。

Borders
边界
The number of pixels that will not scale with the texture at each edge of the image. As you rarely know the resolution your game runs in, chances are your GUI will get scaled. Some GUI textures have a border at the edge that is meant to be an exact number of pixels. In order for this to work, set the border sizes to match those from the texture.
边界指的是图像的每一个边框,这个边框的像素数量是不随着图片缩放而变化的。尽管你很少知道你所运行的游戏的分辨率,你仍有机会调整缩放你的GUI。GUI贴图都一个拥有固定像素个数的边框在边缘处。要让这些起作用,就为这些贴图设置合适的边框尺寸。

Pixel Inset
像素插入
The purpose of the Pixel Inset is to prevent textures from scaling with screen resolution, and keeping thim in a fixed pixel size. This allows you to render a texture without any scaling. This means that players who run your game in higher resolutions will see your textures in smaller areas of the screen, allowing them to have more screen real-estate for your gameplay graphics.
像素插入的目的是为防止贴图以屏幕分辨率缩放过程中,让他们保持在一个固定的像素尺寸。这允许你不用任何缩放,就能渲染一个贴图。这意味着运行游戏的玩家在一个高分辨率的屏幕中,看到你的贴图只是这个屏幕的一块区域,允许他们为你的显卡节约更多的资源。
To use it effectively, you need to set the scale of the GUI Texture’s Transform to (0, 0, 0). Now, the Pixel Inset is in full control of the texture’s size and you can set the Pixel Inset values to be the exact pixel size of your Texture.
为了有效地使用,你需要设置GUI贴图的变形缩放参数到(0,0,0)。现在,像素插入功能已经可以实现贴图尺寸的全部控制功能了,你可以设置像素插入数值为你的贴图的精确的像素数值。

Hints
提示
• The depth of each layered GUI Texture is determined by its individual Z Transform position, not the global Z position.
• GUI Textures are great for making menu screens, or pause/escape menu screens.
• You should use Pixel Inset on any GUI Textures that you want to be a specific number of pixels for the width and height.
每一层的GUI贴图都由独立的Z变形位置来检测,而不是全局的Z位置。
GUI贴图适合于制作菜单屏幕,或者停止/退出菜单屏幕。
如果你想是一个指定高度和宽度的GUI贴图,你也可以使用像素插入来实现。

分类: 游戏开发 标签:

Unity脚本入门(2)

2010年12月16日 没有评论

前面我们提到,可以通过写代码的方式指定变量(而不是通过Unity界面),如何做到呢?上面按下空格时告诉聚光灯聚焦到Cube上,我们是在SpotLight脚本中做一个显式的变量,将Cube拖放上去.而在代码中主要有2种方法去实现:
1.使用对象的名称(name)
2.使用对象的标签(tag)

1.对象名称
可以从Hierarchy面板上看到对象的名称.用GameObject.Find()函数来使这些名称作为参数.因此,我们可以这样写:
function Update(){
if(Input.GetButtonDown(“Jump”))
{
var newTarget = GameObject.Find(“Cube”).transform;
GetComponent(SpotLight).target = newTarget;
}
}
注意,以上没有出现显式的变量.
2.对象标签
对象标签是一个字符串,用来识别一个组件.在Inspector面板中点击Tag按钮查看内建的标签.我们也可以创建自己的标签.GameObject.FindWithTag()函数能通过具体的标签寻找组件并返回一个字符串作为参数.
function Update(){
if(Input.GetButtonDown(“Jump”))
{
var newTarget = GameObject.FindWithTag(“fang”).transform;
GetComponent(SpotLight).target = newTarget;
}
}
7.实例
我们要在运行时创建(create)对象就要用到Instantiate函数.让我们来实现如何在每次按下开火按钮(鼠标左键或Ctrl键)后通过实例化一个新的对象.需要思考以下几点:
1.哪个物体做我们的实例?
2.在哪儿实例化?
关于第一个问题,最好的办法就是显式变量.这样我们就可以随时通过拖放来改变我们的实例对象.至于在哪儿实例化,我们只要实现当按下开火键时,在用户的当前位置创建一个对象即可.实例化函数有3个参数:1.我们要建立的对象.2.对象的位置坐标.3.对象的旋转位置.完整的代码如下:
var newObject : Transform;
function Update(){
if(Input.GetButtonDown(“Fire1”)){
Instantiate(newObject, transform.position, transform.rotation);
}
}
要记住,transform.position和transform.rotation是附加这个脚本的物体的位置.我们这里假设为主相机.一般情况下,将要被实例化的对象设置为预设(prefab),我们现将Cube设置为预设.
-首先,让我们创建一个预置.Assets->Create->Prefab.命名为Cube.
-从Hierarchy面板中选取Cube拖放到Project面板的Cube上.
-创建一个脚本并命名为Create,并把上面的代码加进去.
-把这个脚本赋予相机,并将Cube预设赋予脚本变量.
-运行.移动相机并按下开火键,你能看到新的Cube出现.
8.调试
调试是发现和修正你的代码中人为错误的技巧,Unity中提供了Debug类,我们现在看看Debug.Log()函数.
Log()函数允许用户发送信息到Unity的控制台.这样做的原因可能包括:
1.在运行时要验证某部分代码是否达成.
2.报告变量的状态.
我们现在使用Log()函数,当用户点击开火按钮时,发送一个消息到Unity控制台.
-打开创建的脚本并在”Instantiate”代码内”if”处添加如下代码:
Debug.Log(“Cube created”);
-运行.点击开火键,我们能看到Unity界面下方显式”Cube created”.
Watch
另外一个有用的功能是用于调试私有变量.这使得当Debug模式被选中时Inspector面板中的变量,但它不能被编辑.为了证明这一点,我们将显式一个私有变量作为Cube实例的计数器.我们在脚本中加入两行内容,1.添加私有变量cubeCount.2.当一个cube实例创建后增加这个变量
完整代码如下:
var newObject : Transform;
private var cubeCount = 0;
function Update(){
if(Input.GetButtonDown(“Fire1”))
{
Instantiate(newObject, transform.position, transform.rotation);
Debug.Log(“Cube created”);
cubeCount++;
Debug.Log(cubeCount);
}
}
9.常见脚本类型
每当一个新脚本被创建,默认情况下将包含Update()函数.这里我们讲解几个其他常见的函数.
FixedUpdate()
在这个函数体中的代码每隔固定的间隔执行.它通常在Rigibody中有力的作用的时候被用到.如:
// Apply a upwards force to the rigibody every frame
function FixedUpdate(){
rigidbody.AddForce(Vector3.up);
}
Awake()
这里的代码将被用作初始化.
Start()
这个函数在Update()之前,但在Awake()之后执行.Start()函数和Awake()函数的不同点在于Start()函数仅在脚本启用时候执行(Inspector面板中的复选框被选中).
OnCollisionEnter()
当游戏对象的碰撞脚本与另一个游戏对象碰撞时执行这个函数内的代码.
OnMouseDown()
当鼠标在一个载有GUI元素(GUIElement)或碰撞器(Collider)的游戏对象里按下时执行该函数体内的代码.
// Loads the level named “SomeLevel” as a response
// to the user clicking on the object
function OnMouseDown(){
Application.LoadLevel(“SomeLevel”);
}
OnMouseOver()
当鼠标悬停在一个GUI元素或碰撞器的对象上时,执行该函数体内的代码.如:
// Fades the red component of the material to zero
// while the mouse is over the mesh
function OnMouseOver(){
renderer.material.color.r -= 0.1 * Time.deltaTime;
}

分类: 游戏开发 标签:

Unity脚本入门(1)

2010年12月16日 没有评论

在Unity中脚本是必不可少的.因为他将定义你游戏的各种行为.这个教程将介绍javaScript的基本使用.
1.目标
在Unity中,脚本是用来界定用户在游戏中的行为(或规则).Unity推荐使用的编程语言是JavaScript,同时也支持C#或Boo.
2.前提
本教程的重点是Unity脚本基础,前提是你已经熟悉了Unity的界面(如果不是,你可以阅读UnityGUI教程).为了使脚本更容易理解,最好有个支持JavaScript语法高亮的代码编辑器,它会将关键字用醒目的方式显示出来.可以使用SubEthaEdit编辑器.
3.命名规范
开始前,先说下Unity的一些规范.
变量 – 首写为小写字母.变量用来存储游戏状态中的任何信息.
函数 – 首写为大写字母.函数是一个代码块,在需要的时候可以被重复调用.
类 – 首写为大写字母.可以被认为是函数的库.
当阅读范例时注意首写字母,将有助于你更好的理解对象之间的关系.
4.用户输入
我们第一个例子是在场景中实现一个简单的移动.
设置场景
-启动Unity.创建一个用来移动的平面.GameObject->CreateOther->Plane.在Inspector面板中设置Position为”0,0,0″.
-创建一个Cube.GameObject->CreateOther->Cube.坐标为”0,1,0″.
-我们都知道现实世界里物体成像靠的是光反射,那么我们这里也是需要光线的.GameObject->CreateOther->PointLight.坐标为”0,5,0″.
-保存.快捷键为Ctrl+s.
我们的第一个脚本
我们打算移动用户的视线,这需要通过控制主相机的位置来实现.我们就要写一个脚本,然后把脚本和相机结合起来.
-创建一个空脚本.Assets->Create->JavaScript并命名为”Move”.重命名快捷键为F2.
-双击打开脚本Move.默认包含Update()函数.将我们的代码加入这个函数,他将在每一帧执行一次.
我们需要用transform来改变相机的位置,用到Translate这个函数,他有x,y,z三个参数.我们加入以下代码:
function Update(){
transform.Translate(Input.GetAxis(“Horizontal”),0,Input.GetAxis(“Vertical”));
}
Input.GetAxis()函数返回一个从-1到1之间的值,如横轴上左半轴为-1到0,右半轴为0到1.如果需要,我们可以通过Edit->ProjectSettings->Input中重定义按键映射.
连接脚本
脚本写完了,如何让他起作用呢?我们需要把脚本赋予物体才行.
-点击希望应用脚本的物体对象.这里对我们而言就是相机.从Hierarchy面板中选中它.
-在菜单中选择Components->Scripts->Move,这样我们便从Inspector面板中看到相机中添加了Move这个组件.(我们也可以用鼠标把脚本拖拽到物体对象上)
点击运行,我们即可前后左右来控制相机移动了.
DeltaTime
放在Update()函数中的代码是按照帧来执行的.如果我们需要物体的移动按照时间秒来执行.为了实现这一目标,我们需要将Input.GetAxis()函数的返回值乘以Time.deltaTime:
var speed = 5;
function Update(){
var x = Input.GetAxis(“Horizontal”) * Time.deltaTime * speed;
var y = Input.GetAxis(“Vertical”) * Time.deltaTime * speed;
transform.Translate(x, 0, z);
}
这里的speed为显式变量,可以在Inspector面板中看到.我们可以在使用中随时调整它的值,很方便.
5.连接变量
Unity允许在界面上拖拽(drag and drop)的方式赋脚本.快捷方便.这里,我们将涉及连接变量的概念.
-在场景中添加一个聚光灯.GameObject->CreateOther->SpotLight.Position为”0,5,0″,Rotation为”90,0,0″.
-创建一个JavaScript脚本,命名为”SpotLight”.
我们想让聚光灯照向主相机.我们可以使用transform.LookAt()这个函数.
如何使用这个函数呢?我们需要创建一个显式变量.在SporLight脚本中写入如下代码:
var target : Transform;
function Update(){
transform.LookAt(target);
}
-把脚本赋予聚光灯对象.记得怎样赋予吗?要么在菜单栏Component中添加,要么鼠标拖放.之后,”target”变量就出现在Inspector面板里了.
-将Hierarchy面板中的主相机对象拖放到Target变量上.如果我们想让聚光灯照向其他物体,我们也可以将其他物体拖放上去,只要是Transform类型的即可.
-运行.你可以看到聚光灯一直照向主相机.
6.访问组件
一个游戏对象可能有多个脚本或其他组件.它将不可避免的要访问其他组件的函数或变量.Unity中通过GetComponent()函数来实现这个目的.我们现在要实现按下空格键后让聚光灯照向Cube.
我们考虑一下这个步骤:1.监视空格键被按下.2.空格键按下后聚光灯照向Cube.由于SporLight脚本中有target变量,我们只需要为这个变量设定新的值就可以了.
-创建一个脚本,命名为Switch,添加如下代码:
var switchToTarget : Transform;
function Update(){
if(Input.GetButtonDown(“Jump”))
GetComponent(SpotLight).target = switchToTarget;
}
注意GetComponent()的参数,它将返回一个参数给SpotLight脚本,我们就可以用它来访问”target”变量.
-添加Switch脚本到聚光灯对象,并将Cube拖放到Inspector面板中的switchToTarge变量上.
-运行.按下空格后,聚光灯将照向Cube.

分类: 游戏开发 标签:

关于贴图动画的一些经验

2010年12月15日 没有评论

原文:
uthor: Joachim Ante – Extended by TomLong74

1 Description
2 Usage
3 Example
4 JavaScript – AnimatedTextureExtendedUV.js
[edit] Description

This script extends the capabilities of the original AnimatedTexureUV.js. This allows many animation skins or animation states to be stored in the same texture. They can be updated at run time to play the new skin or new animation state via SetSpriteAnimation();
[edit] Usage

Attach this script to the object that has a material with the animation cell-sheet texture. From your other script call this script’s SetSpriteAnimation() function with the new parameters:
colCount: the total number of columns in the animation cell-sheet;
rowCount: the total number of rows in the animation cell-sheet;
rowNumber: the row where this animation will start;
colNumber: the column where this animation will start;
totalCells: the number of cells in this animation;
fps: the number of cells (frames) per second the animation will play;
[edit] Example


Example function call: SetSpriteAnimation(4,4,1,0,4,12); Should animate the 4 green cells starting with the left most cell and at a speed of 12 cells per second.
[edit] JavaScript – AnimatedTextureExtendedUV.js

//vars for the whole sheet
var colCount : int = 4;
var rowCount : int = 4;

//vars for animation
var rowNumber : int = 0; //Zero Indexed
var colNumber : int = 0; //Zero Indexed
var totalCells : int = 4;
var fps : int = 10;
var offset : Vector2; //Maybe this should be a private var

//Update
function Update () { SetSpriteAnimation(colCount,rowCount,rowNumber,colNumber,totalCells,fps); }

//SetSpriteAnimation
function SetSpriteAnimation(colCount : int,rowCount : int,rowNumber : int,colNumber : int,totalCells : int,fps : int){

// Calculate index
var index : int = Time.time * fps;
// Repeat when exhausting all cells
index = index % totalCells;

// Size of every cell
var size = Vector2 (1.0 / colCount, 1.0 / rowCount);

// split into horizontal and vertical index
var uIndex = index % colCount;
var vIndex = index / colCount;

// build offset
// v coordinate is the bottom of the image in opengl so we need to invert.
offset = Vector2 ((uIndex+colNumber) * size.x, (1.0 – size.y) – (vIndex+rowNumber) * size.y);

renderer.material.SetTextureOffset (“_MainTex”, offset);
renderer.material.SetTextureScale (“_MainTex”, size);
}
中文的已经有人翻译出来了,大体意思是多。我在使用的过程中的经验:
1,添加cube到场景中;
2,添加材料到cube上;
3,将cube的shader设置为Tranparent/diffuse;
4,将贴图拉到cube上;
5,将贴图的Tiling的x,改成1/frame,frame表示,小贴图的个数;
6,脚本等,就不说了,就是有一个问题,发现,调用脚本动画时候,Time.time已经运转,那么就不是从第一帧开始执行了,我的解决方案是在Start()中获取一个起始时间,然后在脚本动画函数中,减去这个时间。
7,现在发现的问题是,贴图和cube的契合度,会出现,画质损失,或者,在最上面出现最下面的一些像素点。

分类: 游戏开发 标签:

unity圣典

2010年12月15日 没有评论

推荐一个unity手册汉化的网站:unity圣典
有很多志愿者一起翻译官方文档。这样会比较正规,比较有错误,可以被揪出。

分类: 游戏开发 标签:

Unity–预设(Prefabs)(转)

2010年11月30日 没有评论

预设是一个存储在工程视图中可重复利用的游戏物体。它可以被插入到任意数量的场景中,亦可在多次出现在同一场景中。当你添加一个预设到场景中,你就创建了一个它的实例(instance)。所有预设实例都与原始预设相关联,且本质上就是原始预设的一个克隆。
不论在你的工程中存在多少实例,当你对预设作了任何改变后,你将看到这种改变被应用到所有的实例上。不论你的预设是单一的一个游戏物体或者是一组游戏物体,在预设的变换层次中所作的任何改变都将被应用到它的实例上。

创建预设

为了创建预设,你需要建一个新的空预设。这个空预设部不包含任何物体,并且你不能创建它的一个实例。你可将它想象为空的容器,里面空间需要游戏物体数据来填充。

一个新的空预设,它不能被实例化,除非你使用游戏物体来填充它

为了填充预设,你需要利用场景中已创建的游戏物体。下面是精确的步骤。
� 在工程视图中,选择一个你要放置预设的文件夹
� 从主菜单中选择Assets->Create->Prefab,或者从工程视图的上下文菜单中选择
Create->Prefab
� 命名该预设
� 在层次视图(Hierarchy view)中,选择你要放入预设的游戏物体
� 将它们从层次使用中拖放到工程视图中在你执行了上述步骤后,游戏物体和它子物体都将被拷贝到预设中。那么,预设可以在多个实例中被重复使用了。在层次中的原始物体现在已经成了该预设的一个实例。

实例化预设(Prefab Instances)

为了在当前场景中创建一个预设的实例,从工程视图中拖动预设到场景或层次视图中。这将从预设中拷贝所有父物体和所有的子物体。这些游戏物体与预设相连,在工程视图中将使用蓝色的文本来显示它们。

其中三个物体是预设的实例

继承(Inheritance)

继承意味着当预设改变时,这些改变也将被应用到所有与之相连的物体上。例如,如果你添加一个脚本到一个预设,那么所有该预设的实例都将包含该脚本。然而你也可以修改单个实例的属性而不会破坏与预设的联系。一个链接物体检视面板中的所有公有属性都有一个复选框。这个复选框是一个重载标记(override flag)。如果该属性的重载标记被启用,表示该属性将不会受到预设改变的影响。这允许你修改实例物体并使得它们不同于它们的预设,而且又不会破坏它与预设之间的联系。

一个实例物体和非继承

一个实例物体和非继承

预设链接的去除和复位

当你在监视面板中修改一个属性的时候,该属性的重载标记会自动启用。任何对已有属性的改变都不会打断与预设的联系。然而有一些改动将断开它,下面是保持预设的基本规则:
�不能添加一个新的组件到一个实例上
�不能从一个实例上移除一个组件
�不能使用其他游戏物体作为实例的子物体如果你这样做,你将看到一个警告消息出现要求你确认。当一个实例与预设断开后,对预设的修改将不会影响到这个游戏物体。如果你特意或是意外的断了实例的连接,你可以应用你的改变到预设并重新建立该连接。这将使得预设和所有的实例都发生改变。

导入预设

当你放置了一个网格资源到你的资源文件夹中时,Unity 将自动导入该文件并生成一些看起来与预设相似东西。但它们并不是预设,只是简单的资源文件。

注意资源文件图标与预设图标是有点不同的

这个资源在场景中作为一个游戏物体被初始化。可以在该游戏物体上添加或移除组件。然而你不能将任何改变应用到资源自身上因为这需要添加一些数据到该资源物体上!如果要创建需要重用的物体,你应该将资源实例作为预设。
当你已经创建了一个资源实例,可以创建一个新的空预设并拖动游戏物体到该预设上。现在你拥有了一个连接到该物体的标准预设。
下面给出了一些详细的步骤:
� 从工程视图中拖动一个资源文件到场景或层次视图中。
� 修改该资源(例如,添加脚本,子物体,组件等等)
� 创建一个新的空预设。从菜单中选择Assets->Create->Prefab,或者从工程视图的上
下文菜单中选择Create->Prefab
� 从层次视图中拖动该物体到预设上。

分类: 游戏开发 标签:

Unity3d导致蓝屏

2010年11月23日 没有评论

我用的机器是小黑R400,双显卡,独立的是ATI 的HD3470,集成的自然是Intel的X4500.一般情况下,我都用3470.装了Unity3D之后,也确实可以用, 不过在某种情况下,却出现恐怖的情况,只要一运行Unity,就会蓝屏。这个问题困扰了很久。起初以为是SVN的缘故。因为,我重装了系统后,不装SVN,是ok的。不过后来证实不对,因为,我又装了SVN,结果还是可以共存。

因为提醒的蓝屏缘故跟ATI显卡有关系。所以,逐步怀疑到驱动,于是切换了4500,结果原来一开Unity就蓝屏死机的事情,就消失了。看来应该是驱动的缘故,跟显卡应该也没有太大的关系。还要验证这个想法。

分类: 游戏开发 标签:

Input.GetMouse

2010年11月22日 没有评论

在unity中,检测鼠标输入,使用Input.GetMouseDown(n)、Input.GetMouse(n)以及Input.GetMouseUp(n)。GetMouseDown和GetMouseUp检测鼠标按下和松开(这里是一种跳变,),GetMouse在官方文档上说的不是很清楚,其实它可以用来检测一种状态“鼠标按下了”(状态)(不是鼠标移动)。

分类: 游戏开发 标签:

Overview: Performance Optimization性能优化[转]

2010年11月18日 没有评论

1.使用静态类型

当使用JavaScript很重要的优化是使用静态类型替代动态类型。Unity使用一种技术叫做类型推理的技术来自动转换JavaScript为静态类型脚本。

var foo = 5;

上面例子中的foo将自动被推断为一个整数值。因此,Unity可能使用大量的编辑时间进行优化,而不使用耗时的动态名称变量查找等。这就是为什么Unity的JavaScript执行平均速度是其他JavaScript的20倍的原因之一。

唯一的问题是有时不是所有的东西都能做类型推断,Unity将会为这些变量重新使用动态类型。通过这样,编写JavaScript代码很简单,但也会使代码运行速度变慢。

看个例子:

function Start ()
{
var foo = GetComponent(MyScript);
foo.DoSomething();
}

这里foo将是动态类型,因此呼叫函数DoSomething必须要较长的时间,因为foo的类型未知,它必须弄明白是否支持DoSomething函数,如果支持,调用函数。

function Start ()
{
var foo : MyScript = GetComponent(MyScript);
foo.DoSomething();
}

这里我们强制foo为指定类型,你将获得更好的性能。

2.使用#pragma strict

现在问题是,你通常不会意识到你在使用动态类型。#pragma strict可以解决这个问题!简单的添加#pragma strict在脚本顶部,之后Unity将禁用脚本的动态类型,强制你使用静态类型。如果有一个类型未知,Unity将报告编译错误。下面,foo将在编译时报错:

#pragma strict
function Start ()
{
var foo = GetComponent(MyScript);
foo.DoSomething();
}

3.缓存组件查找

另一个优化是组件缓存。这种优化需要一些代码并且不是总有必要。但是如果你的代码真的很大,并且你需要尽可能的性能提升,它会是很好的优化。

当你通过GetComponent获取一个组件或一个变量时,Unity必须从游戏物体里找到正确的组件。这时你便能通过一个缓存组件引用到一个私有变量。

将:

function Update () {
transform.Translate(0, 0, 5);
}

转换为:

private var myTransform : Transform;
function Awake () {
myTransform = transform;
}

function Update () {
myTransform.Translate(0, 0, 5);
}

后面的代码运行较快,因为Unity不用在每一帧寻找变换组件。同样,支持脚本组件。你可以使用GetComponent获取组件或其他快捷属性。

4.使用内置数组

内置数组是非常快的。ArrayList或Array类很容易使用,你能轻易添加元件。但是他们有完全不同的速度。 内置数组有固定长度,并且大多时候你会事先知道最大长度然后填充它。内置数组最好的一点是他们直接嵌入结构数据类型在一个紧密的缓存里,而不需要任何额外类型信息或其他开销。因此,在缓存中遍历它是非常容易的,因为每个元素都是对齐的。

private var positions : Vector3[];
function Awake () {
positions = new Vector3[100];
for (var i=0;i<100;i++)
positions[i] = Vector3.zero;
}

5.如果没有必要不要调用函数

最简单,最好的优化是执行最少的工作。如,当一个敌人在远处时,让他处于睡眠状态,大多时候是可行的。直到玩家靠近,可以这样处理:

function Update ()
{
// Early out if the player is too far away.
if (Vector3.Distance(transform.position, target.position) > 100)
return;
perform real work work…
}

这并不是很好的方法,虽然Unity不得不在每一帧访问update函数。更好的方法是禁用这个行为直到玩家靠近。有3中方法做这个:使用OnBecameVisible和OnBecameInvisible。这些调用与渲染系统相联系。一旦摄像机看到物体,OnBecameVisible将被调用,不看他时,OnBecameInvisible被调用。这有时很有用。但是对于AI来讲通常是没有用的,因为你背转敌人,敌人就变成不可用了。

function OnBecameVisible () {
enabled = true;
}

function OnBecameInvisible ()
{
enabled = false;
}

2.使用触发器。一个简单的球形触发器能引发惊人效果。你可以调用OnTriggerEnter/Exit,当进入你想要的作用范围。

function OnTriggerEnter (c : Collider)
{
if (c.CompareTag(“Player”))
enabled = true;
}

function OnTriggerExit (c : Collider)
{
if (c.CompareTag(“Player”))
enabled = false;
}

3.使用协同程序。Update的问题是他在每帧都发生。很可能只需要5秒钟检查一次玩家的距离。这可以节约大量的处理周期。

分类: 游戏开发 标签:

LineRenderer例程注释

2010年11月16日 没有评论
using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    public Color c1 = Color.yellow;   //颜色参数
    public Color c2 = Color.red;
    public int lengthOfLineRenderer = 20;   //线段参数
    void Start() {
        LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();   //添加一个LineRenderer元件到游戏对象中
        lineRenderer.material = new Material(Shader.Find("Particles/Additive"));   //材质设置
        lineRenderer.SetColors(c1, c2);   //设置颜色
        lineRenderer.SetWidth(0.2F, 0.2F);   //设置线宽
        lineRenderer.SetVertexCount(lengthOfLineRenderer);   //设置最大的线段
    }
    void Update() {
        LineRenderer lineRenderer = GetComponent<LineRenderer>();	//获取LineRenderer元件
        int i = 0;
        while (i < lengthOfLineRenderer) {
            Vector3 pos = new Vector3(i * 0.5F, Mathf.Sin(i + Time.time), 0);   //计算绘制点,这里绘制的是一条正弦曲线
            lineRenderer.SetPosition(i, pos);   //绘制曲线
            i++;
        }
    }
}
分类: 游戏开发 标签: