原文地址:Game Objects and Scripts 建立一个时钟Packages: - Unity的功用是模块化的。除了焦点功用之外,还有额外的软件包可以下载并包括在您的项目中。默许情况下,默许3D项目当前包括一些包,您可以在项目窗口中的“包”下看到这些包
Default packages
- 经过切换项目窗口右上角的按钮,可以隐藏这些包,该按钮看起来像一只眼睛,上面有一条破折号。这纯洁是为了削减编辑器中的视觉紊乱,包照旧是项目标一部分。该按钮还显现有几多这样的包。 您可以经过包治理器控制项目中包括哪些包,包治理器可以经过窗口/包治理器菜单项翻开
Package manager, only showing packages in project.
- 这些软件包为Unity增加了额外的功用。例如,Visual Studio编辑器为用于编写代码的Visual Studio编辑器增加了集成。本教程不利用包括的包的功用,所以我把它们都删除了。唯一的破例是Visual Studio编辑器,由于这是我用来编写代码的编辑器。假如您利用分歧的编辑器,您会希望包括它的集成包,假如它存在的话
Color Space: - 现在衬着凡是在线性色彩空间中完成,可是Unity照旧默许利用gamma色彩空间。为了获得最好视觉结果,请挑选“项目设备”窗口的“播放器”种别,翻开“其他设备”面板,并向下转动到其“衬着”部分。确保色彩空间设备为线性。Unity会显现警告,这能够需要很长时候,可是对于一个几近空的项目来说就不会这样了。确认切换
Color space set to linear
- 仅当您针对旧硬件或旧图形API时。OpenGL ES 2.0和WebGL 1.0不支持线性空间,除此之外,gamma在旧的移动装备上能够比线性更快
Creating a Game Object - 我们需要一个游戏工具来暗示时钟。我们将从最简单的游戏工具起头,它是一个空的工具。它可以经过游戏工具/建立空菜单选项来建立。大概,您可以利用“条理”窗口的快速菜单中的“建立空”选项,您可以经过另一种单击方式翻开该窗口,凡是是右键单击或双指导击。这将游戏工具增加参加景中。它是可见的,并立即在“条理”窗口中的SampleScene下被选中,现在用星号标志,暗示它有未保存的变动。您也可以立即变动它的称号或留待今后
Hierarchy with new game object selected.
- 只要游戏工具被选中,检查器窗口就会显现它的具体信息。它的顶部是一个题目,带有工具的称号和一些设置选项。默许情况下,工具处于启用状态,不是静态的,没有标志,而且位于默许图层上。这些设备都没题目,除了它的名字。将其重命名为Clock
Inspector window with clock selected
- 题目下面是游戏工具一切组件的列表。列表顶部总是有一个转换组件,这是我们的时钟今朝所具有的。它控制游戏工具的位置、扭转和缩放。确保一切时钟的位置和扭转值都设备为0。其比例尺应同一为1
- 由于游戏工具是空的,所以它在场景窗口中是不偏见的。但是,操纵工具在游戏工具的位置是可见的,它在天下的中心
Selected with move tool.
- 可以经过编辑器工具栏左上角的按钮来控制哪个操纵工具处于活动状态。这些形式也可以经过Q、W、E、R、T和Y键激活。该组中最右侧的按钮用于启用自界说编辑器工具,这是我们没有的。默许情况下,移开工具处于活动状态
Manipulation mode toolbar.
- 形式按钮旁边还有三个按钮,用于控制操纵工具的放置、偏向和捕捉
Creating the Face of the Clock: - 虽然我们有一个时钟工具,但我们还看不到任何工具。我们将不能不增加三维模子,所以获得一些衬着。Unity包括一些原始工具,我们可以用它们来构建一个简单的时钟。让我们起头经过游戏工具/ 3D工具/圆柱体增加一个圆柱体参加景中。确保它与我们的时钟具有不异的变更值
代表圆柱体的游戏工具
- 这个新工具比一个空的游戏工具多了三个组件。首先,它有一个MeshFilter,其中包括对内置圆柱体网格的援用
MeshFilter component, set to cylinder.
- 第二个是网格衬着器。该组件的目标是确保工具的网格获得衬着。它还决议了用于衬着的材质,即默许材质。该材质也显现在检查器中,位于组件列表下方
MeshRenderer组件,设备为默许材质。
- 第三个是用于3D物理的CapsuleCollider。该工具代表一个圆柱体,但它有一个胶囊碰撞器,由于Unity没有原始的圆柱体碰撞器。我们不需要,可以去掉这个组件。假如你想在时钟上利用物理学,你最好利用MeshCollider组件。组件可以经过右上角的三点下拉菜单删除
- 我们将把圆柱体变平,酿成钟的概况。这是经过削减其标度的Y份量来实现的。下降到0.2。由于圆柱体网格高两个单元,其有用高度变成0.4个单元。我们再做一个大钟,把它刻度的X和Z份量增加到10
Scaled cylinder.
- 将圆柱体工具的称号变动成Face,由于它代表时钟的概况。它只是时钟的一部分,所以我们让它成为时钟工具的子工具。我们经过在条理窗口中把脸拖到时钟上来实现
Face child object.
- 子工具受制于其父工具的变更。这意味着那时钟改变位置时,脸也随着改变。就似乎他们是一个单一的实体。扭转和缩放也是如此。您可以利用它来建立复杂的工具条理
Creating the Clock Periphery - 钟面的外环凡是有标志,有助于显现时候。这就是所谓的时钟外围。让我们用块来暗示12小时制的小时。 经过GameObject / 3D Object / Cube向场景中增加一个立方体工具,将其命名为小时指示器12,并使其成为时钟的子工具。子工具在条理中的顺序无关紧急,您可以将它放在面的上方或下方
Hour indicator child object.
- 将其X比例设备为0.5,Y比例设备为1,Z比例设备为0.1,使其成为一个窄而平的长块。然后将其X位置设为0,Y位置设为4,Z位置设为0.25。这就把它放在了脸的上方来指示12小时。还要移除它的BoxCollider组件
Indicator for hour 12.
- 指示器很丢脸到,由于它和脸的色彩一样。让我们为它建立一个零丁的材质,经过Assets / Create / Material,大概经过加号按钮或项目窗口的高低文菜单。这为我们供给了一个材质资产,它是默许材质的副本。将其称号改成小时指示器
Hour indicator in project window, one and two column layout.
- What is albedo:Albedo是一个拉丁词,意义是红色。它是被白光照亮的工具的色彩
Hours arm.
- 手臂必须围绕时钟中心扭转,但改变其Z扭转会使其围绕自己的中心扭转
Clock arm rotates around its center.
- 发生这类情况是由于扭转是相对于游戏工具的部分位置。为了建立适当的扭转,我们必须引入一个枢轴工具并扭转它。是以,建立一个新的空游戏工具,并使其成为Clock的子工具。您可以经过条理窗口中Clock的高低文菜单间接建立工具。将其命名为小时臂枢轴,并确保其位置和扭转为零,其比例分歧为1。然后使小时臂成为支点的子
Clock arm rotates around the pivot.
终极成果
时钟动画- 我们的钟现在不报时,它总是停在12点。要建造动画,我们必须给它增加一个自界说行为。我们经过建立一个定制的组件范例来实现这一点,它是经过一个剧本来界说的。
C# Script Asset: - 经过Assets / Create / C# Script向项目增加一个新的剧本资本,并将其命名为Clock。C#是用于Unity剧本的编程说话,发音为C-sharp。让我们也立即把它放在一个新的剧本文件夹中,以连结项目标整洁
Scripts folder with Clock script, one and two column layout.
- 当剧本被选中时,检查器将显现其内容。可是要编辑代码,我们必须利用代码编辑器。您可以经过按“翻开”来翻开剧本停止编辑...按钮,大概在“条理结构”窗口中连按它。翻开哪个法式可以经过Unity的偏好设备停止设置
Inspector of C# Clock asset.
Defining a Component Type: - 一旦剧本加载到代码编辑器中,首先删除标准模板代码,由于我们将重新起头建立组件范例。
- 空文件不界说任何内容。它必须包括我们的时钟组件的界说。我们要界说的不是一个组件的单个实例。相反,我们界说了称为Clock的一般类或范例。一旦建立起来,我们便可以在Unity中建立多个这样的组件,虽然在本教程中我们只限于利用一个时钟
- 在C#中,我们经过首先声明我们正在界说一个类,然后是它的名字来界说时钟范例。鄙人面的代码片断中,点窜后的代码有一个黄色的布景,大概假如你利用黑色的网页主题来检察本教程的话,是暗红色的。当我们从一个空文件起头时,它的内容现实上应当酿成class Clock而不是此外,虽然您可以随意在单词之间增加空格和换行符
class Clock
- 你可以把一个类设想成一个蓝图,用来建立驻留在计较机内存中的工具。蓝图界说了这些工具包括什么数据以及它们有什么功用。 类也可以界说不属于工具实例而是属于类自己的数据和功用。这凡是用于供给全局可用的功用。我们将利用其中的一些,但时钟不会有它
- 由于我们不想限制哪个代码可以拜候我们的时钟范例,所以最幸亏它前面加上public access修饰符。
public class Clock
- 此时,我们还没有有用的C#语法。假如你要保存文件并返回到Unity编辑器,那末编译毛病将会记录在控制台窗口中。 我们指出我们正在界说一个范例,所以我们必须现实界说它是什么样的。这是由声明前面的代码块完成的。代码块的鸿沟用花括号暗示。我们临时将其留空,是以只需填写{}
public class Clock {}
- 我们的代码现在有用。保存文件并切换回Unity。Unity编辑器将检测到剧本资本已经改变,并触发重新编译。完成后,挑选我们的剧本。检查员将告诉我们该资产不包括MonoBehaviour剧本
Non-component script.
- 这意味着我们不能利用这个剧本在Unity中建立组件。此时,我们的时钟界说了一个根基的C#工具范例。我们的自界说组件范例必须扩大Unity的MonoBehaviour范例,继续它的数据和功用
- What does mono-behavior mean? 这个想法是,我们可以编写自己的组件来为游戏工具增加自界说行为。行为部分指的就是这个。它只是碰巧利用了英国拼法,这很希奇。mono部分指的是对自界说代码的支持被增加到Unity的方式。它利用了Mono项目,这是。NET框架。是以,MonoBehaviour。这是一个陈腐的名字,由于向后兼容,我们一向相沿它。
- 要将Clock转换成MonoBehaviour的子范例,我们必须变动我们的范例声明,以便它扩大该范例,这是经过在我们的范例名后加上冒号,后跟它扩大的内容来实现的。这使得Clock继续了MonoBehaviour类范例的一切内容
public class Clock : MonoBehaviour {}
- 可是,这将致使编译后出错。编译器报错说找不到MonoBehaviour范例。发生这类情况是由于该范例包括在一个命名空间中,该命名空间是UnityEngine。要拜候它,我们必须利用它的完全限命名UnityEngine.MonoBehaviour
What's a namespace? - 命名空间就像一个网站域,但对于代码来说。就像域可以有子域一样,称号空间可以有子称号空间。最大的区分是它是反过来写的。是以,它将不是com.unity.forum,而是com.unity.forum。称号空间用于构造代码和避免称号抵触。 包括UnityEngine代码的法式集是Unity自带的,你不用去网上零丁取。假如您导入了适当的编辑器集成包,代码编辑器利用的项目文件应当被设备为自动识别它
- 当拜候Unity范例时,总是必须包括UnityEngine前缀是不方便的。荣幸的是,我们可以声明应当自动搜索命名空间来完成C#文件中的范例名。这是经过利用UnityEngine增加来完成的;在文件的顶部。分号是标志语句竣事所必须的
using UnityEngine;
public class Clock : MonoBehaviour {}
- 现在,我们可以在Unity中将自界说组件增加到时钟游戏工具中。这可以经过将剧本资本拖到工具上,大概经过工具检查器底部的“增加组件”按钮来完成
Clock game object with our Clock component.
- 请留意,我的教程中的大大都代码范例都链接到了在线文档。例如,MonoBehaviour是一个链接,带你到Unity的在线剧本API页面
Getting Hold of an Arm: - 为了扭转手臂,时钟工具需要晓得它们。让我们从时针起头。像一切游戏工具一样,它可以经过调剂其变更组件来扭转。是以,我们必须将手臂枢轴的变更组件的常识增加到Clock中。这可以经过在其代码块中增加一个数据字段来实现,界说为一个称号后跟一个分号
- hours pivot这个称号合适于该字段。但是,名字必须是单个单词。老例是将字段名的第一个单词小写,其他一切单词大写,然后将它们粘在一路。所以我们将它命名为hoursPivot
public class Clock : MonoBehaviour {
hoursPivot; }
- 我们还必须声明字段的范例,在本例中是UnityEngine.Transform,它必须写在字段名的前面。
Transform hoursPivot;
- 我们的类现在界说了一个字段,它可以保存对另一个工具的援用,该工具的范例必须是Transform。我们必须确保它包括对小时臂轴心的变更组件的援用。 默许情况下,字段是私有的,这意味着它们只能由属于Clock的代码拜候。可是这个类不晓得我们的Unity场景,所以没有间接的方式将这个字段与正确的工具关联起来
- 我们可以经过将该字段声明为serializable来改变这类情况。这意味着当Unity保存场景时,它应当包括在场景的数据中,这是经过将所稀有据放入一个序列(序列化)并将其写入一个文件来实现的
- 将字段标志为可序列化是经过向其附加属性来完成的,在本例中为SerializeField。它写在方括号内的字段声明的前面,凡是在字段声明的上一行,但也可以放在同一行
[SerializeField] Transform hoursPivot;
- 一旦该字段是可序列化的,Unity将检测到这一点,并将其显现在我们的时钟游戏工具的时钟组件的检查器窗口中
Hours pivot field.
- 要建立正确的毗连,请将小时臂透视从条理结构拖到小时透视字段上。大概,利用字段右侧的圆形按钮,在弹出的列表中搜索枢轴。在这两种情况下,Unity编辑器城市获得小时臂轴心的变更组件,并在我们的字段中援用它
Hours pivot connected.
Knowing all Three Arms: - 我们必须对分秒臂枢轴做一样的工作。是以,利用适当的称号向Clock增加两个可序列化的转换字段
[SerializeField] Transform hoursPivot,Transform minutesPivot,Transform secondsPivot;
Waking Up: - 现在我们已经可以利用臂枢轴,下一步是扭转它们。为此,我们需要告诉Clock履行一些代码。这是经过向类中增加一个代码块(称为方式)来实现的。块必须以一个称号为前缀,这个称号依照老例是大写的。我们将它命名为Awake,这意味着代码应当在组件叫醒时履行。
public class Clock : MonoBehaviour {
[SerializeField] Transform hoursPivot, minutesPivot, secondsPivot;
Awake { } }
- 例如,方式有点像数学函数 f(x)=2x+3。该函数采用一个数字——由变量参数暗示 x—加倍,然后加三。它对一个数字进交运算,其成果也是一个数字。就方式而言,它更像是 f(p)=c其中 p代表输入参数,而且 c代表它履行的任何代码
- 像数学函数一样,方式可以发生成果,但这不是必须的。我们必须声明成果的范例——就像它是一个字段一样——大概编写void来暗示没有成果。在我们的例子中,我们只想履行一些代码而不供给成果值,所以我们利用void。
- 我们也不需要任何输入数据。但是,我们照旧必须将方式的参数界说为圆括号之间的逗号分隔列表。在我们的例子中它只是一个空列表。
void Awake () {}Rotating via Code: - 要扭转手臂,我们必须建立一个新的扭转。我们可以经过为它的 localRotation 属性指定一个新的属性来改变转换的扭转。
- What's a property ? 属性是伪装成字段的方式。它能够是只读的或只写的。C#的老例是大写属性,可是Unity的代码没有这样做。
- 虽然在检查器中,变更组件的扭转是用欧拉角(每轴度数)界说的,但在代码中,我们必须用四元数来完成
- What's a quaternion ? 四元数基于复数,用于暗示3D扭转。虽然比零丁的X、Y和Z扭转角度的组合更难了解,但它们有一些有用的特征。例如,它们不会蒙受万向节锁
void Awake () { Quaternion.Euler; }- 该方式具有用于描写所需扭转的参数。在这类情况下,我们将在方式名后供给一个包括三个参数的逗号分隔列表,一切参数都在圆括号内。我们为X、Y和Z扭转供给三个数字。前两次扭转利用0,Z扭转利用 -30
Quaternion.Euler(0, 0, -30);- 该挪用的成果是一个四元数结构值,包括绕Z轴顺时针扭转30°,与时钟上的1小时相婚配。
- struct—structure:的缩写——是一个蓝图,就像类一样。分歧之处在于,它建立的任何工具都被视为一个简单的值,如整数或色彩,而不是一个工具。它没有认同感。界说你自己的结构和界说一个类是一样的,除了你写struct而不是class。
- 要将此扭转利用到时臂,请指定四元数的成果。Euler到hoursPivots.localRotation,利用=赋值语句
hoursPivot.localRotation = Quaternion.Euler(0, 0, -30);What's the difference between localRotation and rotation ? - localRotation属性暗示由Transform组件零丁描写的扭转,是以它是相对于其父级的扭转。这是你在它的检查器中看到的扭转。相比之下,rotation属性暗示天下空间中的终极扭转,将全部工具条理斟酌在内。假如我们将时钟作为一个整体扭转,设备该属性会发生希奇的成果,由于手臂会疏忽它,由于该属性会抵偿时钟的扭转。
- 现在在编辑器中进入播放形式。您可以经过编辑/播放(指示的键盘快速键)或按下编辑器窗口顶部中心的播放按钮来完成此操纵。Unity会将焦点切换到游戏窗口,衬着场景中主摄像头看到的内容。时钟组件将被叫醒,时钟将被设备为一点钟
Always one o'clock in play mode.
- 假如相机没有聚焦在时钟上,您可以移动它,使时钟变得可见,但请记着,退出播放形式时场景会重置,是以在播放形式下对场景所做的任何变动都不会延续。可是这对于资产来说是不正确的,对它们的改变总是持久的。你也可以在游戏形式下翻收场景窗口,甚最多个场景和游戏窗口。继续之前退出播放形式
Getting the Current Time - 下一步是计较出我们醒来确当前时候。我们可以利用 DateTime 结构来拜候正在运转的装备的系统时候。DateTime不是Unity范例,它位于系统命名空间中。它是的焦点功用的一部分。NET框架,Unity用它来支持剧本。
- DateTime有一个Now属性,该属性天生一个包括当前系统日期和时候的DateTime值。为了检查它能否正确,我们将在叫醒起头时将其记录到控制台。我们可以经过将它传递给调试器来做到这一点。日志方式
using System; using UnityEngine;
public class Clock : MonoBehaviour {
[SerializeField] Transform hoursPivot, minutesPivot, secondsPivot;
void Awake () { Debug.Log(DateTime.Now); hoursPivot.localRotation = Quaternion.Euler(0, 0, -30); } }
- 现在,我们每次进入播放形式时城市记录一个时候戳。您可以在控制台窗口和编辑器窗口底部的状态栏中看到它
Rotating the Arms - 我们正在接近一个工作时钟。让我们再次从小时起头。DateTime有一个小时属性,用于获得DateTime值的小时部分。在当前时候戳上挪用它将会给我们一天中的某个小时。
Debug.Log(DateTime.Now.Hour);- 是以,要让时针显现当前小时,我们必须将30°扭转乘以当前小时。乘法是用星号*字符完成的。我们也不再需要记录当前时候,是以可以删除该语句
hoursPivot.localRotation = Quaternion.Euler(0, 0, -30 * DateTime.Now.Hour);
Currently four o'clock in play mode.
- 为了清楚地表白我们正在将小时转换为度,我们可以界说一个包括转换因子的hours to degrees字段。四元数的角度。欧拉被界说为浮点值,所以我们将利用浮点范例。由于我们已经晓得了这个数字,所以我们可以立行将它作为字段声明的一部分停止赋值。然后乘以字段,而不是Awake中的笔墨-30。
float hoursToDegrees = -30;
[SerializeField] Transform hoursPivot, minutesPivot, secondsPivot;
void Awake () { hoursPivot.localRotation = Quaternion.Euler(0, 0, hoursToDegrees * DateTime.Now.Hour); }
- 假如我们声明一个不带后缀的整数,那末它被假定为一个整数,这是一个分歧的值范例。虽然编译器会自动转换它们,可是让我们经过给它们加上f后缀来明白一切的数字都是float范例
float hoursToDegrees = -30f;
[SerializeField] Transform hoursPivot, minutesPivot, secondsPivot;
void Awake () { hoursPivot.localRotation = Quaternion.Euler(0f, 0f, hoursToDegrees * DateTime.Now.Hour); }
- 每小时的度数总是稳定的。我们可以经过在hoursToDegrees的声明中增加const前缀来实现这一点。这将它酿成一个常数,而不是一个字段
const float hoursToDegrees = -30f;
- 让我们利用DateTime的适当属性对其他两个分支停止一样的处置。分和秒都用负六度的扭转来暗示
const float hoursToDegrees = -30f, minutesToDegrees = -6f, secondsToDegrees = -6f;
[SerializeField] Transform hoursPivot, minutesPivot, secondsPivot;
void Awake () { hoursPivot.localRotation = Quaternion.Euler(0f, 0f, hoursToDegrees * DateTime.Now.Hour); minutesPivot.localRotation = Quaternion.Euler(0f, 0f, minutesToDegrees * DateTime.Now.Minute); secondsPivot.localRotation = Quaternion.Euler(0f, 0f, secondsToDegrees * DateTime.Now.Second); }
Currently 5:16:31.
- 我们利用日期时候。现在三次,检索小时、分钟和秒。每次我们再次遍历属性,这需要一些工作,理论上能够会致使分歧的时候值。为了确保这类情况不会发生,我们应当只检索一次时候。我们可以经过在方式中声明一个变量并给它分派时候,然后利用这个值来实现。让我们把它命名为时候
- What's a variable ? 变量的感化类似于字段,只是它只在方式履行时存在。它属于方式,而不是类
void Awake () { DateTime time = DateTime.Now; hoursPivot.localRotation = Quaternion.Euler(0f, 0f, hoursToDegrees * time.Hour); minutesPivot.localRotation = Quaternion.Euler(0f, 0f, minutesToDegrees * time.Minute); secondsPivot.localRotation = Quaternion.Euler(0f, 0f, secondsToDegrees * time.Second); }
- 在变量的情况下,可以省略范例声明,用var关键字替换它。这可以收缩代码,但只要当变量的范例可以从声明时赋予它的内容中揣度出来时才是能够的。此外,我更喜好只在语句中明白提到范例时才这样做,这里就是这类情况
var time = DateTime.Now;
Animating the Arms: - 当进入播放形式时,我们获得当前时候,但以后时钟连结不动。为了连结时钟与当前时候同步,将我们的Awake方式的称号改成Update。这是另一个特别的事务方式,只要我们处于播放形式,Unity每一帧城市挪用它,而不是只挪用一次
void Update () { var time = DateTime.Now; hoursPivot.localRotation = Quaternion.Euler(0f, 0f, hoursToDegrees * time.Hour); minutesPivot.localRotation = Quaternion.Euler(0f, 0f, minutesToDegrees * time.Minute); secondsPivot.localRotation = Quaternion.Euler(0f, 0f, secondsToDegrees * time.Second); }
What's a frame? - 在游戏形式下,Unity会从主摄像机的角度持续衬着场景。一旦绘制完成,成果就显现给显现器。显现器然后将显现该帧,直到它获得下一帧。在衬着一个新的帧之前,一切的工具城市被更新。所以Unity履历了一系列的更新、衬着、更新、衬着等等。一次衬着场景以后的单个更新步调凡是被以为是单个帧,虽然现实上时候放置要复杂很多
Clock component that can be disabled.
Continuously Rotating: - 我们时钟的指针正确地指示当前的小时、分钟或秒钟。它的行为就像一个数字时钟,离散,但有手臂。典型的时钟有缓慢扭转的指针,供给时候的模拟暗示。让我们改变我们的方式,使我们的时钟成为模拟的。
- 日期时候不包括小数数据。荣幸的是,它确切有一个TimeOfDay属性。这经过其TotalHours、TotalMinutes和TotalSeconds属性为我们供给了一个TimeSpan值,该值包括我们需要的格式的数据。
- 首先从DateTime获得TimeOfDay结构值。现在把它存储在变量中。由于这个语句中没有提到TimeSpan范例,所以我将变量的范例显式化。然后调剂我们用来扭转手臂的属性
Is single precision enough? - 对于大大都游戏来说,是的。当处置很是大的间隔或范围差别时,这就成了一个题目。然后你将不能不利用一些技能,比如传送大概相对于摄像机的衬着来连结活跃地区在天下原点四周。虽然利用双精度可以处理这个题目,但它也会使相关数字的内存巨细加倍,从而致使其他性能题目。游戏引擎凡是利用单精度浮点值,GPU也是如此
- 我们可以经过显式地从double转换为float来处理这个题目。这个进程称为强迫转换,是经过在要转换的值前面的圆括号中写入新范例来完成的。
hoursPivot.localRotation = Quaternion.Euler(0f, 0f, hoursToDegrees * (float)time.TotalHours); minutesPivot.localRotation = Quaternion.Euler(0f, 0f, minutesToDegrees * (float)time.TotalMinutes); secondsPivot.localRotation = Quaternion.Euler(0f, 0f, secondsToDegrees * (float)time.TotalSeconds);
https://www.zhihu.com/video/1577616643064389632 |