日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

unity双击打不开脚本_游戏对象和脚本 (创建一个时钟)

發布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity双击打不开脚本_游戏对象和脚本 (创建一个时钟) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

該文章是一篇譯文,附上原文鏈接

Game Objects and Scripts?catlikecoding.com
  • 使用簡單對象構建一個時鐘
  • 編寫一個C#腳本
  • 轉動時鐘的指針來顯示時間
  • 創建指針動畫
  • 在這個教程中,我們將創建一個簡單的時鐘并編寫一個組件來顯當前時間。你只需要對Unity編輯器有最低限度的了解。如果你已經使用了幾分鐘并知道如何在場景中導航,那么你就可以開始了。

    這個教程假設你使用的是Unity編輯器版本最低為 2017.1.0。

    創建一個時鐘
  • 構建一個簡單時鐘
  • 打開Unity并新建一個3D工程。你不需要任何額外的資源包也不需要任何分析。如果你還沒有定制編輯器,你將得到它的默認窗口布局。

    默認窗口布局

    我使用的是另一種窗口布局,2x3的預設布局,你可以從編輯器右上角的下拉列表中選擇。我通過將項目窗口切換到一個列布局來進一步定制該視圖,這樣更適合它的垂直方向。你可以通過工具欄上方窗口右上角的lock圖標旁邊的下拉列表更改它。我通常在場景窗口中通過Gizmos下拉菜單禁用Show Grid。

    自定義2x3窗口布局

    Ps:為何我的游戲窗口中有黑邊框?

    當使用高分辨率顯示時就會發生這種情況,要使其展開并填充整個游戲窗口,請打開游戲窗口上的aspect-ratio下拉菜單并禁用Low Resolution Aspect Ratios選項。

    禁用 Low resolution aspect ratios

    1.1 創建一個游戲對象

    默認場景包含兩個游戲對象。它們陳列在Hierarchy窗口中,你還可以在Scene窗口中看到它們的圖標。第一個是用于渲染場景的Main Camera。Game窗口就是用這個攝像機渲染的。第二個是照亮場景的Directional Light。

    使用GameObject->Create Empty菜單創建你自己的游戲對象。你還可以通過Hierarchy窗口中上下文菜單來完成。這將向場景中添加一個新對象,你可以立即為其命名。由于我們將要創建一個時鐘,所以命名為Clock。

    擁有一個Clock對象的Hierarchy窗口

    Inspector窗口顯示游戲對象的細節。當我們選中clock對象時,它將包含一個有對象名稱的標題以及一些配置選項。默認情況下,對象是可用的,非靜態的,沒有tag屬于default 層。這些設置對我們是友好的。在下面的列表中,它顯示了游戲對象的所有組件??傆幸粋€Transform組件,這是我們的時鐘對象當前擁有的所有組件。

    Clock對象選中時的Inspector窗口

    Transform組件包含3D空間中的位置,旋轉和縮放信息。確保clock對象的位置和旋轉為0,縮放應當為1.

    Ps:那么2D對象呢?

    當在2D而不是3D中工作時,你可以忽略其中的一維坐標。專門針對2D對象(例如UI元素)通常有一個Rect Transform 組件,這是一個特殊的Transform組件。

    1.2 創建時鐘的表面

    盡管我們已經有了時鐘對象,但是我們還不能看見任何東西。我們將為它添加3D模型以便它們能夠渲染。Unity包含一些基本對象,我們可以用它們來構建一個簡單的時鐘。讓我們通過GameObject->3D Object->Cylinder菜單向場景中添加一個cylinder對象。確保它的Transform組件和Clock對象擁有相同的值。

    一個表示圓柱體的游戲對象

    這個新的對象比一個空對象多了三個組件。首先,它有一個包含對內置圓柱體mesh引用的Mesh Filter。其次是用于3D物理的膠囊碰撞體。第三是Mesh Render。這是一個確保對象mesh能夠被渲染的組件。它還控制用于渲染的材質,這是內置的默認材質,除非你改變它。該材質也顯示在inspector組件列表的下面。

    盡管對象表示一個圓柱體,但是他擁有一個膠囊碰撞體,因為Unity沒有一個原始的圓柱體碰撞器。我們不需要它,所以我們可以移除這個組件。如果你想在你的時鐘上使用物理屬性,你最好使用Mesh Collider組件。組件可以通過右上角的齒輪圖標的下拉菜單移除。

    沒有碰撞體

    為了把圓筒變成時鐘的表面,我們需要壓扁它。這是通過減小Y分量的縮放來實現的。將Y分量的值減小到0.1。由于cylinder mesh的高度是兩個單元,所以它現在的有效高度是0.2個單元。我們需要做一個大時鐘,所以我們把X和Z分量的縮放值增加到10。

    一個縮放過的圓柱體

    由于圓柱體代表時鐘的表面,修改它名字為Face。它是時鐘的一部分,所以讓它成為時鐘對象的子節點。你可以通過將Face拖到Hierarchy窗口中的時鐘對象之上來實現這一點。

    Face成為子節點

    子對象受制于其父對象的變換。這意味著當Clock對象位置改變時,Face對象也會跟著一起改變。就好像它們是一個單一的實體??s放和旋轉也是如此。你可以通過這個特性來創建復雜的對象層次結構。

    1.3 創建時鐘的外圍

    時鐘表面的外圈通常有標記用來幫助指示時鐘顯示的時間。這就是時鐘的外圍。讓我們用塊來表示時鐘的12小時。

    通過GameObject->3D Object->Cube向場景中添加一個立方體。將它的縮放設為(0.5,0.2,1),這樣它就變成了一個狹長的扁平塊。它現在位于時鐘表面的內部。將它的位置設為(0,0.2,4)。將它放在Face的上面和12小時對應的一邊。將它命名為Hour Indicator。

    12小時指示器

    指示器很難看見,因為它和時鐘表面有相同的顏色。讓我們通過Assets->Create->Material或Project窗口中的上下文菜單為它創建一個其他的材質。這為我們提供了一個默認材質副本的材質資源。把它的Albedo值改為深一點的,例如rgb設為73。這就得到了一個深灰色的材質。給它一個適當的名字,例如Clock Dark。

    Dark材質資源和顏色值

    Ps:什么是albedo?

    Albedo是一個拉丁詞,意思為白色。它僅僅是材質的顏色。

    讓Hour Indicator 對象使用這個材質。你可以通過將這個材質拖放到場景或者Hierarchy窗口中的對象上來實現這一點。你也可以把它拖拽到Inspector窗口的底部,或者改變Mesh Render材質數組的第一個元素。

    使用Dark材質的小時指示器

    我們的指示器正確定位到12點,但是如果我們想要表示1點呢?因為有12個小時,一個完整的圓是360°,所以我們必須把指示器繞Y軸旋轉30°。

    旋轉小時指示器,位置不正確

    雖然這給出了正確的方向,但是指示器仍然在12小時的位置。這是因為一個對象的旋轉是相對于它自己的局部原點,也就是它自己的局部坐標。

    我們必須沿著時鐘表面的邊緣移動指示器使其與1小時對齊。我們可以利用對象層次結構來代替自己計算這個位置。首先把指示器的旋轉重置為0.然后創建一個位置和旋轉為0,縮放為1的新空對象。讓指示器成為該對象的子對象。

    臨時父節點

    現在設置這個父節點Y軸旋轉為30°。指示器也會有效的圍繞父節點的原點旋轉,從而精確的達到我們想要的位置。

    正確定位的小時指示器

    使用Ctrl或Cmd D或通過hierarchy窗口中的上下文菜單復制臨時父節點。將復制父節點的Y軸旋轉值在增加30°。持續這樣的操作直到每個小時得到一個指示器。

    十二小時指示器

    我們不再需要臨時父節點。在hierarchy窗口中選擇一個小時指示器并將其拖到時鐘對象上。它現在變為時鐘對象的子節點。當這種情況發生時,Unity改變了指示器的變換,所以它的位置和旋轉在世界空間中并沒有發生變化。為十二個指示器重復這個操作然后刪除所有的臨時父對象。你可以通過crl 或 cmd同時選擇多個對象來加快這一過程。

    時鐘外圍子節點

    Ps:我看到的值是90.00001.這有問題嗎?

    發生這種情況是由于位置、旋轉和縮放組件是使用的浮點數。這些數字的精度有限,有可能與期望的數值有微小的偏差。不用擔心這0.00001的偏差,因為它們是不可感知的。

    1.4 創建時針

    我們可以用同樣的方法來創建時鐘的時針。創建另一個名為Arm的對象,并給它賦予指示器使用的相同材質。設置它的縮放值為(0.3,0.2,2.5),這樣它就比指示器更窄、更長。將它的位置設置為(0,0.2,0.75)這樣它就會位于表盤頂部并指向12點,但是它也會指向相反的方向。這就使當它旋轉時看起來像一個有小平衡重量的時針。

    時針

    Ps:光照的圖標去哪兒了?

    我把光線移開,這樣就不會使得場景變得雜亂。因為它是定向光,所以它的位置并不重要。

    要使Arm圍繞時鐘的中心旋轉,我們為它創建一個父對象。確保它的位置和旋轉值為0并且縮放值為1.因為稍后我們會旋轉這個時針,讓這個父節點成為時鐘的子對象并命名為Hours Arm。Arm對象就成為了Clock對象的孫子節點。

    擁有時針的時鐘層次

    復制時針對象來創建分針和秒針。分針對象應當比時針對象更窄、更長,所以設置他的縮放為(0.2,0.15,4),設置位置為(0,0.375,1)。這樣它就在時針的上面.

    對于Seconds Arms節點,設置縮放為(0.1,0.1,5),位置為(0,0.5,1.25)。為了使它看起來不一樣,我為它創建了一個Clock Red材質并設置它的顏色值為(197,0,0)。

    三根指針

    現在時鐘已經被構建好了。如果你還沒有完成,這是一個很好的保存場景的時機。它將作為資源存儲在項目中。

    保存的場景

    2.讓時鐘動起來

    我們的時鐘現在還不能告訴我們時間。它現在僅僅是Unity渲染的一堆Mesh的對象層次結構。僅此而已。如果有一個默認時鐘組件,我們就可以用它來計時。由于沒有現成的,所以我們需要自己創建。組件通過腳本定義。通過Assets->Create->C# Script創建一個新的腳本資源并命名為Clock。

    時鐘腳本資源

    當選中腳本時,檢查器會顯示它的內容,以及一個在代碼編輯器中打開腳本的按鈕。你也可以雙擊腳本資源來打開它。腳本文件會包含一些默認模板代碼,像以下顯示的一樣。

    using System.Collections; using System.Collections.Generic; using UnityEngine;public class Clock : MonoBehaviour {// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {} }

    這是C#代碼。這是在Unity中使用的腳本編程代碼。為了理解代碼是如何工作的,我們將全部刪除從頭開始。

    Ps:那么JavaScript呢?

    Unity還支持另一種編程語言,通常被稱為JavaScript,但它的實際名稱是UnityScript。Unity2017.1.0仍然支持它,但是創建JavaScript的菜單將在Unity 2017.2.0中移除。預計在那以后將完全取消支持。

    2.1 定義一個組建類型

    一個空文件不是一個合法的腳本。它必須包含時鐘組件的定義。我們不定義組件的單個實例。相反,我們定義一般的類或類型稱為Clock。一旦定義完成,我們就可以在Unity中創建多個這樣的組件。

    在C#中,我們聲明要定義一個類,后面是類名稱,以此來定義時鐘類型。在下面的代碼片段中,改變代碼的背景顏色為黃色。當我們從一個空文件開始,它的內容應該變成class Clock而不是其他的,盡管你可以在單詞之間隨意添加空格和換行。

    class Clock

    Ps:從技術上講,什么是類?

    你可以將類看做一個藍圖,它可用于創建存儲在計算機內存中的對象。藍圖定義了它包含哪些數據以及它所擁有的函數。

    類還可以用于定義不屬于對象而是屬于類本身的數據和功能。這通常用于提供全局可用的功能。

    因為我們不想限制哪些代碼可以訪問時鐘,所以最好在前面加上public訪問修飾符。

    public class Clock

    Ps:什么是類的默認訪問修飾符?

    如果沒有訪問修飾符,將會默認我們編寫的是internal class Clock。這將限制對來自同一程序集的訪問,當使用打包在多個dll文件中的代碼時,這一點就變得很重要。為了確保在任何時候都能正常工作,修改類默認訪問修飾符為public。

    目前我們還沒有合法的C#語法。我們指出我們正在定義一個類型,所以我們必須實際定義它是什么樣的。這是通過聲明后面的代碼塊來完成。代碼塊的邊界用大括號表示,我們現在使用{}讓它空著。

    public class Clock { }

    我們的代碼現在是有效的。保存文件并切回到Unity。Unity編輯器將檢測資源是否發生了變化,并觸發重新編譯。完成之后,選擇我們的腳本,檢查器將給我們指出資源沒有包含MonoBehavior腳本。

    沒有組件的腳本

    這意味著我們不能再Unity中使用這個腳本創建組件。此時,我們只是定義了一個通用的C#對象類型。Unity只能使用Monobehaviour的子類來創建組件。

    Ps:mono-behavior是什么?

    我們可以編寫自己的組件來為游戲對象添加自定義行為。這就是行為所指的意義。它只是碰巧使用了奇怪的英式拼寫。Mono部分指的是將對自定義代碼的支持添加到Unity中的方式。它用到了mono項目,這是一個.net框架實現的多平臺項目。因此,MonoBehaviour。這是一個向后兼容的老名字。

    為了將Clock轉換為MonoBehaviour的子類型,我們必須更改類型聲明,以便它繼承該類型,這是通過冒號實現的。這使得Clock繼承了MonoBehaviour的所有功能。

    public class Clock : MonoBehaviour { }

    然而,這將導致編譯后出現錯誤。編譯器說無法找到MonoBehaviour類型。這是因為該類型包含在UnityEngine命名空間中。要訪問它,我們必須使用它的完全限定名UnityEngine.MonoBehaviour。

    public class Clock : UnityEngine.MonoBehaviour { }

    Ps:什么是命名空間?

    命名空間就類似于網站域名,但是它是作用于代碼的。正如域可以有子域一樣,命名空間也可以有子命名空間。最大的不同是它是反過來寫的。所以http://forum.Unity3d.com將被寫成com.unity3d.forum。代碼是Unity自帶的,不需要上網單獨獲取。命名空間用于組織代碼并防止名稱沖突。

    因為在訪問Unity類型的時候總是使用UnityEngine前綴是不方便的,所以我們沒有顯示的提到任何命名空間時,我們可以告訴編譯器搜索這個命名空間。這是通過添加using UnityEngine在文件頂部完成的。命令需要以分號結束。

    using UnityEngine;public class Clock : MonoBehaviour { }

    現在我們可以在Unity中為我們的時鐘游戲對象添加我們的組件了。這是通過拖拽腳本資源到對象上或者通過對象檢查器下方的Add Component按鈕完成的。

    擁有組件的時鐘對象

    現在已經創建了一個C#對象實例,通過使用我們的Clock類作為模板。它已經被添加到時鐘游戲對象的組件列表中。

    2.2 獲取指針的引用

    為了旋轉這些時鐘指針,Clock對象需要獲取它們。讓我們以時針為例。像所有的游戲對象一樣,它可以通過改變變換組件的旋轉值,來達到旋轉目的。所以我們必須把時針的變換組件加入到Clock中。這可以通過添加一個數據字段在代碼塊中來實現。

    Hours transform是一個合適的名稱。然而,名稱必須是單個單詞。通常是將名稱字段的第一個單詞小寫并將所有其他單詞大寫。然后將它們組合在一起。所以它變成了hoursTransform.

    public class Clock : MonoBehaviour {hoursTransform; }

    Ps:using語句去哪里了?

    它仍然在哪里,我僅僅是沒有展示它。代碼片段將包含足夠的現有代碼,以便您了解更改的上下文。

    我們還必須定義字段的類型,在本例中是UnityEngine.Transform。它必須放在名稱字段的前面。

    Transform hoursTransform;

    我們的類現在定義了一個字段,該字段可以保存對另一個對象的引用。該對象的類型必須是Transform。我們必須確保它持有的是時針轉換組件的引用。

    字段在默認情況下是私有的,這意味著它們只能由Clock類的代碼訪問。但是類并不知道我們的Unity場景。通過修改字段為public,以便任何地方都能修改。

    public Transform hoursTransform;

    Ps:公共字段不是很糟嗎?

    一般來說,在編程時避免創建公共字段是一種共識。但是,在Unity編輯器中需要使用公共字段來連接對象。雖然你可以解決這個問題,但這會使代碼變得不那么直觀。

    一旦字段變為public,它將顯示在inspector窗口中。這是因為inspector自動使組件的所有公共字段變為可編輯。

    時針域

    要建立正確的連接,請將Hours Arm從hierarchy中拖拽到Hours Transform字段。或者,使用該字段右側的圓形按鈕搜索Hours Arm.

    建立連接的Hours Transform

    在拖動或者選擇Hours Arm對象之后,Unity編輯器獲取到它的transform組件,并在我們的字段中放入對它的引用。

    2.3獲取三個指針的引用

    我們對分針和秒針做同樣的操作。所以給Clock添加另外兩個合適名字的字段。

    public Transform hoursTransform; public Transform minutesTransform; public Transform secondsTransform;

    可以使這些字段聲明更簡潔,因為它們共享相同的訪問修飾符和類型。它們可以合并到一個逗號分隔的字段名稱列表中,該列表位于訪問修飾符和類型之后。

    public Transform hoursTransform, minutesTransform, secondsTransform; //public Transform minutesTransform; //public Transform secondsTransform;

    Ps:// 是做什么的?

    //表示注釋。它們后面的所有文本直到行尾都被編譯器忽略。如果需要,它用于添加文本以解釋代碼。我還使用它來表示已刪除的代碼。被刪除的代碼也有一行代碼貫穿其中。

    將編輯器中的其它兩個指針也連接起來。

    連接完成的指針

    2.4 獲取時間

    現在我們能夠在clock中獲取到指針,下一步就是指示出當前的時間。 因此,我們需要告訴Clock執行一些代碼。這是通過向類添加一個代碼塊(稱為方法)來實現的。塊必須有一個通常大寫的名稱作為前綴。我們將它命名為Awake,這意味著應該在組件喚醒的時候執行代碼。

    public class Clock : MonoBehaviour {public Transform hoursTransform, minutesTransform, secondsTransform;Awake {} }

    方法有點類似數學函數。例如f(x)=2x+3.這個函數接受一個數字,將其乘以2,然后再加上3。它操作單一的數字,所以它的結果也是單一的數字。對于一個方法,它更像是f(p)=c,p表示輸入參數,c表示代碼執行。由于這是相當普遍的,那么這樣一個函數的返回結果是什么呢?這一點必須明確提到。在我們的示例中,我們只想執行一些代碼,而不提供返回值。換句話說,該方法的返回結果是空的,我們用void前綴表示。

    void Awake {}

    我們也不需要任何輸入數據。然而,我們仍然需要定義方法的參數,在圓括號之間用逗號分隔。只是在我們的例子中它是空的。

    void Awake() {}

    現在我們有了一個合法的方法,盡管它還沒有做任何事情。像Unity檢測我們的字段一樣,它也檢測這個Awake方法。當一個組件擁有一個Awake方法時,Unity將在組件喚醒時調用該方法。這發生在創建或加載之后。

    Ps:Awake不需要是公開的嗎?

    Awake和其它的一系列方法被Unity認為是特殊的。它將找到它們并在適當的時候調用。無論我們如何聲明它們,我們不應該將這些方法公開。因為它們不打算被除Unity引擎以外的任何東西調用。

    為了測試這是否有效,讓Awake創建一條調試信息。UnityEngine.Debug類包含了公開可用日志方法用于此目的。我們將傳遞給它一個要打印的簡單文本字符串。字符串寫在雙引號之間。同樣,需要分號來標記表達式的末尾。

    void Awake() {Debug.Log("Test"); }

    在Unity編輯器中進入運行模式。將在編輯器底部的狀態欄中看到顯示的測試字符串。還可以在控制臺窗口中看到它。通過Window->Console打開控制臺窗口。當選中某條log文本時,控制臺提供了一些附加信息,比如生成消息的代碼。

    現在我們知道我們的方法是有效的。讓我們來指出調用它的當前時間。UnityEngine命名空間包含一個Time類,這個類有一個Time屬性。我們把它打印出來。

    void Awake() {Debug.Log(Time.time); }

    Ps:什么是屬性?

    屬性是偽裝為字段的方法。它可能是只讀的,也可能是只寫的。通常是大寫屬性,但是Unity沒有這樣做。

    Log顯示的結果總是為0。那是因為Time.time是高告訴我們從我們進入Play模式后所流失的時間。由于Awake方法立即被執行,這時還沒有時間流失。所以這不能告訴我們真實的時間。

    為了獲取我們所使用的計算機的系統時間,我們可以使用DateTime結構體。這不是Unity的類型,我們可以在System命名空間中找到它。它是.net框架的核心功能的一部分,Unity使用它來支持腳本。

    Ps:什么是結構體?

    結構體是一個藍圖,跟類類似。不同之處在于它創建的任何對象都被視為一個簡單的值,比如整數、顏色值,而不是對象。定義自己的結構與定義類的工作原理是一樣的,只是使用struct而不是class。

    DateTime有一個公開可訪問的Now屬性。它提供了一個包含當前系統日期和時間DateTime值。讓我們用Log來打印它。

    using System; using UnityEngine;public class Clock : MonoBehaviour {public Transform hoursTransform, minutesTransform, secondsTransform;void Awake(){Debug.Log(DateTime.Now);} }

    現在,每次進入播放模式時,我們都會得到一個時間戳。

    2.5 旋轉指針

    下一步是基于當前時間旋轉時鐘指針。讓我們再次從時針開始。DateTime有一個Hour屬性,它為我們獲取到DateTime的Hours值。在當前時間戳上調用它將得到當前的小時值。

    void Awake() {Debug.Log(DateTime.Now.Hour); }

    我們可以使用這個小時值來創建旋轉。旋轉以四元素的形式存儲在Unity中。我們可以使用公共可用的Quaternion.Euler方法來創建一個。它以X、Y、Z的標準正則角為參數生成一個合適的四元素。

    void Awake() {// Debug.Log(DateTime.Now.Hour);Quaternion.Euler(0, DateTime.Now.Hour, 0); }

    Ps:什么是四元素?

    四元素是基于復數用于表示3D旋轉的。雖然它比簡單的三維向量更難理解,但它們有一些有用的特征。例如,它們不會受到萬向鎖的影響。

    UnityEngine.Quaternion被用作一個簡單的值。它是一個結構體而不是類。

    三個參數都是實數,在C#用浮點數表示。為了顯示的聲明我們提供的方法支持哪種類型的數字,我們為所有的0加上f后綴。

    Quaternion.Euler(0f, DateTime.Now.Hour, 0f);

    我們的時鐘有十二個小時,每個小時指示器間隔30°。為了與旋轉匹配,我們必須把小時乘以30.

    Quaternion.Euler(0f, DateTime.Now.Hour * 30, 0f);

    為了明確的表示我們是將小時轉換為度數,我們可以為轉換因子定義一個適當的字段。由于它是浮點數所以它的類型是float。由于我們已經知道它的值,所以我們可以在字段定義的時候立即給它賦值。

    private float degreesPerHour = 30f;public Transform hoursTransform, minutesTransform, secondsTransform;void Awake() {Debug.Log(DateTime.Now.Hour);Quaternion.Euler(0f, DateTime.Now.Hour * degreesPerHour, 0f); }

    每小時的度數是不會改變的。我們可以在聲明中添加const前綴來實現這一點。這就把每小時的度數變成了常數。

    private const float degreesPerHour = 30f;

    Ps:常量有什么特殊的地方?

    const關鍵字表示值永遠不會改變,并且不需要成為一個字段。相反,它的值將在編譯期間計算,并替換所有使用到整個常量的地方。這只適用于像數字這樣的基本類型。

    現在我們有一個旋轉,但是沒有對它做任何操作,所以它只是被丟棄了。為了讓它作用到時針上,我們需要把它賦值給時針transform組件的localRotation屬性。

    void Awake() {hoursTransform.localRotation =Quaternion.Euler(0f, DateTime.Now.Hour * degreesPerHour, 0f); }

    時針指向4點

    Ps:什么是局部旋轉?

    localRotation是指變換組件的實際旋轉,獨立于其父節點的旋轉。換句話說,它是對象在局部坐標系中的旋轉。它顯示在檢查器中的變換組件中。所以如果我們要旋轉時鐘根對象,它的子對象也會向我們期望的那樣跟著旋轉。

    還有一個rotation屬性。它指的是轉換組件在世界坐標系中的最終旋轉,會計算上父節點的變換值。如果我們使用這種方法,當我們旋轉時鐘時,子節點就不會跟著調整,因為時鐘的旋轉會被補償。

    當進入play模式時,時針現在只想正確的方向。我們用同樣的方法來處理另外兩個指針。一分和一秒都占6度。

    private const float degreesPerHour = 30f; private const float degreesPerMinute = 6f; private const float degreesPerSecond = 6f;public Transform hoursTransform, minutesTransform, secondsTransform;void Awake() {hoursTransform.localRotation =Quaternion.Euler(0f, DateTime.Now.Hour * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, DateTime.Now.Minute * degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, DateTime.Now.Second * degreesPerSecond, 0f); }

    時鐘顯示16:29:06

    我們使用DateTime.Now三次來獲取時、分、秒。每次我們都要訪問屬性,這需要花費一些時間,理論上會得到不同的時間值。為了確保不會發生這樣的情況,我們應該只訪問一次時間。我們可以通過在方法中聲明一個變量并把當前時間賦值給它,然后用這個時間值來實現這一點。

    Ps:什么是變量?

    變量的作用類似于字段,只是它只在方法執行時存在。它屬于方法,而不屬于類。

    void Awake() {DateTime time = DateTime.Now;hoursTransform.localRotation =Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f); }

    2.6 讓指針動起來

    當我們進入播放模式時,我們獲取到當前時間,但在那之后時鐘仍然保持靜止。要使時鐘與當前時間保持同步,修改我們的Awake方法名稱為Update。只要我們處于播放模式,這個Unity會每幀調用一次這個方法,而不是只調用一次。

    void Update() {DateTime time = DateTime.Now;hoursTransform.localRotation =Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f); }

    注意,我們的組件在檢查器中在它的名稱前多了一個check box。這允許我們禁用組件,從而防止Unity調用它的Update方法。

    擁有check box的組件

    2.7 持續旋轉

    我們時鐘的指針精確的指示當前的小時、分、秒。它的行為像一個數字時鐘,離散但有指針。許多時鐘都有緩慢旋轉的指針來模擬時間的流逝。這兩種方法都可行。所以讓我們通過向組件中添加一個toggle來對其進行配置。

    我們為Clock添加另一個名為continuous的公共字段。它可以是on或off,我們可以聲明為bool類型。

    public Transform hoursTransform, minutesTransform, secondsTransform;public bool continuous;

    Bool值可以是true或false,對應于本例中的on和off。默認情況下是false,所以一旦字段出現在檢查器中,就打開它。

    使用continuous開關

    我們現在支持兩種方式。為此,復制我們的Update方法,并將它們重命名為UpdateContinuous和UpdateDiscrete。

    void UpdateContinuous() {DateTime time = DateTime.Now;hoursTransform.localRotation =Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f); }void UpdateDiscrect() {DateTime time = DateTime.Now;hoursTransform.localRotation =Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f); }

    創建一個新的Update方法。如果continuous為true,它應當調用UpdateContinuous。這個可以通過if語句來完成。If關鍵字后面跟著一個圓括號內的表達式。如果表達式結果為true,則執行它后面的代碼塊。否則,代碼塊將被跳過。

    private void Update() {if (continuous){UpdateContinuous();} }

    Ps:新的Update方法必須在哪兒定義?

    在Clock類內部。它相對于另外兩個方法的位置無關緊要。可以在它們后面或前面。

    還可以添加另一個代碼塊,在表達式為false時執行。這是通過關鍵字else完成的。我們可以使用它來調用UpdateDiscrete方法。

    private void Update() {if (continuous){UpdateContinuous();}else{UpdateDiscrect();} }

    現在我們可以在兩種方法之間切換,但是它們仍然做同樣的事情。我們必須調整UpdateContinuous,這樣它就會顯示小數的小時、分鐘和秒。不幸的是DateTime不包含小數數據。幸運的是,它卻又一個TimeOfDay屬性。這將為我們提供一個TimeSpan值,其中包含我們所需要的格式的數據。特別是TotalHours,TotalMinutes,TotalSeconds。

    private void UpdateContinuous() {TimeSpan time = DateTime.Now.TimeOfDay;hoursTransform.localRotation =Quaternion.Euler(0f, time.TotalHours * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, time.TotalMinutes* degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, time.TotalSeconds * degreesPerSecond, 0f); }

    這將導致編譯錯誤,由于新值具有錯誤的數據類型。它們被定義為雙精度浮點值,稱為double。這些值比浮點值擁有更高的精度, 但是Unity代碼只適用于單精度浮點值。

    Ps:單精度值是否夠用?

    對于大多數游戲來說已經夠用。當處理非常大的距離或尺度差異時,這將導致一些其他問題。然后你將不得不使用類似傳送這樣的技巧來保持當前游戲區域接近世界起點。雖然使用雙精度可以解決這個問題,但是它也會使所涉及的數字大小加倍,從而導致一些其他的性能問題。因此,大多數游戲引擎都使用浮點數。

    我們可以通過轉換double為float解決這個問題。這只是簡單的丟棄了我們不需要的精確數據。這個過程被稱為強制轉換。通過在要轉換的值前面的圓括號內寫入新類型完成。

    private void UpdateContinuous() {TimeSpan time = DateTime.Now.TimeOfDay;hoursTransform.localRotation =Quaternion.Euler(0f, (float)time.TotalHours * degreesPerHour, 0f);minutesTransform.localRotation =Quaternion.Euler(0f, (float)time.TotalMinutes* degreesPerMinute, 0f);secondsTransform.localRotation =Quaternion.Euler(0f, (float)time.TotalSeconds * degreesPerSecond, 0f); }

    現在您已經了解了Unity中創建對象和編寫腳本的基本原理。

    總結

    以上是生活随笔為你收集整理的unity双击打不开脚本_游戏对象和脚本 (创建一个时钟)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。