自说自话
她就像一个吟唱诗人,自说自话,也不管你是否在意,或者是否听懂,诉说自己的感受。我不明白,但也会在突然间,明白一点。含义在话之外,要表达的是自说自话这件事的本身所体现的含义。重点在这个状态。
她就像一个吟唱诗人,自说自话,也不管你是否在意,或者是否听懂,诉说自己的感受。我不明白,但也会在突然间,明白一点。含义在话之外,要表达的是自说自话这件事的本身所体现的含义。重点在这个状态。
预设是一个存储在工程视图中可重复利用的游戏物体。它可以被插入到任意数量的场景中,亦可在多次出现在同一场景中。当你添加一个预设到场景中,你就创建了一个它的实例(instance)。所有预设实例都与原始预设相关联,且本质上就是原始预设的一个克隆。
不论在你的工程中存在多少实例,当你对预设作了任何改变后,你将看到这种改变被应用到所有的实例上。不论你的预设是单一的一个游戏物体或者是一组游戏物体,在预设的变换层次中所作的任何改变都将被应用到它的实例上。
创建预设
为了创建预设,你需要建一个新的空预设。这个空预设部不包含任何物体,并且你不能创建它的一个实例。你可将它想象为空的容器,里面空间需要游戏物体数据来填充。
一个新的空预设,它不能被实例化,除非你使用游戏物体来填充它
为了填充预设,你需要利用场景中已创建的游戏物体。下面是精确的步骤。
� 在工程视图中,选择一个你要放置预设的文件夹
� 从主菜单中选择Assets->Create->Prefab,或者从工程视图的上下文菜单中选择
Create->Prefab
� 命名该预设
� 在层次视图(Hierarchy view)中,选择你要放入预设的游戏物体
� 将它们从层次使用中拖放到工程视图中在你执行了上述步骤后,游戏物体和它子物体都将被拷贝到预设中。那么,预设可以在多个实例中被重复使用了。在层次中的原始物体现在已经成了该预设的一个实例。
实例化预设(Prefab Instances)
为了在当前场景中创建一个预设的实例,从工程视图中拖动预设到场景或层次视图中。这将从预设中拷贝所有父物体和所有的子物体。这些游戏物体与预设相连,在工程视图中将使用蓝色的文本来显示它们。
其中三个物体是预设的实例
继承(Inheritance)
继承意味着当预设改变时,这些改变也将被应用到所有与之相连的物体上。例如,如果你添加一个脚本到一个预设,那么所有该预设的实例都将包含该脚本。然而你也可以修改单个实例的属性而不会破坏与预设的联系。一个链接物体检视面板中的所有公有属性都有一个复选框。这个复选框是一个重载标记(override flag)。如果该属性的重载标记被启用,表示该属性将不会受到预设改变的影响。这允许你修改实例物体并使得它们不同于它们的预设,而且又不会破坏它与预设之间的联系。
一个实例物体和非继承
一个实例物体和非继承
预设链接的去除和复位
当你在监视面板中修改一个属性的时候,该属性的重载标记会自动启用。任何对已有属性的改变都不会打断与预设的联系。然而有一些改动将断开它,下面是保持预设的基本规则:
�不能添加一个新的组件到一个实例上
�不能从一个实例上移除一个组件
�不能使用其他游戏物体作为实例的子物体如果你这样做,你将看到一个警告消息出现要求你确认。当一个实例与预设断开后,对预设的修改将不会影响到这个游戏物体。如果你特意或是意外的断了实例的连接,你可以应用你的改变到预设并重新建立该连接。这将使得预设和所有的实例都发生改变。
导入预设
当你放置了一个网格资源到你的资源文件夹中时,Unity 将自动导入该文件并生成一些看起来与预设相似东西。但它们并不是预设,只是简单的资源文件。
注意资源文件图标与预设图标是有点不同的
这个资源在场景中作为一个游戏物体被初始化。可以在该游戏物体上添加或移除组件。然而你不能将任何改变应用到资源自身上因为这需要添加一些数据到该资源物体上!如果要创建需要重用的物体,你应该将资源实例作为预设。
当你已经创建了一个资源实例,可以创建一个新的空预设并拖动游戏物体到该预设上。现在你拥有了一个连接到该物体的标准预设。
下面给出了一些详细的步骤:
� 从工程视图中拖动一个资源文件到场景或层次视图中。
� 修改该资源(例如,添加脚本,子物体,组件等等)
� 创建一个新的空预设。从菜单中选择Assets->Create->Prefab,或者从工程视图的上
下文菜单中选择Create->Prefab
� 从层次视图中拖动该物体到预设上。
也许最后的时刻到了
我没有留下遗嘱
只留下笔,给我的母亲
我并不是英雄
在没有英雄的年代里
我只想做一个人
宁静的地平线
分开了生者和死者的行列
我只能选择天空
决不跪在地上
以显出刽子手们的高大
好阻挡自由的风
从星星的弹空里
将流出血红的黎明
我用的机器是小黑R400,双显卡,独立的是ATI 的HD3470,集成的自然是Intel的X4500.一般情况下,我都用3470.装了Unity3D之后,也确实可以用, 不过在某种情况下,却出现恐怖的情况,只要一运行Unity,就会蓝屏。这个问题困扰了很久。起初以为是SVN的缘故。因为,我重装了系统后,不装SVN,是ok的。不过后来证实不对,因为,我又装了SVN,结果还是可以共存。
因为提醒的蓝屏缘故跟ATI显卡有关系。所以,逐步怀疑到驱动,于是切换了4500,结果原来一开Unity就蓝屏死机的事情,就消失了。看来应该是驱动的缘故,跟显卡应该也没有太大的关系。还要验证这个想法。
在unity中,检测鼠标输入,使用Input.GetMouseDown(n)、Input.GetMouse(n)以及Input.GetMouseUp(n)。GetMouseDown和GetMouseUp检测鼠标按下和松开(这里是一种跳变,),GetMouse在官方文档上说的不是很清楚,其实它可以用来检测一种状态“鼠标按下了”(状态)(不是鼠标移动)。
前段时间我们关闭了Overto公司,这是一家我参与的创业公司。从公司停业便不难看出这是一次失败的创业经历。 因为我们从失败中学到了很多,我认为对创业失败做一个可靠性分析对您应该有用。希望大家不要重蹈我们的覆辙。
没人全职工作
从公司成立初期,我们发现没有一位创始人愿意辞职,来全身心地投入到新公司的运作中。当时,我们以为自己能够在工作之余运营网络服务。在某种程度上,的确如此。 只要服务器和程序没有什么大问题就万事大吉。一有足够的空闲时间,我们就会忙着开发新功能。可是自从那次我们的基础设施出了故障,问题便接踵而至。我们无法抽出时间来解决问题,服务器也因此有多次宕机。这毫无疑问影响了用户体验。由于我们不得不把注意力集中放在解决当前问题,而不是增加新功能上,所以服务/功能开发也受到阻碍。缺少从事维护和错误修正工作的全职人员是这次失败的主要原因。
把握市场脉搏
这是前面提到的原因所引发的部分后果。由于我们把有限时间中的大部分时间放在了服务运营维护上,因而我们也没能抓住瞬息万变的市场脉搏。我们原本需要扩展新领域,以把应用程序提升到另一个层次,可结果我们甚至连当前的开发任务都没完成。整个项目就这样在测试版本中夭折了,而对用户来说项目没有丝毫变化。
缺乏营销技能
处于互联网服务生和死之间的细线是用户。在一开始的时候,用户数量系统地增长。后来我们毫不费力就达到顶峰。这时候是该做些营销推广了。不幸的是,我们之中没有一个人在营销领域内有经验,更糟糕的是,我们都没有足够时间去弥补这一缺失。
商业模式
公司成立之初,我们就没有好好检视我们的商业模式。 并且有几个功能没能达到我们最初设想的效果。 颇有讽刺意味的是,那还不是最麻烦的问题,因为我们已经有了一堆新形势下调整战略的想法。 总之,你应该计划好适时改变最初的商业模式。
错失出售公司的机会
在确定无法长期维持运营之后,我们曾一度有机会将公司转让。 长话短说,一开始我们要价过高,导致谈判失败。 我们过多地考虑自己在它身上的投入,而忽略了它在潜在买主眼中的价值。 不论你为了某件东西付出多少心血,它的最终价值取决于买家的出价。
最终决定 拖延太久
我认为在这点上我们有点感情用事。 毕竟它就像我们的孩子一样,要在马上关闭公司和减少损失之间做出一个决定,的确让我们很纠结。我们一直自欺欺人地想一切都会好转,然而我们已经无力让它再正常运作了。
成立公司的幕后故事
在波兰,成立一家公司需要相当大的努力,不过当初看来,这确实是一个好想法。 所有创始人都是熟人,所以做决策时,不用担心缺乏信任。我们只是想给自己一点动力,使它成为一个真正的公司。而我们始料未及的是,通过展示公司的细节,我们获得大量信誉。而不是让人们觉得,这公司就是由几位学生在假期做的,将来得不到任何支持。虽然让人们看清某一服务后面的公司并不能保证你能生存下去,但至少还是会有人关心你的。
起步之前长时间讨论
在启动项目之前,关于计划做什么和如何做,我们进行了相当长时间的讨论。当然我们没有面面俱到,但是当我拿Overto跟其他创业公司对比之后,我发现,我们在成立初期的考虑很周全。
经验丰富
我们的确有一批精英来运营网络服务。开发、管理和用户支持——我们过去在这些领域上都很有经验。几乎没有什么能难倒我们。在我们应用程序所涉及的任何技术方面,我们不需要去寻求其他专家的帮助。
要在相同地点工作
有一段时间,我们在同一个办公楼工作,这极大有助于决策制定。 如果需要讨论某些重要的事情,我们可以随时见面。 但不久之后,我们分别在不同的地点工作,也正是那时,我们知道了在同一间办公室工作有多重要。
尽管当初为了这个项目我们投资了一些钱,但我认为这不是一种损失。 和我所学到的经验相比,这不算什么。如果我打算再次接触同类项目时,成功的机会会更大。
创业启示录:创业失败报告这个系列包括30多家创业公司的失败案例分析。本文就有由其中一家IT创业公司的CTO所撰写。还是那句老话,成功的故事固然非常鼓舞人心,但我们也可以从失败故事中学到很多。以下是译文。
在互联网泡沫破灭时期,我和朋友一起成立了一家软件公司,我自己担任CTO一职。我们开发了一款知识管理软件,包含了博客、Wiki、文档管理系统、链接管理和技能管理等。
我们在1999年开始创业,当时基本没有其他人做Wiki和博客,我们算很早的。(Moveable Type是成立于2001年)。链接管理系统本质上和后来的Delicious一样。除了那些新特性(至少是在1999年)之外,还有如下三大特性:
我们从VC那得到一笔种子投资资金,我们非常高兴并成功开发我们的程序。在向很多用户展示(程序)后,我们收到了来自大公司的有利反馈。但我们的创业为什么失败了呢?我并没有成为百万富翁?其中有太多的原因,但正如我在《成功商业规则》一文中所说,成功的商业规则很简单:
对企业来说,重中之重的事情就是卖出产品。但事实上,很多创业公司都忘记了,包括我们。左思右想后,我们得出为什么失败的6个原因(由于VC市场崩溃,在我们需要资金的时候,无人能资助一毛钱。这个明显原因除外。):
详细解析:
一、我们没有卖出任何东西(第一部分)
我们之所以没有卖出任何东西,是因为我们没有产品可卖。我们一直在招优秀的工程师,一直等到产品做完。产品完成后,我们才开始销售。我们曾在中途时出售产品,不过是接近1.0的版本。这一举措导致过多注意力放在开发上,没有充分关注产品销售。因为没有一个完成产品,我们认为无法推向客户。我们慢慢学到两件事:
二、我们没有卖出任何东西(第二部分)
我们之所以没有卖出任何东西,是因为我们没有销售人员。真失败!当然了,我们一直在寻找合适的销售人员。商业计划上说:寻找销售的最好方法是组建销售团队。组建团队费时又耗力,并且我们根本没时间和相应资源。如果你想出售产品,找一个销售当合作伙伴,或者一开始就雇佣销售。
三、我们没有卖出任何东西(第三部分)
我们之所以没有卖出任何东西,是因为客户不会买。虽然我们产品很优秀,用户也喜欢,但用户决定购买的时间太漫长了。“(潜在客户公司的)底层 -> 产品经理 -> 整个公司”,我们想通过这样的流程来出售产品。但每每一听说产品是知识管理软件,每位高管都决定放到他的工作日程中,而不是立即决定是否购买。所以,知识管理软件进入命令传达链条中,并没有真正的决策人。
我们在非相关的人身上浪费太多的时间了,我们应当直接找决策人。在我们的销售对象中,有一些大公司,我也确认他们最后会买,但我们创业公司不能等啊。比如,和我们产品对比而言,SAP有时间等待,甚至可以等一年。卖企业软件需要耗费很多时间。
四、市场大门尚未开启
市场大门尚未开启。当时没人听说过博客、wiki和标签。我们不得不向客户解释wiki的好处(每个人都可以编辑!每个人!),博客的好处(每个人都可以发表观点!每个人!)和标签的好处。如果是几年之后,出售博客、wiki和标签平台会更容易。
五、我们过于注重技术
所有的创始人都沉迷于技术。我们使用的是EJB(EJB那时候还不是很成熟),我们把所有的东西输出为XML,然后用XSLT把XML转化为HTML(转化速度还不够快),编写自己的OR映射器 – 多么愚蠢的想法(当时还没有Hibernate),尝试CSS驱动网站(那时候也没用相关知识)。这导致代码重写,这耗费我们大量时间。我们向客户之间的技术讨论也同样费时,讨论结果令人沮丧。
六、我们的商业模式错误
简而言之:我们的商业模式错误。卖出软件最终能收获不少钱,但这需要时间。在没有进账的情况下,我们有前期成本,达成出售交易耗时不短并且一直在烧钱。
更好的模式应当是:做知识管理相关的咨询,并以开源产品开头。
我们的确向某些公司咨询过如何做知识管理和如何使用wiki等。但我们根本没在咨询商花一分钱,因为这是我们销售计划的一部分。关注咨询和收费人群将带来稳定收入。
我后来的确涉入开源,并做了一个开源产品SnipSnap。SnipSnap采用(一小部分)创业点子(仅wiki和博客)。很多人下载并安装了这款软件。我们真正简化SnipSnap的安装,故它才能快速传播。我曾和一家非常大的软件咨询公司的老板讨论过,他告诉我,他们根本用不上wiki,因为它太乱,结构性不好。呵呵,事实上我知道他公司的好几台电脑都安装了SnipSnap。正如其他人现在所做的一样,我们也可以从开源项目开始,然后基于它再提供付费支持和企业级功能。后来有公司付费给我们,要求在SnipSnap中添加新功能,使其和其他公司抗衡。但是在1999年,我们对商业模式的了解,远没有现在这么多。
你能从我的失误中学到什么呢?
在软件管理、产品、商业模式、资金和做CTO这些方面,我已经学到了很多。你能从我的失误中学到什么呢?有一点可以肯定:尽早考虑销售、尽快销售出公司的服务或产品。
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秒钟检查一次玩家的距离。这可以节约大量的处理周期。
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++; } } }